refactor: 优化计算节点自测与评分脚本的提示信息
This commit is contained in:
1 parent
b91d121a42
commit
711a933355
1 file changed
+34
-36
+34
-36
@@ -34,7 +34,7 @@ banner() {
|
|||||||
}
|
}
|
||||||
section() {
|
section() {
|
||||||
TASK_CNT=$((TASK_CNT+1))
|
TASK_CNT=$((TASK_CNT+1))
|
||||||
printf '%b[➜] %d. 检查任务:%s%b\n' "$BLUE" "$TASK_CNT" "$1" "$NC"
|
printf '%b[➜] %d. %s%b\n' "$BLUE" "$TASK_CNT" "$1" "$NC"
|
||||||
}
|
}
|
||||||
error() {
|
error() {
|
||||||
printf '%b[✘ 失败] %s%b\n' "$RED" "$1" "$NC"
|
printf '%b[✘ 失败] %s%b\n' "$RED" "$1" "$NC"
|
||||||
@@ -47,28 +47,26 @@ check() {
|
|||||||
TOTAL=$((TOTAL+points))
|
TOTAL=$((TOTAL+points))
|
||||||
if "$@" >/dev/null 2>&1; then
|
if "$@" >/dev/null 2>&1; then
|
||||||
SCORE=$((SCORE+points)); PASS_CNT=$((PASS_CNT+1))
|
SCORE=$((SCORE+points)); PASS_CNT=$((PASS_CNT+1))
|
||||||
printf '%b[✔ 通过] %s(得 %d 分)%b\n' "$GREEN" "$success_message" "$points" "$NC"
|
printf '%b[✔ 通过] %s%b\n' "$GREEN" "$success_message" "$NC"
|
||||||
else
|
else
|
||||||
FAIL_CNT=$((FAIL_CNT+1))
|
FAIL_CNT=$((FAIL_CNT+1))
|
||||||
printf '%b[✘ 失败] %s(扣 %d 分)%b\n' "$RED" "$failure_message" "$points" "$NC"
|
printf '%b[✘ 失败] %s%b\n' "$RED" "$failure_message" "$NC"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
finish() {
|
finish() {
|
||||||
printf '\n'
|
printf '\n'
|
||||||
separator
|
separator
|
||||||
printf '实验自测检查完毕!通过项: %b%d%b,失败项: %b%d%b\n' "$GREEN" "$PASS_CNT" "$NC" "$RED" "$FAIL_CNT" "$NC"
|
printf '%b总成绩:%d/100 分%b | 通过: %b%d%b | 失败: %b%d%b\n' "$YELLOW" "$SCORE" "$NC" "$GREEN" "$PASS_CNT" "$NC" "$RED" "$FAIL_CNT" "$NC"
|
||||||
printf '%b总成绩:%d/100 分%b\n' "$YELLOW" "$SCORE" "$NC"
|
|
||||||
if [ "$TOTAL" -ne 100 ]; then
|
if [ "$TOTAL" -ne 100 ]; then
|
||||||
error "评分项总分异常:$TOTAL,请联系教师检查脚本。"
|
error "评分项总分异常:$TOTAL,请联系教师检查脚本。"
|
||||||
separator
|
separator
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
if [ "$FAIL_CNT" -eq 0 ]; then
|
if [ "$FAIL_CNT" -eq 0 ]; then
|
||||||
printf '%b所有检查项均已通过,实验自测完成!%b\n' "$GREEN" "$NC"
|
|
||||||
separator
|
separator
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
printf '%b你有 %d 处检查未通过,请根据上方红字提示核对实验步骤并修正!%b\n' "$RED" "$FAIL_CNT" "$NC"
|
printf '%b请按红字提示修正。%b\n' "$RED" "$NC"
|
||||||
separator
|
separator
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
@@ -115,7 +113,7 @@ ini_value() {
|
|||||||
enabled_service() { [ "$(timeout 10 systemctl is-enabled "$1" 2>/dev/null)" = enabled ]; }
|
enabled_service() { [ "$(timeout 10 systemctl is-enabled "$1" 2>/dev/null)" = enabled ]; }
|
||||||
active_service() { timeout 10 systemctl is-active --quiet "$1"; }
|
active_service() { timeout 10 systemctl is-active --quiet "$1"; }
|
||||||
|
|
||||||
banner 'OpenStack 计算节点实验自测与自动化评分脚本'
|
banner 'OpenStack 计算节点评分'
|
||||||
preflight
|
preflight
|
||||||
CONF=/etc/nova/nova.conf
|
CONF=/etc/nova/nova.conf
|
||||||
# 自动检测失败(例如 hosts 冲突)仍继续评分,让解析项正常扣分。
|
# 自动检测失败(例如 hosts 冲突)仍继续评分,让解析项正常扣分。
|
||||||
@@ -130,7 +128,7 @@ if ! valid_ipv4 "$CONTROLLER_IP"; then error '控制节点 IP 参数或 hosts
|
|||||||
if [ -n "${CHECK_COMPUTE_IP:-}" ] && ! valid_ipv4 "$CHECK_COMPUTE_IP"; then error 'CHECK_COMPUTE_IP 无效。未评分。'; exit 2; fi
|
if [ -n "${CHECK_COMPUTE_IP:-}" ] && ! valid_ipv4 "$CHECK_COMPUTE_IP"; then error 'CHECK_COMPUTE_IP 无效。未评分。'; exit 2; fi
|
||||||
case "$REPO_BASE" in http://*|https://*) ;; *) error '软件源根 URL 必须使用 http(s)。未评分。'; exit 2;; esac
|
case "$REPO_BASE" in http://*|https://*) ;; *) error '软件源根 URL 必须使用 http(s)。未评分。'; exit 2;; esac
|
||||||
|
|
||||||
section '基础安全设置(8分)'
|
section '安全设置(8分)'
|
||||||
firewall_stopped() { [ "$(timeout 10 systemctl is-active firewalld 2>/dev/null)" = inactive ]; }
|
firewall_stopped() { [ "$(timeout 10 systemctl is-active firewalld 2>/dev/null)" = inactive ]; }
|
||||||
firewall_disabled() {
|
firewall_disabled() {
|
||||||
local state
|
local state
|
||||||
@@ -144,12 +142,12 @@ selinux_persistent() {
|
|||||||
v=$0; sub(/^[^=]*=/,"",v); sub(/[[:space:]]*#.*/,"",v); gsub(/[[:space:]"\047]/,"",v)
|
v=$0; sub(/^[^=]*=/,"",v); sub(/[[:space:]]*#.*/,"",v); gsub(/[[:space:]"\047]/,"",v)
|
||||||
} END {exit (v!="disabled")}' /etc/selinux/config
|
} END {exit (v!="disabled")}' /etc/selinux/config
|
||||||
}
|
}
|
||||||
check 2 'firewalld 防火墙已停止' 'firewalld 应停止,查询失败也不得分' firewall_stopped
|
check 2 'firewalld 已停止' 'firewalld 未停止或查询失败' firewall_stopped
|
||||||
check 2 'firewalld 防火墙已禁止开机启动' 'firewalld 应禁止开机启动' firewall_disabled
|
check 2 'firewalld 自启已禁用' 'firewalld 自启未禁用' firewall_disabled
|
||||||
check 2 'SELinux 当前为 Disabled 或 Permissive' 'SELinux 当前应为 Disabled 或 Permissive' selinux_runtime
|
check 2 'SELinux 非强制模式' 'SELinux 仍强制执行或查询失败' selinux_runtime
|
||||||
check 2 'SELinux 持久配置为 disabled' '/etc/selinux/config 应设置 SELINUX=disabled' selinux_persistent
|
check 2 'SELinux 永久禁用' 'SELinux 未永久禁用' selinux_persistent
|
||||||
|
|
||||||
section '主机名、解析与网络(12分)'
|
section '主机与网络(12分)'
|
||||||
hostname_ok() { [ "$(hostname)" = compute ] && [ "$(tr -d '[:space:]' < /etc/hostname)" = compute ]; }
|
hostname_ok() { [ "$(hostname)" = compute ] && [ "$(tr -d '[:space:]' < /etc/hostname)" = compute ]; }
|
||||||
controller_mapping() { [ "$(hosts_ip controller)" = "$CONTROLLER_IP" ]; }
|
controller_mapping() { [ "$(hosts_ip controller)" = "$CONTROLLER_IP" ]; }
|
||||||
compute_mapping() {
|
compute_mapping() {
|
||||||
@@ -159,14 +157,14 @@ compute_mapping() {
|
|||||||
}
|
}
|
||||||
both_resolve() { resolved_as controller "$CONTROLLER_IP" && resolved_as compute "$COMPUTE_IP"; }
|
both_resolve() { resolved_as controller "$CONTROLLER_IP" && resolved_as compute "$COMPUTE_IP"; }
|
||||||
localhost_preserved() { awk '{sub(/#.*/,""); if($1=="127.0.0.1")for(i=2;i<=NF;i++)if($i=="localhost")found=1} END{exit !found}' /etc/hosts; }
|
localhost_preserved() { awk '{sub(/#.*/,""); if($1=="127.0.0.1")for(i=2;i<=NF;i++)if($i=="localhost")found=1} END{exit !found}' /etc/hosts; }
|
||||||
check 2 '运行中及持久主机名均为 compute' '运行中及持久主机名都应为 compute' hostname_ok
|
check 2 '主机名 compute' '主机名应为 compute' hostname_ok
|
||||||
check 2 'controller 的 hosts 映射唯一,控制节点 IP 配置正确' '/etc/hosts 中 controller 应唯一映射到控制节点 IP' controller_mapping
|
check 2 'controller hosts 映射' 'controller hosts 映射缺失或冲突' controller_mapping
|
||||||
check 2 'compute 的 hosts 映射唯一,且指向本机管理 IPv4' '/etc/hosts 中 compute 应唯一映射到本机管理 IPv4' compute_mapping
|
check 2 'compute hosts 映射' 'compute hosts 应指向本机管理 IP' compute_mapping
|
||||||
check 2 'controller 和 compute 的系统解析与 hosts 配置一致' 'controller/compute 的系统解析应与 hosts 一致' both_resolve
|
check 2 '主机名解析' '主机名解析与 hosts 不一致' both_resolve
|
||||||
check 2 'hosts 中保留了 localhost 的 IPv4 映射' '新增 hosts 条目时应保留 localhost 的 IPv4 映射' localhost_preserved
|
check 2 'localhost 映射保留' 'localhost 映射缺失' localhost_preserved
|
||||||
check 2 '可通过主机名 ping 通 controller' '应能通过主机名 ping 通 controller' timeout 8 ping -4 -c 2 -W 2 controller
|
check 2 'ping controller' 'ping controller 不通' timeout 8 ping -4 -c 2 -W 2 controller
|
||||||
|
|
||||||
section '软件源配置、连通性与缓存(15分)'
|
section '软件源(15分)'
|
||||||
# 每个仓库分别评价配置、repomd 索引、已有缓存,各1分。
|
# 每个仓库分别评价配置、repomd 索引、已有缓存,各1分。
|
||||||
shopt -s nullglob
|
shopt -s nullglob
|
||||||
REPOS=(/etc/yum.repos.d/*.repo)
|
REPOS=(/etc/yum.repos.d/*.repo)
|
||||||
@@ -213,9 +211,9 @@ repo_cache() {
|
|||||||
}
|
}
|
||||||
while IFS='|' read -r file id path; do
|
while IFS='|' read -r file id path; do
|
||||||
url="$REPO_BASE/$path"
|
url="$REPO_BASE/$path"
|
||||||
check 1 "[$id] 软件源配置正确,定义唯一,且未遗留其他启用源" "[$id] 配置缺失、重复或遗留其他启用源(Rocky 还需 exclude=sip,PyQt4)" repo_ok "/etc/yum.repos.d/$file" "$id" "$url"
|
check 1 "[$id] 配置" "[$id] 配置异常,检查重复项、启用源和 exclude" repo_ok "/etc/yum.repos.d/$file" "$id" "$url"
|
||||||
check 1 "[$id] 仓库索引可正常访问:$url" "[$id] 仓库索引不可访问:$url" repo_online "$url"
|
check 1 "[$id] 连通" "[$id] 索引不可访问" repo_online "$url"
|
||||||
check 1 "[$id] 已有 YUM 缓存可正常读取" "[$id] 已有 YUM 缓存不可读取,请检查 yum makecache 结果" repo_cache "$id"
|
check 1 "[$id] 缓存" "[$id] 缓存异常,执行 yum makecache" repo_cache "$id"
|
||||||
done <<'REPOLIST'
|
done <<'REPOLIST'
|
||||||
CentOS-Base.repo|local-base|vault-base
|
CentOS-Base.repo|local-base|vault-base
|
||||||
CentOS-Base.repo|local-updates|vault-updates
|
CentOS-Base.repo|local-updates|vault-updates
|
||||||
@@ -224,7 +222,7 @@ CentOS-QEMU-EV.repo|local-qemu-ev|vault-centos-qemu-ev
|
|||||||
CentOS-OpenStack-rocky.repo|local-openstack-rocky|vault-centos-openstack-rocky
|
CentOS-OpenStack-rocky.repo|local-openstack-rocky|vault-centos-openstack-rocky
|
||||||
REPOLIST
|
REPOLIST
|
||||||
|
|
||||||
section 'NTP 时间同步(15分)'
|
section '时间同步(15分)'
|
||||||
chrony_config() {
|
chrony_config() {
|
||||||
awk '{sub(/[#!;].*/,"")}
|
awk '{sub(/[#!;].*/,"")}
|
||||||
$1=="server" && $2=="controller" {n++; for(i=3;i<=NF;i++)if($i=="iburst")good++}
|
$1=="server" && $2=="controller" {n++; for(i=3;i<=NF;i++)if($i=="iburst")good++}
|
||||||
@@ -239,14 +237,14 @@ chrony_synced() {
|
|||||||
$1 ~ /^[\^=]/ && $2!=ip {bad=1}
|
$1 ~ /^[\^=]/ && $2!=ip {bad=1}
|
||||||
END{exit !(found && !bad)}'
|
END{exit !(found && !bad)}'
|
||||||
}
|
}
|
||||||
check 2 'chrony 时间同步软件包已安装' 'chrony 软件包未安装' rpm -q chrony
|
check 2 'chrony 已安装' 'chrony 未安装' rpm -q chrony
|
||||||
check 4 'chrony 仅启用了 server controller iburst,默认外网源已注释' 'chrony 应仅启用 server controller iburst,并注释默认外网源' chrony_config
|
check 4 'chrony 时间源配置' 'chrony 应仅启用 server controller iburst' chrony_config
|
||||||
check 2 'chronyd 时间同步服务正在运行' 'chronyd 未运行' active_service chronyd
|
check 2 'chronyd 运行' 'chronyd 未运行' active_service chronyd
|
||||||
check 2 'chronyd 时间同步服务已设置持久开机自启' 'chronyd 未持久设置开机自启' enabled_service chronyd
|
check 2 'chronyd 自启' 'chronyd 未设置自启' enabled_service chronyd
|
||||||
check 5 'chronyd 已选中控制节点为同步源(^*),且未加载其他服务器源' 'chronyd 当前应选中控制节点为同步源(^*),且没有其他服务器源' chrony_synced
|
check 5 '时间已同步到 controller' '时间源未选中 controller 或有其他源' chrony_synced
|
||||||
|
|
||||||
section 'Nova 软件包(5分)'
|
section 'Nova 软件包(5分)'
|
||||||
check 5 'openstack-nova-compute 软件包已安装' 'openstack-nova-compute 未安装' rpm -q openstack-nova-compute
|
check 5 'nova-compute 已安装' 'nova-compute 未安装' rpm -q openstack-nova-compute
|
||||||
|
|
||||||
section 'Nova 配置(30分)'
|
section 'Nova 配置(30分)'
|
||||||
# 配置按小组评分;组内错误键附在失败提示中,不输出实际值或口令。
|
# 配置按小组评分;组内错误键附在失败提示中,不输出实际值或口令。
|
||||||
@@ -275,7 +273,7 @@ config_group() {
|
|||||||
done
|
done
|
||||||
# my_ip 必须同时属于本机;即便 hosts 未完成,也不接受示例中的远端 IP。
|
# my_ip 必须同时属于本机;即便 hosts 未完成,也不接受示例中的远端 IP。
|
||||||
if [ "$group" = DEFAULT ] && ! compute_mapping >/dev/null 2>&1; then bad="$bad my_ip/hosts/本机地址"; fi
|
if [ "$group" = DEFAULT ] && ! compute_mapping >/dev/null 2>&1; then bad="$bad my_ip/hosts/本机地址"; fi
|
||||||
check "$points" "[$group] Nova 配置符合实验要求" "[$group] 错误或缺失的配置键:${bad:-文件不可读};请检查 $CONF" test -z "$bad"
|
check "$points" "Nova [$group]" "Nova [$group] 错误键:${bad:-文件不可读}" test -z "$bad"
|
||||||
}
|
}
|
||||||
config_group 6 DEFAULT enabled_apis 'osapi_compute,metadata' transport_url 'rabbit://openstack:openstack@controller' my_ip "$COMPUTE_IP" use_neutron true firewall_driver nova.virt.firewall.NoopFirewallDriver
|
config_group 6 DEFAULT enabled_apis 'osapi_compute,metadata' transport_url 'rabbit://openstack:openstack@controller' my_ip "$COMPUTE_IP" use_neutron true firewall_driver nova.virt.firewall.NoopFirewallDriver
|
||||||
config_group 2 api auth_strategy keystone
|
config_group 2 api auth_strategy keystone
|
||||||
@@ -296,11 +294,11 @@ virtualization_ok() {
|
|||||||
fi
|
fi
|
||||||
[ "$type" = qemu ]
|
[ "$type" = qemu ]
|
||||||
}
|
}
|
||||||
check 5 'Nova 虚拟化类型与 CPU 硬件虚拟化能力匹配' '无 vmx/svm 时必须设置 [libvirt] virt_type=qemu;有扩展时允许默认 kvm 或 qemu' virtualization_ok
|
check 5 '虚拟化类型' '虚拟化类型不匹配;无 vmx/svm 时需用 qemu' virtualization_ok
|
||||||
|
|
||||||
section '计算服务运行与开机自启(10分)'
|
section '服务状态(10分)'
|
||||||
for service in libvirtd openstack-nova-compute; do
|
for service in libvirtd openstack-nova-compute; do
|
||||||
check 3 "$service 服务正在运行" "$service 未运行" active_service "$service"
|
check 3 "$service 运行" "$service 未运行" active_service "$service"
|
||||||
check 2 "$service 服务已设置持久开机自启" "$service 未持久设置开机自启" enabled_service "$service"
|
check 2 "$service 自启" "$service 未设置自启" enabled_service "$service"
|
||||||
done
|
done
|
||||||
finish
|
finish
|
||||||
Reference in new issue
Block a user