Files
OpenStackScripts/env3-2-local.sh
T

354 lines
11 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
set -euo pipefail
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_err() {
echo -e "${RED}[ERROR]${NC} $1"
}
# 检查 root 权限
if [ "$EUID" -ne 0 ]; then
log_err "请使用 root 权限执行此脚本(如: sudo bash $0)"
exit 1
fi
log_info "=========================================="
log_info "开始初始化实验环境..."
log_info "=========================================="
# 直接连接终端,保留 yum 原生下载进度条;不要通过 tee 管道转存输出。
run_yum() {
local status
log_info "执行 yum $*(下载速度取决于网络和镜像源)..."
# 仅启用本地仓库,避免系统中其他已启用的公网仓库参与下载。
if yum --disablerepo='*' \
--enablerepo=local-base,local-updates,local-extras,local-qemu-ev,local-openstack-rocky \
"$@"; then
log_info "yum 操作完成。"
else
status=$?
log_err "yum 操作失败(退出码 $status),请查看上方错误信息。"
return "$status"
fi
}
REPO_DIR="/etc/yum.repos.d"
BACKUP_DIR="/etc/yum.repos.d.bak"
# 首次运行时备份原有软件源
if [ ! -d "$BACKUP_DIR" ]; then
log_info "备份原有 yum 软件源..."
cp -a "$REPO_DIR" "$BACKUP_DIR"
fi
# 配置 CentOS 7.9 基础源
log_info "配置 CentOS 7.9 本地软件源(192.168.192.205:3080)..."
cat > "$REPO_DIR/CentOS-Base.repo" <<'EOF'
[local-base]
name=Local - Base
baseurl=http://192.168.192.205:3080/vault-base/
gpgcheck=0
enabled=1
[local-updates]
name=Local - Updates
baseurl=http://192.168.192.205:3080/vault-updates/
gpgcheck=0
enabled=1
[local-extras]
name=Local - Extras
baseurl=http://192.168.192.205:3080/vault-extras/
gpgcheck=0
enabled=1
EOF
# 配置 QEMU EV 源
cat > "$REPO_DIR/CentOS-QEMU-EV.repo" <<'EOF'
[local-qemu-ev]
name=Local - QEMU EV
baseurl=http://192.168.192.205:3080/vault-centos-qemu-ev/
gpgcheck=0
enabled=1
EOF
# 配置 OpenStack Rocky 源
cat > "$REPO_DIR/CentOS-OpenStack-rocky.repo" <<'EOF'
[local-openstack-rocky]
name=Local - OpenStack Rocky
baseurl=http://192.168.192.205:3080/vault-centos-openstack-rocky/
gpgcheck=0
enabled=1
exclude=sip,PyQt4
EOF
# 删除不再需要的 Ceph 源,避免 yum 读取其元数据
rm -f "$REPO_DIR/CentOS-Ceph-Luminous.repo"
# 清除旧仓库元数据,保留已下载的软件包缓存
log_info "刷新软件源元数据..."
run_yum clean metadata
CONTROLLER_IP="192.168.30.129"
CONTROLLER_HOSTNAME="controller"
# 首次修改时备份配置,重复运行不覆盖原始备份。
backup_config() {
if [ -f "$1" ] && [ ! -e "$1.env3-2.bak" ]; then
cp -a "$1" "$1.env3-2.bak"
fi
}
log_info "关闭防火墙和 SELinux..."
if systemctl list-unit-files firewalld.service --no-legend | grep -q '^firewalld.service'; then
systemctl stop firewalld
systemctl disable firewalld
fi
if command -v getenforce > /dev/null 2>&1; then
if [ "$(getenforce)" = "Enforcing" ]; then
setenforce 0
fi
fi
if [ -f /etc/selinux/config ]; then
backup_config /etc/selinux/config
sed -i '/^[[:space:]]*SELINUX=/d' /etc/selinux/config
echo 'SELINUX=disabled' >> /etc/selinux/config
fi
log_info "配置主机名和 hosts 解析..."
hostnamectl set-hostname "$CONTROLLER_HOSTNAME"
backup_config /etc/hosts
# 移除旧 controller 映射,保留同一行的其他别名及注释。
HOSTS_TMP=$(mktemp)
awk -v host="$CONTROLLER_HOSTNAME" '
/^[[:space:]]*#/ || NF == 0 { print; next }
{
comment = ""
pos = index($0, "#")
if (pos) {
comment = substr($0, pos)
$0 = substr($0, 1, pos - 1)
}
line = $1
aliases = 0
for (i = 2; i <= NF; i++) {
if ($i != host) {
line = line " " $i
aliases++
}
}
if (aliases) print line (comment == "" ? "" : " " comment)
else if (comment != "") print comment
}
' /etc/hosts > "$HOSTS_TMP"
cat "$HOSTS_TMP" > /etc/hosts
rm -f "$HOSTS_TMP"
printf '%s %s\n' "$CONTROLLER_IP" "$CONTROLLER_HOSTNAME" >> /etc/hosts
log_info "升级系统软件包,合并安装虚拟化、OpenStack 基础服务和 Keystone..."
run_yum -y upgrade
run_yum install -y chrony python2-openstackclient \
mariadb mariadb-server python2-PyMySQL \
rabbitmq-server memcached python-memcached etcd \
qemu-kvm libvirt virt-install bridge-utils qemu-img \
openstack-keystone httpd mod_wsgi
# 启动 libvirtd
log_info "启动 libvirtd 服务..."
systemctl enable --now libvirtd > /dev/null
# 验证服务状态
if systemctl is-active --quiet libvirtd; then
log_info "libvirtd 状态正常。"
else
log_err "libvirtd 启动失败!"
exit 1
fi
log_info "配置 chrony 时间服务器..."
backup_config /etc/chrony.conf
if ! grep -Eq '^[[:space:]]*allow[[:space:]]+all([[:space:]]*(#.*)?)?$' /etc/chrony.conf; then
printf '\n# 允许所有网段的机器访问同步时间\nallow all\n' >> /etc/chrony.conf
fi
systemctl enable chronyd
systemctl restart chronyd
log_info "配置 MariaDB..."
mkdir -p /etc/my.cnf.d
backup_config /etc/my.cnf.d/openstack.cnf
cat > /etc/my.cnf.d/openstack.cnf <<'EOF'
[mysqld]
bind-address = 0.0.0.0
# 默认使用 InnoDB,每个表的数据独立保存成文件。
default-storage-engine = innodb
innodb_file_per_table = on
# 调高最大连接数,并使用 UTF-8 字符集。
max_connections = 4096
collation-server = utf8_general_ci
character-set-server = utf8
EOF
systemctl enable mariadb
systemctl restart mariadb
log_info "初始化 MariaDB 安全配置及 root 远程登录权限..."
# CentOS 7 的 MariaDB 5.5:自动执行 mysql_secure_installation 的等效操作。
# 使用权限为 600 的临时客户端配置,避免把密码放进进程参数。
MYSQL_AUTH_FILE=$(mktemp)
trap 'rm -f "$MYSQL_AUTH_FILE"' EXIT
chmod 600 "$MYSQL_AUTH_FILE"
cat > "$MYSQL_AUTH_FILE" <<'EOF'
[client]
user=root
password=123456
protocol=socket
EOF
MYSQL_CMD=(mysql --defaults-extra-file="$MYSQL_AUTH_FILE")
if ! "${MYSQL_CMD[@]}" -e 'SELECT 1' > /dev/null 2>&1; then
MYSQL_CMD=(mysql --no-defaults --user=root --protocol=socket)
if ! "${MYSQL_CMD[@]}" -e 'SELECT 1' > /dev/null 2>&1; then
log_err "无法使用空密码或预设密码连接 MariaDB root,请检查已有数据库凭据。"
exit 1
fi
fi
"${MYSQL_CMD[@]}" <<'SQL'
DELETE FROM mysql.user WHERE User = '';
DELETE FROM mysql.user
WHERE User = 'root' AND Host NOT IN ('localhost', '127.0.0.1', '::1');
UPDATE mysql.user SET Password = PASSWORD('123456') WHERE User = 'root';
DROP DATABASE IF EXISTS test;
DELETE FROM mysql.db WHERE Db = 'test' OR Db = 'test\_%';
FLUSH PRIVILEGES;
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY '123456' WITH GRANT OPTION;
FLUSH PRIVILEGES;
SQL
log_info "创建 Keystone 数据库并授权..."
mysql --defaults-extra-file="$MYSQL_AUTH_FILE" <<'SQL'
CREATE DATABASE IF NOT EXISTS keystone;
GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' IDENTIFIED BY 'keystone';
GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' IDENTIFIED BY 'keystone';
FLUSH PRIVILEGES;
SQL
rm -f "$MYSQL_AUTH_FILE"
trap - EXIT
log_info "配置 RabbitMQ 用户及权限..."
systemctl enable rabbitmq-server
systemctl start rabbitmq-server
RABBITMQ_USERS=$(rabbitmqctl list_users -q)
if awk '$1 == "openstack" { found = 1 } END { exit !found }' <<< "$RABBITMQ_USERS"; then
rabbitmqctl change_password openstack openstack
else
rabbitmqctl add_user openstack openstack
fi
rabbitmqctl set_permissions -p / openstack '.*' '.*' '.*'
log_info "配置 Memcached..."
backup_config /etc/sysconfig/memcached
sed -i '/^[[:space:]]*OPTIONS=/d' /etc/sysconfig/memcached
echo 'OPTIONS="-l 127.0.0.1,::1,controller"' >> /etc/sysconfig/memcached
systemctl enable memcached
systemctl restart memcached
log_info "配置 Etcd..."
backup_config /etc/etcd/etcd.conf
cat > /etc/etcd/etcd.conf <<'EOF'
#[Member]
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_NAME="controller"
#[Clustering]
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://controller:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://controller:2379"
ETCD_INITIAL_CLUSTER="controller=http://controller:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster-01"
ETCD_INITIAL_CLUSTER_STATE="new"
EOF
systemctl enable etcd
systemctl restart etcd
log_info "配置 Keystone 数据库连接及 Fernet 令牌..."
backup_config /etc/keystone/keystone.conf
cat > /etc/keystone/keystone.conf <<'EOF'
[database]
connection = mysql+pymysql://keystone:keystone@controller/keystone
[token]
provider = fernet
EOF
chown root:keystone /etc/keystone/keystone.conf
chmod 640 /etc/keystone/keystone.conf
log_info "同步 Keystone 数据库表结构..."
su -s /bin/sh -c "keystone-manage db_sync" keystone
# 使用 setup 命令初始化密钥库,不删除已有密钥。
log_info "初始化 Fernet 和 credential 密钥库..."
keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone
keystone-manage credential_setup --keystone-user keystone --keystone-group keystone
log_info "初始化 Keystone 管理员及服务端点..."
keystone-manage bootstrap --bootstrap-password admin \
--bootstrap-admin-url http://controller:5000/v3 \
--bootstrap-public-url http://controller:5000/v3 \
--bootstrap-internal-url http://controller:5000/v3 \
--bootstrap-region-id RegionOne
log_info "配置 Apache HTTP 服务..."
backup_config /etc/httpd/conf/httpd.conf
# 删除已有生效的 ServerName,避免重复追加。
sed -i '/^[[:space:]]*ServerName[[:space:]]/d' /etc/httpd/conf/httpd.conf
printf '\nServerName controller\n' >> /etc/httpd/conf/httpd.conf
WSGI_SOURCE="/usr/share/keystone/wsgi-keystone.conf"
WSGI_LINK="/etc/httpd/conf.d/wsgi-keystone.conf"
if [ ! -f "$WSGI_SOURCE" ]; then
log_err "缺少 Keystone WSGI 配置:$WSGI_SOURCE"
exit 1
fi
# 备份已有普通配置文件;重复运行时更新软链接。
if [ ! -L "$WSGI_LINK" ]; then
backup_config "$WSGI_LINK"
fi
ln -sfnT "$WSGI_SOURCE" "$WSGI_LINK"
log_info "检查 Apache 配置并启动服务..."
httpd -t
systemctl enable httpd
systemctl restart httpd
log_info "检查各项服务状态..."
for service in libvirtd chronyd mariadb rabbitmq-server memcached etcd httpd; do
if systemctl is-active --quiet "$service"; then
log_info "$service 状态正常。"
else
log_err "$service 未正常运行,请使用 journalctl -u $service 查看日志。"
exit 1
fi
done
log_info "=========================================="
log_info "OpenStack 控制节点及 Keystone 初始化完成!"
log_info "控制节点:$CONTROLLER_HOSTNAME ($CONTROLLER_IP)"
log_info "MariaDB root 密码:123456,已允许远程登录。"
log_info "RabbitMQ 用户/密码:openstack / openstack"
log_info "Keystone 管理员/密码:admin / admin,区域:RegionOne"
log_info "Keystone API:http://controller:5000/v3"
log_info "=========================================="