#!/usr/bin/env bash
# 设置脚本在遇到错误时退出,并且管道命令中任何命令失败都会导致脚本退出
set -o errexit
set -o pipefail
# 默认环境变量
KOLLA_DEBUG=${KOLLA_DEBUG:-0} # 是否启用调试模式,默认为0(关闭)
KOLLA_CONFIG_PATH=${KOLLA_CONFIG_PATH:-/etc/kolla} # Kolla配置文件路径,默认为/etc/kolla
# OpenStack命令的前缀
KOLLA_OPENSTACK_COMMAND=openstack
# 如果启用调试模式,添加--debug选项到OpenStack命令
if [[ $KOLLA_DEBUG -eq 1 ]]; then
set -o xtrace # 打印执行的命令
KOLLA_OPENSTACK_COMMAND="$KOLLA_OPENSTACK_COMMAND --debug"
fi
# 脚本功能:下载CirrOS镜像并注册到Glance,配置网络,设置Nova配额,允许创建40个m1.small实例
# 获取系统架构(如x86_64或arm64)
ARCH=$(uname -m)
# CirrOS镜像版本,默认为0.6.2
CIRROS_RELEASE=${CIRROS_RELEASE:-0.6.2}
# 镜像存储路径,默认为/opt/cache/files/
IMAGE_PATH=/opt/cache/files/
# CirrOS镜像的下载URL
IMAGE_URL=https://github.com/cirros-dev/cirros/releases/download/${CIRROS_RELEASE}/
# 镜像文件名,根据架构和版本生成
IMAGE=cirros-${CIRROS_RELEASE}-${ARCH}-disk.img
# 在OpenStack中注册的镜像名称
IMAGE_NAME=cirros
# 镜像类型(操作系统类型)
IMAGE_TYPE=linux
# 网络配置,默认为IPv4
IP_VERSION=${IP_VERSION:-4}
# 内部网络配置
DEMO_NET_CIDR=${DEMO_NET_CIDR:-'10.0.0.0/24'} # 内部网络CIDR
DEMO_NET_GATEWAY=${DEMO_NET_GATEWAY:-'10.0.0.1'} # 内部网络网关
DEMO_NET_DNS=${DEMO_NET_DNS:-'8.8.8.8'} # 内部网络DNS
# 外部网络配置(可选)
ENABLE_EXT_NET=${ENABLE_EXT_NET:-1} # 是否启用外部网络,默认启用
EXT_NET_CIDR=${EXT_NET_CIDR:-'10.0.2.0/24'} # 外部网络CIDR
EXT_NET_RANGE=${EXT_NET_RANGE:-'start=10.0.2.150,end=10.0.2.199'} # 外部网络分配范围
EXT_NET_GATEWAY=${EXT_NET_GATEWAY:-'10.0.2.1'} # 外部网络网关
# 清理语言环境变量,避免因语言设置导致命令失败
unset LANG
unset LANGUAGE
LC_ALL=C
export LC_ALL
# 检查curl和openstack命令是否已安装
for i in curl openstack; do
if [[ ! $(type ${i} 2>/dev/null) ]]; then
if [ "${i}" == 'curl' ]; then
echo "Please install ${i} before proceeding" # 提示安装curl
else
echo "Please install python-${i}client before proceeding" # 提示安装python-openstackclient
fi
exit
fi
done
# 检查clouds.yaml配置文件是否存在
if [[ ! -f ${KOLLA_CONFIG_PATH}/clouds.yaml ]]; then
echo "${KOLLA_CONFIG_PATH}/clouds.yaml is missing." # 提示文件缺失
echo " Did your deploy finish successfully?"
exit 1
fi
# 指定使用clouds.yaml文件
export OS_CLIENT_CONFIG_FILE=${KOLLA_CONFIG_PATH}/clouds.yaml
# 使用admin账户
export OS_CLOUD=kolla-admin
# 检查是否已经注册了CirrOS镜像,避免重复运行脚本
if $KOLLA_OPENSTACK_COMMAND image list | grep -q cirros; then
echo "This tool should only be run once per deployment."
exit
fi
# 检查本地是否有CirrOS镜像,如果没有则下载
echo Checking for locally available cirros image.
if ! [ -f "${IMAGE_PATH}/${IMAGE}" ]; then
IMAGE_PATH='./' # 如果指定路径没有镜像,则尝试在当前目录查找
if ! [ -f "${IMAGE_PATH}/${IMAGE}" ]; then
echo "None found, downloading cirros image (version $CIRROS_RELEASE)."
curl --fail -L -o ${IMAGE_PATH}/${IMAGE} ${IMAGE_URL}/${IMAGE} # 下载镜像
fi
else
echo Using cached cirros image from the nodepool node. # 使用缓存的镜像
fi
# 将CirrOS镜像上传到Glance
echo Creating glance image.
$KOLLA_OPENSTACK_COMMAND image create --disk-format qcow2 --container-format bare --public \
--property os_type=${IMAGE_TYPE} --file ${IMAGE_PATH}/${IMAGE} ${IMAGE_NAME}
# 配置Neutron网络
echo Configuring neutron.
# 创建路由器
$KOLLA_OPENSTACK_COMMAND router create demo-router
# 初始化子网创建参数
SUBNET_CREATE_EXTRA=""
# 如果是IPv6网络,添加IPv6相关参数
if [[ $IP_VERSION -eq 6 ]]; then
SUBNET_CREATE_EXTRA="${SUBNET_CREATE_EXTRA} --ipv6-ra-mode dhcpv6-stateful"
SUBNET_CREATE_EXTRA="${SUBNET_CREATE_EXTRA} --ipv6-address-mode dhcpv6-stateful"
fi
# 创建内部网络和子网
$KOLLA_OPENSTACK_COMMAND network create demo-net
$KOLLA_OPENSTACK_COMMAND subnet create --ip-version ${IP_VERSION} \
--subnet-range ${DEMO_NET_CIDR} --network demo-net \
--gateway ${DEMO_NET_GATEWAY} --dns-nameserver ${DEMO_NET_DNS} \
${SUBNET_CREATE_EXTRA} demo-subnet
# 将子网添加到路由器
$KOLLA_OPENSTACK_COMMAND router add subnet demo-router demo-subnet
# 如果启用外部网络,配置外部网络
if [[ $ENABLE_EXT_NET -eq 1 ]]; then
$KOLLA_OPENSTACK_COMMAND network create --external --provider-physical-network physnet1 \
--provider-network-type flat public1 # 创建外部网络
$KOLLA_OPENSTACK_COMMAND subnet create --no-dhcp --ip-version ${IP_VERSION} \
--allocation-pool ${EXT_NET_RANGE} --network public1 \
--subnet-range ${EXT_NET_CIDR} --gateway ${EXT_NET_GATEWAY} public1-subnet # 创建外部子网
# 将外部网络设置为路由器的网关
if [[ $IP_VERSION -eq 4 ]]; then
$KOLLA_OPENSTACK_COMMAND router set --external-gateway public1 demo-router
else
# IPv6不支持NAT,需要手动配置静态路由
$KOLLA_OPENSTACK_COMMAND router set --external-gateway public1 \
--fixed-ip subnet=public1-subnet,ip-address=${EXT_NET_DEMO_ROUTER_ADDR} \
demo-router
fi
fi
# 获取admin项目和默认安全组的ID
ADMIN_PROJECT_ID=$($KOLLA_OPENSTACK_COMMAND project list | awk '/ admin / {print $2}')
ADMIN_SEC_GROUP=$($KOLLA_OPENSTACK_COMMAND security group list --project ${ADMIN_PROJECT_ID} | awk '/ default / {print $2}')
# 配置安全组规则,允许ICMP、SSH、以及特定TCP端口
$KOLLA_OPENSTACK_COMMAND security group rule create --ingress --ethertype IPv${IP_VERSION} \
--protocol icmp ${ADMIN_SEC_GROUP}
$KOLLA_OPENSTACK_COMMAND security group rule create --ingress --ethertype IPv${IP_VERSION} \
--protocol tcp --dst-port 22 ${ADMIN_SEC_GROUP}
$KOLLA_OPENSTACK_COMMAND security group rule create --ingress --ethertype IPv${IP_VERSION} \
--protocol tcp --dst-port 8000 ${ADMIN_SEC_GROUP}
$KOLLA_OPENSTACK_COMMAND security group rule create --ingress --ethertype IPv${IP_VERSION} \
--protocol tcp --dst-port 8080 ${ADMIN_SEC_GROUP}
# 生成SSH密钥对,并将其上传到OpenStack
if [ ! -f ~/.ssh/id_ecdsa.pub ]; then
echo Generating ssh key.
ssh-keygen -t ecdsa -N '' -f ~/.ssh/id_ecdsa
fi
if [ -r ~/.ssh/id_ecdsa.pub ]; then
echo Configuring nova public key and quotas.
$KOLLA_OPENSTACK_COMMAND keypair create --public-key ~/.ssh/id_ecdsa.pub mykey
fi
# 增加admin项目的配额,允许创建40个m1.small实例
$KOL