blob: 80c7bb6ee98549ff650ac5133ecb3056636f88ab [file]
#!/usr/bin/env bash
# c8k.in/stall.sh - Easiest Apache CloudStack Installer
# Author: Rohit Yadav <rohit@apache.org>
# Install with this command (from your Ubuntu host):
#
# curl -sSfL https://c8k.in/stall.sh | bash
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you 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.
set -e
set -o noglob
CS_VERSION=4.18
INTERFACE=
BRIDGE=cloudbr0
HOST_IP=
GATEWAY=
# --- helper functions for logs ---
info()
{
echo '[INFO] ' "$@"
}
warn()
{
echo '[WARN] ' "$@" >&2
}
fatal()
{
echo '[ERROR] ' "$@" >&2
exit 1
}
### Intro ###
echo "
░█████╗░░█████╗░██╗░░██╗░░░██╗███╗░░██╗
██╔══██╗██╔══██╗██║░██╔╝░░░██║████╗░██║
██║░░╚═╝╚█████╔╝█████═╝░░░░██║██╔██╗██║
██║░░██╗██╔══██╗██╔═██╗░░░░██║██║╚████║
╚█████╔╝╚█████╔╝██║░╚██╗██╗██║██║░╚███║
░╚════╝░░╚════╝░╚═╝░░╚═╝╚═╝╚═╝╚═╝░░╚══╝
CloudStack Installer By 🅁🄾🄷🄸🅃 🅈🄰🄳🄰🅅
"
info "Installing Apache CloudStack All-In-One-Box"
info "NOTE: this works only on Ubuntu 22.04 (tested), and run as 'root' user!"
if [[ $EUID -ne 0 ]]; then
fatal "This script must be run as root"
exit 1
fi
warn "Work in progress, try again while this is being hacked"
### Setup Prerequisites ###
info "Installing dependencies"
#apt-get update
apt-get install -y openssh-server sudo wget jq htop tar nmap bridge-utils
### Setup Bridge ###
setup_bridge() {
if brctl show $BRIDGE > /dev/null; then
return
fi
#FIXME: we want to avoid virtual nics
# ls -l /sys/class/net/ | grep -v virtual
interface=$(ls /sys/class/net/ | grep -v 'lo' | head -1)
gateway=$(ip route show 0.0.0.0/0 dev ens3 | cut -d\ -f3)
hostip=$(ip -f inet addr show $interface | sed -En -e 's/.*inet ([0-9.]+).*/\1/p')
info "Setting up bridge on $interface which has IP $hostip and gateway $gateway"
echo "network:
version: 2
renderer: networkd
ethernets:
$interface:
dhcp4: false
dhcp6: false
optional: true
bridges:
$BRIDGE:
addresses: [$hostip/24]
routes:
- to: default
via: $gateway
nameservers:
addresses: [8.8.8.8, 1.1.1.1]
interfaces: [$interface]
dhcp4: false
dhcp6: false
parameters:
stp: false
forward-delay: 0" > /etc/netplan/01-netcfg.yaml
info "Disabling cloud-init netplan config"
rm -f /etc/netplan/50-cloud-init.yaml
echo "network: {config: disabled}" > /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg
netplan generate
netplan apply
export INTERFACE=$interface
}
### Setup CloudStack Packages ###
configure_repo() {
info "Configuring CloudStack $CS_VERSION repo"
mkdir -p /etc/apt/keyrings
wget -O- http://packages.shapeblue.com/release.asc 2>/dev/null | gpg --dearmor | sudo tee /etc/apt/keyrings/cloudstack.gpg > /dev/null
echo deb [signed-by=/etc/apt/keyrings/cloudstack.gpg] http://packages.shapeblue.com/cloudstack/upstream/debian/$CS_VERSION / > /etc/apt/sources.list.d/cloudstack.list
apt-get update
}
install_packages() {
info "Installing CloudStack $CS_VERSION, MySQL and NFS server"
if dpkg -l | grep cloudstack-management > /dev/null; then
warn "CloudStack packages seem to be already installed, skipping CloudStack packages installation"
apt-get install -y mysql-server nfs-kernel-server quota qemu-kvm
else
apt-get install -y cloudstack-management cloudstack-usage mysql-server nfs-kernel-server quota qemu-kvm cloudstack-agent
systemctl daemon-reload
systemctl stop cloudstack-management cloudstack-usage cloudstack-agent
fi
}
### Configure Methods ###
configure_mysql() {
info "Configuring MySQL Server: $(mysql -V)"
if grep 'sql-mode' /etc/mysql/mysql.conf.d/mysqld.cnf > /dev/null; then
info "Skipping MySQL configuration setup, already done"
return
fi
echo "server_id = 1
sql-mode="STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,ERROR_FOR_DIVISION_BY_ZERO,NO_ZERO_DATE,NO_ZERO_IN_DATE,NO_ENGINE_SUBSTITUTION"
innodb_rollback_on_timeout=1
innodb_lock_wait_timeout=600
max_connections=1000
log-bin=mysql-bin
binlog-format = 'ROW'" >> /etc/mysql/mysql.conf.d/mysqld.cnf
systemctl restart mysql
}
configure_storage() {
info "Configuring NFS Storage"
echo "/export *(rw,async,no_root_squash,no_subtree_check)" > /etc/exports
mkdir -p /export/primary /export/secondary
exportfs -a
sed -i -e 's/^RPCMOUNTDOPTS="--manage-gids"$/RPCMOUNTDOPTS="-p 892 --manage-gids"/g' /etc/default/nfs-kernel-server
sed -i -e 's/^STATDOPTS=$/STATDOPTS="--port 662 --outgoing-port 2020"/g' /etc/default/nfs-common
if ! grep 'NEED_STATD=yes' /etc/default/nfs-common > /dev/null; then
echo "NEED_STATD=yes" >> /etc/default/nfs-common
fi
sed -i -e 's/^RPCRQUOTADOPTS=$/RPCRQUOTADOPTS="-p 875"/g' /etc/default/quota
service nfs-kernel-server restart
info "NFS exports created: $(exportfs)"
}
configure_host() {
info "Configuring KVM on this host"
sed -i -e 's/\#vnc_listen.*$/vnc_listen = "0.0.0.0"/g' /etc/libvirt/qemu.conf
if ! grep 'LIBVIRTD_ARGS="--listen"' /etc/default/libvirtd > /dev/null; then
echo LIBVIRTD_ARGS=\"--listen\" >> /etc/default/libvirtd
fi
if ! grep 'listen_tcp=1' /etc/libvirt/libvirtd.conf > /dev/null; then
echo 'listen_tcp=1' >> /etc/libvirt/libvirtd.conf
echo 'listen_tls=0' >> /etc/libvirt/libvirtd.conf
echo 'tcp_port = "16509"' >> /etc/libvirt/libvirtd.conf
echo 'mdns_adv = 0' >> /etc/libvirt/libvirtd.conf
echo 'auth_tcp = "none"' >> /etc/libvirt/libvirtd.conf
systemctl mask libvirtd.socket libvirtd-ro.socket libvirtd-admin.socket libvirtd-tls.socket libvirtd-tcp.socket
systemctl restart libvirtd
# Ubuntu: disable apparmor
ln -s /etc/apparmor.d/usr.sbin.libvirtd /etc/apparmor.d/disable/
ln -s /etc/apparmor.d/usr.lib.libvirt.virt-aa-helper /etc/apparmor.d/disable/
apparmor_parser -R /etc/apparmor.d/usr.sbin.libvirtd
apparmor_parser -R /etc/apparmor.d/usr.lib.libvirt.virt-aa-helper
fi
if ! kvm-ok; then
warn "KVM may not work on your host"
else
info "KVM host configured"
virsh nodeinfo
fi
}
deploy_cloudstack() {
if systemctl is-active cloudstack-management > /dev/null; then
info "CloudStack Management Server is already running, skipping DB deployment"
return
fi
info "Deploying CloudStack Database"
cloudstack-setup-databases cloud:cloud@localhost --deploy-as=root: #-i <cloudbr0 IP here>
info "Deploying CloudStack Management Server"
cloudstack-setup-management
}
install_completed() {
info "CloudStack installation completed!"
info "Access CloudStack UI at: http://$HOST_IP:8080/client with username 'admin' and password 'password'"
echo
}
deploy_zone() {
info "Deploying CloudStack Zone"
wget -q https://github.com/apache/cloudstack-cloudmonkey/releases/download/6.4.0/cmk.linux.x86-64 -O /usr/bin/cmk > /dev/null
chmod +x /usr/bin/cmk
cmk set username admin
cmk set password password
cmk set display json
cmk sync
zone_id=$(cmk create zone dns1=8.8.8.8 internaldns1=$GATEWAY name=AdvZone1 networktype=Advanced | jq '.zone.id')
info "Created CloudStack Zone with ID $zone_id"
phy_id=$(cmk create physicalnetwork name=cloudbr0 zoneid=$zone_id | jq '.physicalnetwork.id')
cmk add traffictype traffictype=Management physicalnetworkid=$phy_id
cmk add traffictype traffictype=Public physicalnetworkid=$phy_id
cmk add traffictype traffictype=Guest physicalnetworkid=$phy_id
cmk update physicalnetwork state=Enabled id=$phy_id
info "Created CloudStack Physical Network in zone with ID $phy_id"
nsp_id=$(cmk list networkserviceproviders name=VirtualRouter physicalnetworkid=$phy_id | jq -r '.networkserviceprovider[0].id')
vre_id=$(cmk list virtualrouterelements nspid=$nsp_id | jq -r '.virtualrouterelement[0].id')
cmk configure virtualrouterelement enabled=true id=$vre_id
cmk update networkserviceprovider state=Enabled id=$nsp_id
info "Configured VR Network Service Provider for zone"
nsp_id=$(cmk list networkserviceproviders name=Internallbvm physicalnetworkid=$phy_id | jq -r '.networkserviceprovider[0].id')
ilbvm_id=$(cmk list internalloadbalancerelements nspid=$nsp_id | jq -r '.internalloadbalancerelement[0].id')
cmk configure internalloadbalancerelement enabled=true id=$ilbvm_id
cmk update networkserviceprovider state=Enabled id=$nsp_id
info "Configured ILBVM Network Service Provider for zone"
nsp_id=$(cmk list networkserviceproviders name=VpcVirtualRouter physicalnetworkid=$phy_id | jq -r '.networkserviceprovider[0].id')
vpcvre_id=$(cmk list virtualrouterelements nspid=$nsp_id | jq -r '.virtualrouterelement[0].id')
cmk configure virtualrouterelement enabled=true id=$vpcvre_id
cmk update networkserviceprovider state=Enabled id=$nsp_id
info "Configured VPC VR Network Service Provider for zone"
# TODO: use nmap to scan for free IPs in the range
# sudo nmap -v -sn -n 192.168.1.0/24 -oG - | awk '/Status: Down/{print $2}'
RANGE=$(echo $GATEWAY | sed 's/\..$//g')
pod_id=$(cmk create pod name=AdvPod1 zoneid=$zone_id gateway=$GATEWAY netmask=255.255.255.0 startip=$pod_start endip=$pod_end | jq '.pod.id')
}
display_url() {
echo "
█████████████████████████████████████████████████████████████
█─▄▄▄─█▄─▄███─▄▄─█▄─██─▄█▄─▄▄▀█─▄▄▄▄█─▄─▄─██▀▄─██─▄▄▄─█▄─█─▄█
█─███▀██─██▀█─██─██─██─███─██─█▄▄▄▄─███─████─▀─██─███▀██─▄▀██
▀▄▄▄▄▄▀▄▄▄▄▄▀▄▄▄▄▀▀▄▄▄▄▀▀▄▄▄▄▀▀▄▄▄▄▄▀▀▄▄▄▀▀▄▄▀▄▄▀▄▄▄▄▄▀▄▄▀▄▄▀
URL: http://$HOST_IP:8080/client
User: admin
Password: password
"
}
### Installer: Setup ###
setup_bridge
export HOST_IP=$(ip -f inet addr show $BRIDGE | sed -En -e 's/.*inet ([0-9.]+).*/\1/p')
export GATEWAY=$(ip route show 0.0.0.0/0 dev $BRIDGE | cut -d\ -f3)
info "Bridge $BRIDGE is setup with IP $HOST_IP"
configure_repo
install_packages
configure_mysql
configure_storage
configure_host
deploy_cloudstack
install_completed
### Installer: Deploy Zone ###
#deploy_zone
### Installer: Finish ###
display_url