diff --git a/src/client/zun/index.js b/src/client/zun/index.js index a9c9ee47..e8464ebd 100644 --- a/src/client/zun/index.js +++ b/src/client/zun/index.js @@ -66,6 +66,11 @@ export class ZunClient extends Base { }, ], }, + { + name: 'hosts', + key: 'hosts', + responseKey: 'host', + }, ]; } } diff --git a/src/layouts/admin-menu.jsx b/src/layouts/admin-menu.jsx index fb1813a2..66a25a26 100644 --- a/src/layouts/admin-menu.jsx +++ b/src/layouts/admin-menu.jsx @@ -813,6 +813,22 @@ const renderMenu = (t) => { }, ], }, + { + path: '/container/hosts-admin', + name: t('Hosts'), + key: 'zunHostsAdmin', + endpoints: 'zun', + level: 1, + children: [ + { + path: /^\/container\/hosts-admin\/detail\/.[^/]+$/, + name: t('Hosts Detail'), + key: 'zuHostsDetailAdmin', + level: 2, + routePath: '/container/hosts-admin/detail/:id', + }, + ], + }, ], }, ]; diff --git a/src/locales/en.json b/src/locales/en.json index f1b7c365..a32e871b 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -272,6 +272,7 @@ "COE": "COE", "COE Version": "COE Version", "CPU": "CPU", + "CPU (Core)": "CPU (Core)", "CPU Arch": "CPU Arch", "CPU Cores": "CPU Cores", "CPU Policy": "CPU Policy", @@ -404,6 +405,7 @@ "Configuration Group Name": "Configuration Group Name", "Configuration Groups": "Configuration Groups", "Configuration Update": "Configuration Update", + "Configured Disk (GiB)": "Configured Disk (GiB)", "Configured Memory (GiB)": "Configured Memory (GiB)", "Confirm": "Confirm", "Confirm Config": "Confirm Config", @@ -435,6 +437,7 @@ "Container Stopping": "Container Stopping", "Container Version": "Container Version", "Containers": "Containers", + "Containers Info": "Containers Info", "Content": "Content", "Content Type": "Content Type", "Control Location": "Control Location", @@ -1035,6 +1038,7 @@ "Host Routes Format Error(e.g. ::0a38:01fe/24,::0a38:01fe)": "Host Routes Format Error(e.g. ::0a38:01fe/24,::0a38:01fe)", "Hostname": "Hostname", "Hosts": "Hosts", + "Hosts Detail": "Hosts Detail", "Hungary": "Hungary", "Hypervisor Detail": "Hypervisor Detail", "Hypervisors": "Hypervisors", @@ -1251,6 +1255,7 @@ "Kenya": "Kenya", "Kernel ID": "Kernel ID", "Kernel Image": "Kernel Image", + "Kernel Version": "Kernel Version", "Key": "Key", "Key Pair": "Key Pair", "Key Pairs": "Key Pairs", @@ -1544,6 +1549,7 @@ "OS": "OS", "OS Admin": "OS Admin", "OS Disk": "OS Disk", + "OS Type": "OS Type", "OS Version": "OS Version", "OSDs": "OSDs", "OSPF": "OSPF", @@ -2305,6 +2311,7 @@ "Total Capacity": "Total Capacity", "Total Connections": "Total Connections", "Total Consumers": "Total Consumers", + "Total Containers": "Total Containers", "Total Exchanges": "Total Exchanges", "Total IPs": "Total IPs", "Total Queues": "Total Queues", @@ -2650,6 +2657,7 @@ "floating ips": "floating ips", "heat services": "heat services", "host aggregates": "host aggregates", + "hosts": "hosts", "hypervisor": "hypervisor", "image": "image", "images": "images", diff --git a/src/locales/zh.json b/src/locales/zh.json index 4367439c..b3353219 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -272,6 +272,7 @@ "COE": "COE", "COE Version": "COE版本", "CPU": "CPU", + "CPU (Core)": "CPU (核)", "CPU Arch": "CPU架构", "CPU Cores": "CPU核数", "CPU Policy": "CPU策略", @@ -404,6 +405,7 @@ "Configuration Group Name": "配置组名称", "Configuration Groups": "配置组", "Configuration Update": "配置变更", + "Configured Disk (GiB)": "已分配磁盘(GiB)", "Configured Memory (GiB)": "已分配内存(GiB)", "Confirm": "确定", "Confirm Config": "确认配置", @@ -435,6 +437,7 @@ "Container Stopping": "容器关闭中", "Container Version": "容器版本", "Containers": "容器", + "Containers Info": "容器信息", "Content": "内容", "Content Type": "内容类型", "Control Location": "控制端", @@ -1035,6 +1038,7 @@ "Host Routes Format Error(e.g. ::0a38:01fe/24,::0a38:01fe)": "无效:主机路由格式错误(例如: ::0a38:01fe/24,::0a38:01fe))", "Hostname": "主机名称", "Hosts": "主机", + "Hosts Detail": "主机详情", "Hungary": "匈牙利", "Hypervisor Detail": "虚拟机管理器详情", "Hypervisors": "虚拟机管理器", @@ -1251,6 +1255,7 @@ "Kenya": "肯尼亚", "Kernel ID": "内核ID", "Kernel Image": "Kernel镜像", + "Kernel Version": "内核版本", "Key": "键", "Key Pair": "密钥", "Key Pairs": "密钥", @@ -1544,6 +1549,7 @@ "OS": "操作系统", "OS Admin": "镜像默认用户", "OS Disk": "系统盘", + "OS Type": "操作系统类型", "OS Version": "系统版本", "OSDs": "", "OSPF": "", @@ -2305,6 +2311,7 @@ "Total Capacity": "总容量(GB)", "Total Connections": "", "Total Consumers": "", + "Total Containers": "容器总数", "Total Exchanges": "", "Total IPs": "所有IP", "Total Queues": "", @@ -2650,6 +2657,7 @@ "floating ips": "浮动IP", "heat services": "编排服务", "host aggregates": "主机集合", + "hosts": "主机", "hypervisor": "虚拟机管理器", "image": "镜像", "images": "镜像", diff --git a/src/pages/container-service/containers/Hosts/Detail/BaseDetail.jsx b/src/pages/container-service/containers/Hosts/Detail/BaseDetail.jsx new file mode 100644 index 00000000..8a2ac0bc --- /dev/null +++ b/src/pages/container-service/containers/Hosts/Detail/BaseDetail.jsx @@ -0,0 +1,90 @@ +// Copyright 2021 99cloud +// +// 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. + +import Base from 'containers/BaseDetail'; +import { inject, observer } from 'mobx-react'; + +export class BaseDetail extends Base { + get leftCards() { + const cards = [this.containersInfoCard, this.systemInfoCard]; + return cards; + } + + get rightCards() { + const cards = [this.miscellaneousCard]; + return cards; + } + + get containersInfoCard() { + const options = [ + { + label: t('Total Containers'), + dataIndex: 'total_containers', + }, + ]; + + return { + title: t('Containers Info'), + options, + }; + } + + get systemInfoCard() { + const options = [ + { + label: t('Architecture'), + dataIndex: 'architecture', + }, + { + label: t('Kernel Version'), + dataIndex: 'kernel_version', + }, + { + label: t('OS'), + dataIndex: 'os', + }, + { + label: t('OS Type'), + dataIndex: 'os_type', + }, + ]; + + return { + title: t('System Info'), + options, + }; + } + + get miscellaneousCard() { + const options = [ + { + label: t('Labels'), + dataIndex: 'labels', + render: (value = {}) => JSON.stringify(value), + }, + { + label: t('Links'), + dataIndex: 'links', + render: (value = []) => JSON.stringify(value), + }, + ]; + + return { + title: t('Miscellaneous'), + options, + }; + } +} + +export default inject('rootStore')(observer(BaseDetail)); diff --git a/src/pages/container-service/containers/Hosts/Detail/index.jsx b/src/pages/container-service/containers/Hosts/Detail/index.jsx new file mode 100644 index 00000000..32b51980 --- /dev/null +++ b/src/pages/container-service/containers/Hosts/Detail/index.jsx @@ -0,0 +1,71 @@ +// 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. + +import { inject, observer } from 'mobx-react'; +import Base from 'containers/TabDetail'; +import globalHostsStore from 'src/stores/zun/hosts'; +import BaseDetail from './BaseDetail'; + +export class HostsDetail extends Base { + init() { + this.store = globalHostsStore; + } + + get name() { + return t('Hosts Detail'); + } + + get listUrl() { + return this.getRoutePath('zunHosts'); + } + + get policy() { + return 'container:host:get'; + } + + get detailInfos() { + return [ + { + title: t('Hostname'), + dataIndex: 'name', + }, + { + title: t('CPU (Core)'), + dataIndex: 'cpu_percent', + render: (value, record) => `${record.cpu_used} / ${record.cpus}`, + }, + { + title: t('Configured Memory (GiB)'), + dataIndex: 'memory_percent', + render: (value, record) => + `${record.mem_used_gb} / ${record.mem_total_gb}`, + }, + { + title: t('Configured Disk (GiB)'), + dataIndex: 'disk_percent', + render: (value, record) => `${record.disk_used} / ${record.disk_total}`, + }, + ]; + } + + get tabs() { + return [ + { + title: t('BaseDetail'), + key: 'BaseDetail', + component: BaseDetail, + }, + ]; + } +} + +export default inject('rootStore')(observer(HostsDetail)); diff --git a/src/pages/container-service/containers/Hosts/index.jsx b/src/pages/container-service/containers/Hosts/index.jsx new file mode 100644 index 00000000..66a5c458 --- /dev/null +++ b/src/pages/container-service/containers/Hosts/index.jsx @@ -0,0 +1,96 @@ +// Copyright 2021 99cloud +// +// 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. + +import React from 'react'; +import Base from 'containers/List'; +import { inject, observer } from 'mobx-react'; +import globalHostsStore from 'src/stores/zun/hosts'; +import Progress from 'components/Progress'; + +export class Hosts extends Base { + init() { + this.store = globalHostsStore; + this.downloadStore = globalHostsStore; + } + + get name() { + return t('hosts'); + } + + get policy() { + return 'container:host:get_all'; + } + + getColumns = () => [ + { + title: t('ID/Name'), + dataIndex: 'name', + routeName: 'zuHostsDetailAdmin', + }, + { + title: t('Architecture'), + dataIndex: 'architecture', + isHideable: true, + }, + { + title: t('Total Containers'), + dataIndex: 'total_containers', + isHideable: true, + }, + { + title: t('CPU (Core)'), + dataIndex: 'cpu_percent', + render: (value, record) => ( + + ), + width: 180, + stringify: (value, record) => + `${value}% (${t('Used')}: ${record.cpu_used} / ${t('Total')}: ${ + record.cpus + })`, + }, + { + title: t('Configured Memory (GiB)'), + dataIndex: 'memory_percent', + render: (value, record) => ( + + ), + width: 180, + stringify: (value, record) => + `${value}% (${t('Used')}: ${record.mem_used_gb} / ${t('Total')}: ${ + record.mem_total_gb + })`, + }, + { + title: t('Configured Disk (GiB)'), + dataIndex: 'disk_percent', + render: (value, record) => ( + + ), + width: 180, + stringify: (value, record) => + `${value}% (${t('Used')}: ${record.disk_used} / ${t('Total')}: ${ + record.disk_total + })`, + }, + ]; +} + +export default inject('rootStore')(observer(Hosts)); diff --git a/src/pages/container-service/routes/index.js b/src/pages/container-service/routes/index.js index cf50a7f5..c2cb0eda 100644 --- a/src/pages/container-service/routes/index.js +++ b/src/pages/container-service/routes/index.js @@ -16,8 +16,10 @@ import BaseLayout from 'layouts/Basic'; import E404 from 'pages/base/containers/404'; import Containers from '../containers/Containers'; import Capsules from '../containers/Capsules'; +import Hosts from '../containers/Hosts'; import ContainersDetail from '../containers/Containers/Detail'; import CapsulesDetail from '../containers/Capsules/Detail'; +import HostsDetail from '../containers/Hosts/Detail'; import StepCreateContainer from '../containers/Containers/actions/StepCreate'; const PATH = '/container'; @@ -54,6 +56,16 @@ export default [ component: CapsulesDetail, exact: true, }, + { + path: `${PATH}/hosts-admin`, + component: Hosts, + exact: true, + }, + { + path: `${PATH}/hosts-admin/detail/:id`, + component: HostsDetail, + exact: true, + }, // All { path: '*', component: E404 }, ], diff --git a/src/stores/zun/hosts.js b/src/stores/zun/hosts.js new file mode 100644 index 00000000..ede0e657 --- /dev/null +++ b/src/stores/zun/hosts.js @@ -0,0 +1,42 @@ +// Copyright 2021 99cloud +// +// 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. + +import Base from 'stores/base'; +import client from 'client'; +import { getGiBValue } from 'utils'; + +export class HostsStore extends Base { + get client() { + return client.zun.hosts; + } + + mapper(data) { + const { mem_total, mem_used, cpus, cpu_used, disk_total, disk_used } = data; + return { + ...data, + id: data.uuid, + name: data.hostname, + cpu_percent: cpus ? ((cpu_used / cpus) * 100).toFixed(2) : 0, + memory_percent: mem_total ? ((mem_used / mem_total) * 100).toFixed(2) : 0, + mem_total_gb: getGiBValue(mem_total), + mem_used_gb: getGiBValue(mem_used), + disk_percent: disk_total + ? ((disk_used / disk_total) * 100).toFixed(2) + : 0, + }; + } +} + +const globalHostsStore = new HostsStore(); +export default globalHostsStore;