198 lines
8.6 KiB
Bash
Executable File
198 lines
8.6 KiB
Bash
Executable File
#!/bin/bash
|
|
## author : Dryusdan
|
|
## date : 30/09/2019
|
|
## description : A vm deployment
|
|
## usage : ./deployvm hypervisor/auto templateID/auto/None os-version vm ram cpu
|
|
|
|
## Import require config ##############################
|
|
source utils/config
|
|
source utils/color
|
|
source utils/logger
|
|
#######################################################
|
|
|
|
if [ $# -eq 0 ]
|
|
then
|
|
fatal "No arguments supplied. Usage : ./deployvm.sh hypervisor/auto templateID vm ram cpu"
|
|
fi
|
|
|
|
if [ -z "${1}" ];
|
|
then
|
|
fatal "Hypervisor is not defined. Usage : ./deployvm.sh hypervisor/auto templateID vm ram cpu"
|
|
else
|
|
HYPERVISOR="${1}"
|
|
fi
|
|
|
|
if [ -z "${2}" ];
|
|
then
|
|
fatal "VM Template ID is not defined. Usage : ./deployvm.sh hypervisor/auto templateID vm ram cpu"
|
|
else
|
|
VMTPLID="${2}"
|
|
fi
|
|
|
|
if [ -z "${3}" ];
|
|
then
|
|
fatal "OS-Version is not defined. Usage : ./deployvm.sh hypervisor/auto templateID vm ram cpu"
|
|
else
|
|
OSVERSION="${3}"
|
|
fi
|
|
|
|
if [ -z "${4}" ];
|
|
then
|
|
fatal "VM name is not defined. Usage : ./deployvm.sh hypervisor/auto templateID vm ram cpu"
|
|
else
|
|
VMNAME="${4}"
|
|
fi
|
|
|
|
if [ -z "${5}" ];
|
|
then
|
|
fatal "RAM (MB) is not defined. Usage : ./deployvm.sh hypervisor/auto templateID vm ram cpu"
|
|
else
|
|
RAM="${5}"
|
|
fi
|
|
|
|
if [ -z "${6}" ];
|
|
then
|
|
fatal "Hypervisor is not defined. Usage : ./deployvm.sh hypervisor/auto templateID vm ram cpu"
|
|
else
|
|
CPU="${6}"
|
|
fi
|
|
|
|
info "Get token for Proxmox"
|
|
PROXMOX_CREDENTIAL=$(curl -s --insecure -d "username=${PROXMOX_USER}@pam&password=${PROXMOX_PASSWORD}" "${PROXMOX_HOST}/api2/json/access/ticket")
|
|
PROXMOX_TOKEN=$(echo ${PROXMOX_CREDENTIAL} | jq --raw-output '.data.ticket')
|
|
PROXMOX_CSRF=$(echo ${PROXMOX_CREDENTIAL} | jq --raw-output '.data.CSRFPreventionToken')
|
|
|
|
if [ ${HYPERVISOR} == "auto" ]
|
|
then
|
|
info "Get cluster state"
|
|
bestmemcluster=99999999999999999999999999999999
|
|
bestname=""
|
|
for node in $(curl -s --insecure -b "PVEAuthCookie=${PROXMOX_TOKEN}" "${PROXMOX_HOST}/api2/json/cluster/resources?type=node" | jq --raw-output ".data[] | @base64")
|
|
do
|
|
memory=$(echo ${node} | base64 --decode | jq --raw-output ".mem")
|
|
name=$(echo ${node} | base64 --decode | jq --raw-output ".node")
|
|
if [[ "${memory}" < "${bestmemcluster}" ]]
|
|
then
|
|
bestmemcluster=${memory}
|
|
bestname=${name}
|
|
fi
|
|
done
|
|
info "Choosing ${bestname}"
|
|
HYPERVISOR=${bestname}
|
|
|
|
fi
|
|
|
|
|
|
if [ ${VMTPLID} == "auto" ]
|
|
then
|
|
info "Get template ID"
|
|
VMTPLID=$(curl -s --insecure -b "PVEAuthCookie=${PROXMOX_TOKEN}" "${PROXMOX_HOST}/api2/json/nodes/${HYPERVISOR}/qemu" | jq --raw-output '.data[] | select(.name=="template-'${OSVERSION}'") | .vmid')
|
|
fi
|
|
|
|
info "Get new ID"
|
|
NEWID=$(curl -s --insecure -b "PVEAuthCookie=${PROXMOX_TOKEN}" "${PROXMOX_HOST}/api2/extjs/cluster/nextid" | jq --raw-output ".data")
|
|
|
|
if [ ${VMTPLID} == "" ]
|
|
then
|
|
fatal "No VMTPLID. Maybe OS-VERSION variable is wrong"
|
|
fi
|
|
|
|
if [ "${VMTPLID}" != "None" ]
|
|
then
|
|
info "Clone ${VMTPLID} for new vm ${VMNAME}"
|
|
UPID=$(curl -s --insecure -H "Content-Type: application/x-www-form-urlencoded" -H "CSRFPreventionToken: ${PROXMOX_CSRF}" -b "PVEAuthCookie=${PROXMOX_TOKEN}" -X POST --data "newid=${NEWID}&format=qcow2&full=1&name=${VMNAME}" "${PROXMOX_HOST}/api2/json/nodes/${HYPERVISOR}/qemu/${VMTPLID}/clone" | jq --raw-output '.data')
|
|
else
|
|
info "Create new VM ${VMNAME}"
|
|
|
|
fi
|
|
|
|
while [ true ]
|
|
do
|
|
info "Task is runnning"
|
|
sleep 15
|
|
if [ "$(curl -s --insecure -b "PVEAuthCookie=${PROXMOX_TOKEN}" "${PROXMOX_HOST}/api2/json/nodes/${HYPERVISOR}/tasks/${UPID}/status" | jq --raw-output '.data.status')" == "stopped" ]
|
|
then
|
|
info "Task ended"
|
|
break
|
|
fi
|
|
done
|
|
|
|
info "Get Netbox data for ${HYPERVISOR}"
|
|
NETBOX_VMBR0=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/ipam/ip-addresses/?device=${HYPERVISOR}&interface=vmbr0")
|
|
info "Get Gateway"
|
|
GATEWAY=$(echo ${NETBOX_VMBR0} | jq --raw-output '.results[0].address')
|
|
info "Get VRF ID"
|
|
VRF=$(echo ${NETBOX_VMBR0} | jq --raw-output '.results[0].vrf.id')
|
|
|
|
info "Get Prefix ID"
|
|
PREFIX_ID=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/ipam/prefixes/?within_include=${GATEWAY}&vrf_id=${VRF}" | jq --raw-output '.results[0].id')
|
|
info "Get address"
|
|
ADDRESS=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/ipam/prefixes/${PREFIX_ID}/available-ips/" | jq --raw-output '.[0].address')
|
|
info "get Gateway"
|
|
GATEWAY=$(echo ${GATEWAY} | cut -d'/' -f1)
|
|
|
|
info "Encode ${ADDRESS}"
|
|
ENCODEADDRESS=$(echo ${ADDRESS} | sed "s@/@%2F@g")
|
|
info "Configure ${VMNAME}"
|
|
curl -s --insecure -H "Content-Type: application/x-www-form-urlencoded" -H "CSRFPreventionToken: ${PROXMOX_CSRF}" -b "PVEAuthCookie=${PROXMOX_TOKEN}" -X PUT -d "ipconfig0=ip%3D${ENCODEADDRESS}%2Cgw%3D${GATEWAY}" "${PROXMOX_HOST}/api2/json/nodes/${HYPERVISOR}/qemu/${NEWID}/config" &> /dev/null
|
|
|
|
info "Get Netbox cluster ID"
|
|
CLUSTERID=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/dcim/devices/?name=${HYPERVISOR}" | jq --raw-output '.results[0].cluster.id')
|
|
|
|
info "Add vm on Netbox"
|
|
VMID=$(curl -s -X POST -H "Content-Type: application/json" -H "Authorization: Token ${NETBOX_TOKEN}" --data '{"name": "'${VMNAME}'", "cluster": '${CLUSTERID}', "role": 2, "disk": 20}' "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/virtual-machines/" | jq --raw-output '.id')
|
|
|
|
info "Create interface"
|
|
INTERFACEID=$(curl -s -X POST -H "Content-Type: application/json" -H "Authorization: Token ${NETBOX_TOKEN}" --data '{"virtual_machine": '${VMID}',"name": "eth0", "mtu": 1500, "enabled": "true"}' "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/interfaces/" | jq --raw-output ".id" )
|
|
|
|
info "Add ip on netbox for this interface ${INTERFACEID}"
|
|
curl -s -X POST -H "Content-Type: application/json" -H "Authorization: Token ${NETBOX_TOKEN}" --data '{"address": "'${ADDRESS}'","vrf": '${VRF}', "status": "active", "interface": '${INTERFACEID}'}' "${NETBOX_URL}${NETBOX_API_PATH}/ipam/ip-addresses/" &> /dev/null
|
|
|
|
${UPGRADERAM} ${VMNAME} ${RAM}
|
|
${UPGRADECPU} ${VMNAME} ${CPU}
|
|
|
|
info "Starting ${VMNAME}"
|
|
curl --insecure -H "Content-Type: application/x-www-form-urlencoded" -H "CSRFPreventionToken: ${PROXMOX_CSRF}" -b "PVEAuthCookie=${PROXMOX_TOKEN}" -X POST "${PROXMOX_HOST}/api2/json/nodes/${HYPERVISOR}/qemu/${NEWID}/status/start" &> /dev/null
|
|
|
|
info "Connect to Zabbix"
|
|
ZABBIX_AUTH_TOKEN=$(curl -s -X POST -H "Content-Type: application/json-rpc" -d '{"jsonrpc": "2.0","method":"user.login","params":{"user":"'${ZABBIX_USER}'","password":"'${ZABBIX_PASS}'"},"auth": null,"id":0}' ${ZABBIX_API} | jq --raw-output '.result')
|
|
|
|
info "Add HOST"
|
|
VMIP=$(echo ${ADDRESS} | cut -d'/' -f1)
|
|
curl -s -X POST -H 'Content-Type: application/json-rpc' -d '{"jsonrpc":"2.0","method":"host.create","params": {"host":"'${VMNAME}'","interfaces": [{"type": 1,"main": 1,"useip": 1,"ip": "'${VMIP}'","dns": "","port": "10050"}],"groups": [{"groupid": "'${ZABBIX_HOSTGROUPID1}'"},{"groupid": "'${ZABBIX_HOSTGROUPID2}'"}],"templates": [{"templateid": "'${ZABBIX_TEMPLATEID}'"}]},"auth":"'${ZABBIX_AUTH_TOKEN}'","id":1}' ${ZABBIX_API} &> /dev/null
|
|
|
|
info "Create host_vars"
|
|
cp templates/host_vars.tpl ${ANSIBLE_PATH}/host_vars/${VMNAME}
|
|
sed -i "s/<VMNAME>/${VMNAME}/g" ${ANSIBLE_PATH}/host_vars/${VMNAME}
|
|
sed -i "s/<IPADDR>/${VMIP}/g" ${ANSIBLE_PATH}/host_vars/${VMNAME}
|
|
|
|
sed -i "/^\[linux\]/a ${VMNAME} ansible_host=${VMIP}" ${ANSIBLE_PATH}/hosts
|
|
sed -i "/^\[ferm\]/a ${VMNAME}" ${ANSIBLE_PATH}/hosts
|
|
|
|
info "Waiting 5 minutes for ${VMNAME} starting"
|
|
sleep 300
|
|
|
|
info "Run ansible playbook"
|
|
cd ${ANSIBLE_PATH}
|
|
ansible-playbook -i hosts ${POSTINSTALL} --limit=${VMNAME}
|
|
|
|
info "Check if ${VMNAME} is pending"
|
|
RESULT=$(curl -s -X GET -H 'Content-Type: application/json' -H "X-API-Token: ${RUDDER_API_TOKEN}" -H "X-API-Version: 12" ${RUDDER_SRV}/rudder/api/nodes/pending | jq --raw-output '.data.nodes | length')
|
|
I=0
|
|
while [ "${RESULT}" -le "1" ]; do
|
|
sleep 1
|
|
I=$((${I}+1))
|
|
if [ $I -lt 30 ]; then
|
|
RESULT=$(curl -s -X GET -H 'Content-Type: application/json' -H "X-API-Token: ${RUDDER_API_TOKEN}" -H "X-API-Version: 12" ${RUDDER_SRV}/rudder/api/nodes/pending | jq --raw-output '.data.nodes | length')
|
|
else
|
|
fatal " Inventory discovery took too long, something must have fail - Exiting"
|
|
fi
|
|
done
|
|
|
|
info "Get the node ID from the server"
|
|
NODEID=$(curl -s -X GET -H 'Content-Type: application/json' -H "X-API-Token: ${RUDDER_API_TOKEN}" -H "X-API-Version: 12" ${RUDDER_SRV}/rudder/api/nodes/pending | jq --raw-output '.data.nodes[0].id')
|
|
|
|
info "Auto accept node"
|
|
curl -s -X POST -H "X-API-Version: latest" -H "X-API-Token: ${RUDDER_API_TOKEN}" ${RUDDER_SRV}/rudder/api/nodes/pending/${NODEID} -d "status=accepted" &>> /dev/null
|
|
|