From a8f03f4ef70c06cf9230fe9968245fc5e0308007 Mon Sep 17 00:00:00 2001 From: Dryusdan Date: Tue, 21 Apr 2020 22:18:28 +0200 Subject: [PATCH] Add all script --- deletehost.sh | 127 +++++++++++++++++++++++++ deployvm.sh | 249 ++++++++++++++++++++++++++++++++++++++++++++++++++ facts.sh | 187 +++++++++++++++++++++++++++++++++++++ resize.sh | 125 +++++++++++++++++++++++++ upgradecpu.sh | 119 ++++++++++++++++++++++++ upgraderam.sh | 118 ++++++++++++++++++++++++ 6 files changed, 925 insertions(+) create mode 100755 deletehost.sh create mode 100755 deployvm.sh create mode 100755 facts.sh create mode 100755 resize.sh create mode 100755 upgradecpu.sh create mode 100755 upgraderam.sh diff --git a/deletehost.sh b/deletehost.sh new file mode 100755 index 0000000..edd3eae --- /dev/null +++ b/deletehost.sh @@ -0,0 +1,127 @@ +#!/bin/bash +## author : Dryusdan +## date : 30/09/2019 +## description : A vm deployment +## usage : ./upgradevm.sh vmname ram restart + +## Bash strict mode #################################### +set -o errexit # abort on nonzero exitstatus +set -o nounset # abort on unbound variable +set -o pipefail # don't hide errors within pipes + +## Bash color ########################################## +# Set colors +RED='\033[0;31m' +GREEN='\033[00;32m' +YELLOW='\033[00;33m' +BLUE='\033[00;34m' +PURPLE='\033[00;35m' +CYAN='\033[00;36m' +LIGHTGRAY='\033[00;37m' +LRED='\033[01;31m' +LGREEN='\033[01;32m' +LYELLOW='\033[01;33m' +LBLUE='\033[01;34m' +LPURPLE='\033[01;35m' +LCYAN='\033[01;36m' +WHITE='\033[01;37m' +NC='\033[0m' # No Color + +## Logs ################################################ +readonly SCRIPTNAME="$(basename "$0")" +info() { echo -e "${LBLUE}[INFO] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } +warning() { echo -e "${YELLOW}[WARNING] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } +error() { echo -e "${LRED}[ERROR] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } +fatal() { echo -e "${RED}[FATAL] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; exit 1 ; } +######################################################## + +## Define variables #################################### +NETBOX_URL="https://netbox.exemple" +NETBOX_API_PATH="/api" +NETBOX_TOKEN="" + +PROXMOX_HOST="https://proxmox.exemple" +PROXMOX_USER="user" +PROXMOX_PASSWORD="" + +ZABBIX_USER="user" +ZABBIX_PASS="" +ZABBIX_SERVER="zabbix.tld" +ZABBIX_API="https://${ZABBIX_SERVER}/api_jsonrpc.php" +# First hostgroup of vm +ZABBIX_HOSTGROUPID1=2 +# second hostgroup of vm +ZABBIX_HOSTGROUPID2=15 +# First template of vm +ZABBIX_TEMPLATEID=10001 + +# Ansible path to run postinstall script +ASIBLE_PATH="/home/ansible/Ansible" + +RUDDER_API_TOKEN="" +RUDDER_SRV="https://rudder.exemple" + +####################################################### + +if [ $# -eq 0 ] +then + fatal "No arguments supplied. Usage : ./${SCRIPTNAME} vmname ram restart" +fi + +if [ -z "${1}" ]; +then + fatal "VMNAME is not defined. Usage : ./${SCRIPTNAME} vmname ram restart" +else + VMNAME="${1}" +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') + + +info "Search vm with name ${VMNAME}" +for node in $(curl -s --insecure -b "PVEAuthCookie=${PROXMOX_TOKEN}" "${PROXMOX_HOST}/api2/json/nodes" | jq --raw-output ".data[] | @base64") +do + nodename=$(echo ${node} | base64 --decode | jq --raw-output ".node") + VMID=$(curl -s --insecure -b "PVEAuthCookie=${PROXMOX_TOKEN}" "${PROXMOX_HOST}/api2/json/nodes/${nodename}/qemu" | jq --raw-output '.data[] | select(.name=="'${VMNAME}'") | .vmid') + if [ "${VMID}" != "" ] + then + info "Found vm ${VMNAME} with ID ${VMID} on ${nodename}" + break + fi +done + +info "Stopping VM" +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/${nodename}/qemu/${VMID}/status/shutdown" &> /dev/null + +info "Get token for 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 "Remove host from Zabbix" +HOSTID=$(curl -s -X GET -H 'Content-Type: application/json-rpc' -d '{"jsonrpc": "2.0","method": "host.get","params": {"filter": {"host": ["'${VMNAME}'"]}},"auth": "'${ZABBIX_AUTH_TOKEN}'","id": 1}' ${ZABBIX_API} | jq --raw-output '.result[0].hostid') +curl -s -X GET -H 'Content-Type: application/json-rpc' -d '{"jsonrpc": "2.0","method": "host.delete","params": ["'${HOSTID}'"],"auth": "'${ZABBIX_AUTH_TOKEN}'","id": 1}' ${ZABBIX_API} &> /dev/null + +info "Remove host from Ansible" +rm -f "${ANSIBLE_PATH}/host_vars/${VMNAME}" +sed -i "/${VMNAME}/d" "${ANSIBLE_PATH}/hosts" +sudo sed -i "/${VMNAME}/d" /etc/hosts + +info "Remove host from Prometheus" +sudo rm -f "/etc/prometheus/nodes/*${VMNAME}*" +sudo systemctl restart prometheus + +info "Remove host from Rudder" +RUDDER_ID=$(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" | jq --raw-output '.data.nodes[] | select(.hostname=="'${VMNAME}'") | .id') +curl -s -X DELETE -H 'Content-Type: application/json' -H "X-API-Token: ${RUDDER_API_TOKEN}" -H "X-API-Version: 12" "${RUDDER_SRV}/rudder/api/nodes/${RUDDER_ID}" &> /dev/null + +info "Remove host from Netbox" +clusterid=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/dcim/devices/?name=${nodename}" | jq --raw-output '.results[0].cluster.id') +deviceid=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/virtual-machines/?name=${VMNAME}" | jq --raw-output ".results[0].id") +curl -s -X DELETE -H "Content-Type: application/json" -H "Authorization: Token ${NETBOX_TOKEN}" "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/virtual-machines/${deviceid}/" &> /dev/null + +info "Remove host from Proxmox" +curl --insecure -H "Content-Type: application/x-www-form-urlencoded" -H "CSRFPreventionToken: ${PROXMOX_CSRF}" -b "PVEAuthCookie=${PROXMOX_TOKEN}" -X DELETE "${PROXMOX_HOST}/api2/json/nodes/${nodename}/qemu/${VMID}" &> /dev/null + +info "Ending" diff --git a/deployvm.sh b/deployvm.sh new file mode 100755 index 0000000..e32c4cb --- /dev/null +++ b/deployvm.sh @@ -0,0 +1,249 @@ +#!/bin/bash +## author : Dryusdan +## date : 30/09/2019 +## description : A vm deployment +## usage : ./deployvm hypervisor/auto templateID/auto/None os-version vm ram cpu + +## Bash strict mode #################################### +set -o errexit # abort on nonzero exitstatus +set -o nounset # abort on unbound variable +set -o pipefail # don't hide errors within pipes + +## Bash color ########################################## +# Set colors +RED='\033[0;31m' +GREEN='\033[00;32m' +YELLOW='\033[00;33m' +BLUE='\033[00;34m' +PURPLE='\033[00;35m' +CYAN='\033[00;36m' +LIGHTGRAY='\033[00;37m' +LRED='\033[01;31m' +LGREEN='\033[01;32m' +LYELLOW='\033[01;33m' +LBLUE='\033[01;34m' +LPURPLE='\033[01;35m' +LCYAN='\033[01;36m' +WHITE='\033[01;37m' +NC='\033[0m' # No Color + +## Logs ################################################ +readonly SCRIPTNAME="$(basename "$0")" +info() { echo -e "${LBLUE}[INFO] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } +warning() { echo -e "${YELLOW}[WARNING] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } +error() { echo -e "${LRED}[ERROR] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } +fatal() { echo -e "${RED}[FATAL] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; exit 1 ; } +######################################################## + +## Define variables #################################### +NETBOX_URL="https://netbox.exemple" +NETBOX_API_PATH="/api" +NETBOX_TOKEN="" + +PROXMOX_HOST="https://proxmox.exemple" +PROXMOX_USER="user" +PROXMOX_PASSWORD="" + +ZABBIX_USER="user" +ZABBIX_PASS="" +ZABBIX_SERVER="zabbix.example.fr" +ZABBIX_API="https://${ZABBIX_SERVER}/api_jsonrpc.php" +ZABBIX_HOSTGROUPID1=2 +ZABBIX_HOSTGROUPID2=15 +ZABBIX_TEMPLATEID=10001 + +ANSIBLE_PATH="/home/ansible/Ansible" + +RUDDER_API_TOKEN="" +RUDDER_SRV="https://rudder.exmple" + +UPGRADERAM="/home/ansible/adminscrips/upgraderam.sh" +UPGRADECPU="/home/ansible/adminscrips/upgradecpu.sh" +####################################################### + +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}" + #curl -s --insecure -b "PVEAuthCookie=${PROXMOX_TOKEN}" -x POST --data '{"node": "'${HYPERVISOR}'", "vmid": '${NEWID}', "format": "qcow2", "full": true, "name": "'${VMNAME}'"}' "${PROXMOX_HOST}/api2/json/nodes/${HYPERVISOR}/qemu/${VMTPLID}/clone" + +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}" +${UPGRADERAM} ${VMNAME} ${RAM} +${UPGRADECPU} ${VMNAME} ${CPU} +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 + +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}/g" ${ANSIBLE_PATH}/host_vars/${VMNAME} +sed -i "s//${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 postint.yml --limit=${VMNAME} +ansible-playbook -i hosts ferm.yml --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') + +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 + diff --git a/facts.sh b/facts.sh new file mode 100755 index 0000000..6838d11 --- /dev/null +++ b/facts.sh @@ -0,0 +1,187 @@ +#!/bin/bash +## author : Dryusdan +## date : 30/09/2019 +## description : A Nextcloud Update +## usage : ./nextcloud.sh + +## Bash strict mode #################################### +set -o errexit # abort on nonzero exitstatus +set -o nounset # abort on unbound variable +set -o pipefail # don't hide errors within pipes + +## Logs ################################################ +readonly SCRIPTNAME="$(basename "$0")" +info() { echo -e "[INFO] $* " | logger --tag "${SCRIPTNAME}" --stderr ; } +warning() { echo -e "[WARNING] $* " | logger --tag "${SCRIPTNAME}" --stderr ; } +error() { echo -e "[ERROR] $* " | logger --tag "${SCRIPTNAME}" --stderr ; } +fatal() { echo -e "[FATAL] $* " | logger --tag "${SCRIPTNAME}" --stderr ; exit 1 ; } +######################################################## + +## Define variables #################################### +NETBOX_URL="https://netbox.example" +NETBOX_API_PATH="/api" +NETBOX_TOKEN="" +FACTS_FOLDER="PAHT/TO/FACT/STORE/facts" + +PROXMOX_HOST="https://proxmox.example" +PROXMOX_USER="user" +PROXMOX_PASSWORD="" +####################################################### + +info "Get token for Proxmox" +PROXMOX_TOKEN=$(curl -s --insecure -d "username=${PROXMOX_USER}@pam&password=${PROXMOX_PASSWORD}" "${PROXMOX_HOST}/api2/json/access/ticket" | jq --raw-output '.data.ticket') + +info "Get Proxmox node" +for nodes in $(curl -s --insecure -b "PVEAuthCookie=${PROXMOX_TOKEN}" "${PROXMOX_HOST}/api2/json/nodes" | jq --raw-output '.data[] | @base64') +do + nodename=$(echo ${nodes} | base64 --decode | jq --raw-output '.node') + clusterid=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/dcim/devices/?name=${nodename}" | jq --raw-output '.results[0].cluster.id') + #for nodes in $(curl -s --insecure -b "PVEAuthCookie=${PROXMOX_TOKEN}" "${PROXMOX_HOST}/api2/json/nodes/" | jq --raw-output '.data[] | @base64') + info "Get VM" + for qemus in $(curl -s --insecure -b "PVEAuthCookie=${PROXMOX_TOKEN}" "${PROXMOX_HOST}/api2/json/nodes/${nodename}/qemu/" | jq --raw-output '.data[] | @base64') + do + vmname=$(echo ${qemus} | base64 --decode | jq --raw-output '.name') + if [ $(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/virtual-machines/?name=${vmname}" | jq --raw-output '.count') -eq 0 ] + then + curl -s -X POST -H "Content-Type: application/json" -H "Authorization: Token ${NETBOX_TOKEN}" --data '{"name": "'${vmname}'", "cluster": '${clusterid}', "role": 2}' "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/virtual-machines/" &> /dev/null + fi + done +done +info "Remove facts content" +/bin/rm -rf "${FACTS_FOLDER}"/* +info "Get facts" +/usr/bin/ansible -i "${HOME}/Ansible/hosts" all -m gather_facts -u root --tree "${FACTS_FOLDER}" &> /dev/null || /bin/true +info "Replace for Emeldiz" +/bin/mv ${FACTS_FOLDER}/emeldiz ${FACTS_FOLDER}/Emeldiz +info "Running read facts" +for fact in $(ls ${FACTS_FOLDER}) +do + server_facts="${FACTS_FOLDER}/${fact}" + device_name=$(cat "${server_facts}" | jq --raw-output ".ansible_facts.ansible_nodename") + info "Get data if device exist" + if [ $(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" ${NETBOX_URL}${NETBOX_API_PATH}/dcim/devices/?name=${device_name} | jq --raw-output ".count" ) -eq 1 ]; + then + info "${device_name} is a physical device" + DEVICE_URI="/dcim/devices/" + DEVICE_INT="/dcim/interfaces/" + DEVICE_REQUEST="device_id" + DATA_DEVICE="device" + else + info "${device_name} is a vm" + DEVICE_URI="/virtualization/virtual-machines/" + DEVICE_INT="/virtualization/interfaces/" + DEVICE_REQUEST="virtual_machine_id" + DATA_DEVICE="virtual_machine" + fi + device_id=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}${DEVICE_URI}?name=${device_name}" | jq --raw-output ".results[0].id") + if [ ${DATA_DEVICE} == "virtual_machine" ] + then + info "Get name and cluster id" + vm_info=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/virtual-machines/${device_id}/") + cluster_id=$(echo ${vm_info} | jq --raw-output ".cluster.id" ) + info "Get vCPU" + vcpu_netbox=$(echo ${vm_info} | jq --raw-output ".vcpus") + vcpu_facts=$(cat ${server_facts} | jq --raw-output '.ansible_facts["ansible_processor_vcpus"]') + if [ ${vcpu_netbox} != ${vcpu_facts} ] + then + warning "vCPU is not the same, updating" + curl -s -X PUT -H "Content-Type: application/json" -H "Authorization: Token ${NETBOX_TOKEN}" --data '{"name": "'${device_name}'", "cluster": '${cluster_id}', "vcpus": '${vcpu_facts}'}' "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/virtual-machines/${device_id}/" &> /dev/null + fi + info "Get Memory" + ram_netbox=$(echo ${vm_info} | jq --raw-output ".memory") + ram_facts=$(cat ${server_facts} | jq --raw-output '.ansible_facts["ansible_memtotal_mb"]') + ram_facts=$(echo "scale=4; ${ram_facts}/1000*1024" | bc -l | awk '{printf("%d\n",$1 + 0.5)}') + if [ ${ram_netbox} != ${ram_facts} ] + then + warning "RAM is not the same, updating" + curl -s -X PUT -H "Content-Type: application/json" -H "Authorization: Token ${NETBOX_TOKEN}" --data '{"name": "'${device_name}'", "cluster": '${cluster_id}', "memory": '${ram_facts}'}' "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/virtual-machines/${device_id}/" &> /dev/null + fi + info "Get disk size" + disk_netbox=$(echo ${vm_info} | jq --raw-output ".disk") + disk_facts=0 + for disk_mount in $(cat ${server_facts} | jq --raw-output ".ansible_facts.ansible_mounts[] | values | .size_total") + do + disk_facts=$(echo "${disk_facts}+${disk_mount}" | bc) + done + disk_facts=$(echo "scale=4; ${disk_facts}/1000*1024/1024/1024/1024" | bc -l | awk '{printf("%d\n",$1 + 0.5)}') + if [ ${disk_netbox} != ${disk_facts} ] + then + warning "Disk is not the same, updating" + curl -s -X PUT -H "Content-Type: application/json" -H "Authorization: Token ${NETBOX_TOKEN}" --data '{"name": "'${device_name}'", "cluster": '${cluster_id}', "disk": '${disk_facts}'}' "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/virtual-machines/${device_id}/" &> /dev/null + fi + info "Get primary IPv4" + idip_netbox=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/virtual-machines/${device_id}/" | jq --raw-output ".primary_ip4.id") + idip_facts="0" + ip_facts=$(cat ${server_facts} | jq --raw-output '.ansible_facts.ansible_default_ipv4.address') + if [ $(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/ipam/ip-addresses/?address=${ip_facts}" | jq --raw-output ".count") -eq 1 ]; + then + info "Get IP ID" + idip_facts=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/ipam/ip-addresses/?address=${ip_facts}" | jq --raw-output ".results[0].id") + fi + if [ ${idip_netbox} != ${idip_facts} ] + then + warning "IPv4 is not the same, updating" + curl -s -X PUT -H "Content-Type: application/json" -H "Authorization: Token ${NETBOX_TOKEN}" --data '{"name": "'${device_name}'", "cluster": '${cluster_id}', "primary_ip4": '${idip_facts}'}' "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/virtual-machines/${device_id}/" &> /dev/null + fi + fi + for interface in $(cat ${server_facts} | jq --raw-output ".ansible_facts.ansible_interfaces | values | .[]") + do + if [ $(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}${DEVICE_INT}?name=${interface}&${DEVICE_REQUEST}=${device_id}" | jq --raw-output ".count") -eq 0 ]; + then + warning "Create new interface called ${interface}" + curl -s -X POST -H "Content-Type: application/json" -H "Authorization: Token ${NETBOX_TOKEN}" --data '{"'${DATA_DEVICE}'": '${device_id}',"name": "'${interface}'"}' "${NETBOX_URL}${NETBOX_API_PATH}${DEVICE_INT}" &> /dev/null + else + info "${interface} exist" + fi + interface_id=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}${DEVICE_INT}?name=${interface}&${DEVICE_REQUEST}=${device_id}" | jq --raw-output ".results[0].id" ) + info "Check mac address" + mac_address=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}${DEVICE_INT}${interface_id}/" | jq --raw-output ".mac_address") + macaddress=$(cat ${server_facts} | jq --raw-output '.ansible_facts["ansible_'${interface}'"]["macaddress"]') + if [ "${mac_address^^}" != "${macaddress^^}" ]; + then + warning "Updating ${interface} MAC address to ${macaddress^^}" + curl -s -X PATCH -H "Content-Type: application/json" -H "Authorization: Token ${NETBOX_TOKEN}" --data '{"'${DATA_DEVICE}'": '${device_id}',"name": "'${interface}'", "mac_address": "'${macaddress^^}'"}' "${NETBOX_URL}${NETBOX_API_PATH}${DEVICE_INT}${interface_id}/" &> /dev/null + fi + info "Check MTU" + mtu_netbox=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}${DEVICE_INT}${interface_id}/" | jq --raw-output ".mtu") + mtu=$(cat ${server_facts} | jq --raw-output '.ansible_facts["ansible_'${interface}'"]["mtu"]') + if [ "${mtu_netbox}" != "${mtu}" ]; + then + warning "Change MTU to ${mtu}" + curl -s -X PATCH -H "Content-Type: application/json" -H "Authorization: Token ${NETBOX_TOKEN}" --data '{"'${DATA_DEVICE}'": '${device_id}',"name": "'${interface}'", "mtu": '${mtu}'}' "${NETBOX_URL}${NETBOX_API_PATH}${DEVICE_INT}${interface_id}/" &> /dev/null + fi + ipv4=$(cat ${server_facts} | jq --raw-output '.ansible_facts["ansible_'${interface}'"]["ipv4"]["address"]') + broadcast=$(cat ${server_facts} | jq --raw-output '.ansible_facts["ansible_'${interface}'"]["ipv4"]["broadcast"]') + netmask=$(cat ${server_facts} | jq --raw-output '.ansible_facts["ansible_'${interface}'"]["ipv4"]["netmask"]') + network=$(cat ${server_facts} | jq --raw-output '.ansible_facts["ansible_'${interface}'"]["ipv4"]["network"]') + if [ ${ipv4} != null ] + then + info "IPv4 exist" + if [ $(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/ipam/ip-addresses/?interface_id=${interface_id}&?address=${ipv4}" | jq --raw-output ".count") -eq 0 ] + then + vrfidipv4=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/ipam/prefixes/?prefix=${ipv4}/${netmask}" | jq --raw-output '.results[0].vrf.id') + echo "${NETBOX_URL}${NETBOX_API_PATH}/ipam/prefixes/?prefix=${ipv4}/${netmask}" + echo '{"address": "'${ipv4}'/'${netmask}'","vrf": '${vrfidipv4}', "status": "active", "interface": '${interface_id}'}' + curl -s -X POST -H "Content-Type: application/json" -H "Authorization: Token ${NETBOX_TOKEN}" --data '{"address": "'${ipv4}'/'${netmask}'","vrf": '${vrfidipv4}', "status": "active", "interface": '${interface_id}'}' "${NETBOX_URL}${NETBOX_API_PATH}/ipam/ip-addresses/" &> /dev/null + fi + else + error "${interface} haven't any IPv4" + fi + if [ "$(cat ${server_facts} | jq --raw-output '.ansible_facts["ansible_'${interface}'"]["ipv6"]')" != null ] + then + for ipv6s in $(cat ${server_facts} | jq --raw-output '.ansible_facts["ansible_'${interface}'"]["ipv6"][] | @base64') + do + ipv6=$(echo ${ipv6s} | base64 --decode | jq --raw-output '.address') + prefix=$(echo ${ipv6s} | base64 --decode | jq --raw-output '.prefix') + if [ $(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/ipam/ip-addresses/?interface_id=${interface_id}&?address=${ipv6}" | jq --raw-output ".count") -eq 0 ] + then + warning "Adding ${ipv6}/${prefix}" + vrfidipv6=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/ipam/prefixes/?prefix=${ipv6}/${prefix}" | jq --raw-output '.results[0].vrf.id') + curl -s -X POST -H "Content-Type: application/json" -H "Authorization: Token ${NETBOX_TOKEN}" --data '{"address": "'${ipv6}'/'${prefix}'","vrf": '${vrfidipv6}', "status": "active", "interface": '${interface_id}'}' "${NETBOX_URL}${NETBOX_API_PATH}/ipam/ip-addresses/" &> /dev/null + fi + done + else + error "${interface} haven't any IPv6" + fi + done +done diff --git a/resize.sh b/resize.sh new file mode 100755 index 0000000..79a9ef1 --- /dev/null +++ b/resize.sh @@ -0,0 +1,125 @@ + +#!/bin/bash +## author : Dryusdan +## date : 30/09/2019 +## description : A vm deployment +## usage : ./deployvm VMName resize + +## Bash strict mode #################################### +set -o errexit # abort on nonzero exitstatus +set -o nounset # abort on unbound variable +set -o pipefail # don't hide errors within pipes + +## Bash color ########################################## +# Set colors +RED='\033[0;31m' +GREEN='\033[00;32m' +YELLOW='\033[00;33m' +BLUE='\033[00;34m' +PURPLE='\033[00;35m' +CYAN='\033[00;36m' +LIGHTGRAY='\033[00;37m' +LRED='\033[01;31m' +LGREEN='\033[01;32m' +LYELLOW='\033[01;33m' +LBLUE='\033[01;34m' +LPURPLE='\033[01;35m' +LCYAN='\033[01;36m' +WHITE='\033[01;37m' +NC='\033[0m' # No Color + +## Logs ################################################ +readonly SCRIPTNAME="$(basename "$0")" +info() { echo -e "${LBLUE}[INFO] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } +warning() { echo -e "${YELLOW}[WARNING] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } +error() { echo -e "${LRED}[ERROR] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } +fatal() { echo -e "${RED}[FATAL] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; exit 1 ; } +######################################################## + +## Define variables #################################### +NETBOX_URL="https://netbox.example" +NETBOX_API_PATH="/api" +NETBOX_TOKEN="" + +PROXMOX_HOST="https://proxmox.exemple" +PROXMOX_USER="user" +PROXMOX_PASSWORD="" +# Var to run postinstall +ANSIBLE_PATH="" + +####################################################### + +if [ $# -eq 0 ] +then + fatal "No arguments supplied. Usage : ./${SCRIPTNAME} VMName resize " +fi + +if [ -z "${1}" ]; +then + fatal "VMNAME is not defined. Usage : ./${SCRIPTNAME} VMName resize" +else + VMNAME="${1}" +fi + +if [ -z "${2}" ]; +then + fatal "Resize not defined. Usage : ./${SCRITNAME} VMName resize" +else + RESIZE="${2}" +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') + + +info "Search vm with name ${VMNAME}" +for node in $(curl -s --insecure -b "PVEAuthCookie=${PROXMOX_TOKEN}" "${PROXMOX_HOST}/api2/json/nodes" | jq --raw-output ".data[] | @base64") +do + nodename=$(echo ${node} | base64 --decode | jq --raw-output ".node") + VMID=$(curl -s --insecure -b "PVEAuthCookie=${PROXMOX_TOKEN}" "${PROXMOX_HOST}/api2/json/nodes/${nodename}/qemu" | jq --raw-output '.data[] | select(.name=="'${VMNAME}'") | .vmid') + if [ "${VMID}" != "" ] + then + info "Found vm ${VMNAME} with ID ${VMID} on ${nodename}" + break + fi +done + +info "Get actual disk size" +ACTUALDISKSIZE=$(curl -s --insecure -b "PVEAuthCookie=${PROXMOX_TOKEN}" "${PROXMOX_HOST}/api2/json/nodes/${nodename}/qemu" | jq --raw-output '.data[] | select(.name=="'${VMNAME}'") | .maxdisk') +NEWDISKSIZE=$(echo "${ACTUALDISKSIZE} + ${RESIZE}*1024*1024*1024" | bc ) + +info "Resizing ${VMNAME} with ${RESIZE}GB" +curl -s --insecure -H "Content-Type: application/x-www-form-urlencoded" -H "CSRFPreventionToken: ${PROXMOX_CSRF}" -b "PVEAuthCookie=${PROXMOX_TOKEN}" -X PUT --data "size=${NEWDISKSIZE}&disk=scsi0" "${PROXMOX_HOST}/api2/json/nodes/${nodename}/qemu/${VMID}/resize" &> /dev/null + +info "Wait 30 seconds for hypervisor synchro" +sleep 30 + +info "Resize /dev/sda2" +ssh root@${VMNAME} parted /dev/sda resizepart 2 100% &> /dev/null + +info "Resize /dev/sda5" +ssh root@${VMNAME} parted /dev/sda resizepart 5 100% &> /dev/null + +info "Resize LVM partition" +ssh root@${VMNAME} pvresize /dev/sda5 &> /dev/null + +info "Get partition" +VGNAME=$(ssh root@${VMNAME} ls /dev/mapper | grep vg) &> /dev/null + +info "Extend partition" +ssh root@${VMNAME} lvresize --extents +100%FREE /dev/mapper/${VGNAME} &> /dev/null + +info "Resize FS" +ssh root@${VMNAME} resize2fs /dev/mapper/${VGNAME} &> /dev/null + +info "Update Netbox" +clusterid=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/dcim/devices/?name=${nodename}" | jq --raw-output '.results[0].cluster.id') +deviceid=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/virtual-machines/?name=${VMNAME}" | jq --raw-output ".results[0].id") +GBSIZE=$(echo ${ACTUALDISKSIZE}/1024/1024/1024 + ${RESIZE} | bc) +curl -s -X PUT -H "Content-Type: application/json" -H "Authorization: Token ${NETBOX_TOKEN}" --data '{"name": "'${VMNAME}'", "cluster": '${clusterid}', "disk": '${GBSIZE}'}' "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/virtual-machines/${deviceid}/" &> /dev/null +info "Update finish" +info "End" + +info "Ending" diff --git a/upgradecpu.sh b/upgradecpu.sh new file mode 100755 index 0000000..c4fc61d --- /dev/null +++ b/upgradecpu.sh @@ -0,0 +1,119 @@ +#!/bin/bash +## author : Dryusdan +## date : 30/09/2019 +## description : A vm deployment +## usage : ./upgradecpu.sh vmname cpu restart + +## Bash strict mode #################################### +set -o errexit # abort on nonzero exitstatus +set -o nounset # abort on unbound variable +set -o pipefail # don't hide errors within pipes + +## Bash color ########################################## +# Set colors +RED='\033[0;31m' +GREEN='\033[00;32m' +YELLOW='\033[00;33m' +BLUE='\033[00;34m' +PURPLE='\033[00;35m' +CYAN='\033[00;36m' +LIGHTGRAY='\033[00;37m' +LRED='\033[01;31m' +LGREEN='\033[01;32m' +LYELLOW='\033[01;33m' +LBLUE='\033[01;34m' +LPURPLE='\033[01;35m' +LCYAN='\033[01;36m' +WHITE='\033[01;37m' +NC='\033[0m' # No Color + +## Logs ################################################ +readonly SCRIPTNAME="$(basename "$0")" +info() { echo -e "${LBLUE}[INFO] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } +warning() { echo -e "${YELLOW}[WARNING] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } +error() { echo -e "${LRED}[ERROR] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } +fatal() { echo -e "${RED}[FATAL] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; exit 1 ; } +######################################################## + +## Define variables #################################### +NETBOX_URL="https://netbox.example" +NETBOX_API_PATH="/api" +NETBOX_TOKEN="" + +PROXMOX_HOST="https://proxmox.example" +PROXMOX_USER="user" +PROXMOX_PASSWORD="" + +####################################################### + +if [ $# -eq 0 ] +then + fatal "No arguments supplied. Usage : ./${SCRIPTNAME} vmname cpu restart" +fi + +if [ -z "${1+x}" ]; +then + fatal "VMNAME is not defined. Usage : ./${SCRIPTNAME} vmname cpu restart" +else + VMNAME="${1}" +fi + +if [ -z "${2+x}" ]; +then + fatal "CPU is not defined. Usage : ./${SCRIPTNAME} vmname cpu restart" +else + CPU="${2}" +fi + +if [ -z "${3+x}" ]; +then + RESTART="false" +else + RESTART="true" +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') + +info "Search vm with name ${VMNAME}" +for node in $(curl -s --insecure -b "PVEAuthCookie=${PROXMOX_TOKEN}" "${PROXMOX_HOST}/api2/json/nodes" | jq --raw-output ".data[] | @base64") +do + nodename=$(echo ${node} | base64 --decode | jq --raw-output ".node") + VMID=$(curl -s --insecure -b "PVEAuthCookie=${PROXMOX_TOKEN}" "${PROXMOX_HOST}/api2/json/nodes/${nodename}/qemu" | jq --raw-output '.data[] | select(.name=="'${VMNAME}'") | .vmid') + if [ "${VMID}" != "" ] + then + info "Found vm ${VMNAME} with ID ${VMID} on ${nodename}" + break + fi +done + +info "Upgrade vCPU to ${CPU}" +curl -s --insecure -H "Content-Type: application/x-www-form-urlencoded" -H "CSRFPreventionToken: ${PROXMOX_CSRF}" -b "PVEAuthCookie=${PROXMOX_TOKEN}" -X PUT -d "cores=${CPU}" "${PROXMOX_HOST}/api2/json/nodes/${nodename}/qemu/${VMID}/config" &> /dev/null + +if [ "${RESTART}" == "true" ] +then + info "Requested restart" + info "Stopping VM" + 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/${nodename}/qemu/${VMID}/status/shutdown" &> /dev/null + sleep 1 + RUNNING=$(curl -s --insecure -H "Content-Type: application/x-www-form-urlencoded" -H "CSRFPreventionToken: ${PROXMOX_CSRF}" -b "PVEAuthCookie=${PROXMOX_TOKEN}" -X GET "${PROXMOX_HOST}/api2/json/nodes/${nodename}/qemu/${VMID}/status/current" | jq --raw-output '.data.status') + while [ ${RUNNING} == "running" ] + do + sleep 5 + RUNNING=$(curl -s --insecure -H "Content-Type: application/x-www-form-urlencoded" -H "CSRFPreventionToken: ${PROXMOX_CSRF}" -b "PVEAuthCookie=${PROXMOX_TOKEN}" -X GET "${PROXMOX_HOST}/api2/json/nodes/${nodename}/qemu/${VMID}/status/current" | jq --raw-output '.data.status') + done + info "Starting VM" + 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/${nodename}/qemu/${VMID}/status/start" &> /dev/null +else + info "No restarting" +fi + +info "Update Netbox" +clusterid=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/dcim/devices/?name=${nodename}" | jq --raw-output '.results[0].cluster.id') +deviceid=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/virtual-machines/?name=${VMNAME}" | jq --raw-output ".results[0].id") +info "update" +curl -s -X PUT -H "Content-Type: application/json" -H "Authorization: Token ${NETBOX_TOKEN}" --data '{"name": "'${VMNAME}'", "cluster": '${clusterid}', "vcpu": '${CPU}'}' "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/virtual-machines/${deviceid}/" &> /dev/null +info "Update finish" +info "End" diff --git a/upgraderam.sh b/upgraderam.sh new file mode 100755 index 0000000..dbb8f68 --- /dev/null +++ b/upgraderam.sh @@ -0,0 +1,118 @@ +#!/bin/bash +## author : Dryusdan +## date : 30/09/2019 +## description : A vm deployment +## usage : ./upgradevm.sh vmname ram restart + +## Bash strict mode #################################### +set -o errexit # abort on nonzero exitstatus +set -o nounset # abort on unbound variable +set -o pipefail # don't hide errors within pipes + +## Bash color ########################################## +# Set colors +RED='\033[0;31m' +GREEN='\033[00;32m' +YELLOW='\033[00;33m' +BLUE='\033[00;34m' +PURPLE='\033[00;35m' +CYAN='\033[00;36m' +LIGHTGRAY='\033[00;37m' +LRED='\033[01;31m' +LGREEN='\033[01;32m' +LYELLOW='\033[01;33m' +LBLUE='\033[01;34m' +LPURPLE='\033[01;35m' +LCYAN='\033[01;36m' +WHITE='\033[01;37m' +NC='\033[0m' # No Color + +## Logs ################################################ +readonly SCRIPTNAME="$(basename "$0")" +info() { echo -e "${LBLUE}[INFO] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } +warning() { echo -e "${YELLOW}[WARNING] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } +error() { echo -e "${LRED}[ERROR] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; } +fatal() { echo -e "${RED}[FATAL] $* ${NC}" | logger --tag "${SCRIPTNAME}" --stderr ; exit 1 ; } +######################################################## + +## Define variables #################################### +NETBOX_URL="https://netbox.example" +NETBOX_API_PATH="/api" +NETBOX_TOKEN="" + +PROXMOX_HOST="https://proxmox.example" +PROXMOX_USER="user" +PROXMOX_PASSWORD="" + +####################################################### + +if [ $# -eq 0 ] +then + fatal "No arguments supplied. Usage : ./${SCRIPTNAME} vmname ram restart" +fi + +if [ -z "${1+x}" ]; +then + fatal "VMNAME is not defined. Usage : ./${SCRIPTNAME} vmname ram restart" +else + VMNAME="${1}" +fi + +if [ -z "${2+x}" ]; +then + fatal "VM Template ID is not defined. Usage : ./${SCRIPTNAME} vmname ram restart" +else + RAM="${2}" +fi + +if [ -z "${3+x}" ]; +then + RESTART="false" +else + RESTART="true" +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') + +info "Search vm with name ${VMNAME}" +for node in $(curl -s --insecure -b "PVEAuthCookie=${PROXMOX_TOKEN}" "${PROXMOX_HOST}/api2/json/nodes" | jq --raw-output ".data[] | @base64") +do + nodename=$(echo ${node} | base64 --decode | jq --raw-output ".node") + VMID=$(curl -s --insecure -b "PVEAuthCookie=${PROXMOX_TOKEN}" "${PROXMOX_HOST}/api2/json/nodes/${nodename}/qemu" | jq --raw-output '.data[] | select(.name=="'${VMNAME}'") | .vmid') + if [ "${VMID}" != "" ] + then + info "Found vm ${VMNAME} with ID ${VMID} on ${nodename}" + break + fi +done + +info "Upgrade RAM to ${RAM}MB" +curl -s --insecure -H "Content-Type: application/x-www-form-urlencoded" -H "CSRFPreventionToken: ${PROXMOX_CSRF}" -b "PVEAuthCookie=${PROXMOX_TOKEN}" -X PUT -d "memory=${RAM}" "${PROXMOX_HOST}/api2/json/nodes/${nodename}/qemu/${VMID}/config" &> /dev/null + +if [ "${RESTART}" == "true" ] +then + info "Requested restart" + info "Stopping VM" + 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/${nodename}/qemu/${VMID}/status/shutdown" &> /dev/null + sleep 1 + RUNNING=$(curl -s --insecure -H "Content-Type: application/x-www-form-urlencoded" -H "CSRFPreventionToken: ${PROXMOX_CSRF}" -b "PVEAuthCookie=${PROXMOX_TOKEN}" -X GET "${PROXMOX_HOST}/api2/json/nodes/${nodename}/qemu/${VMID}/status/current" | jq --raw-output '.data.status') + while [ ${RUNNING} == "running" ] + do + sleep 5 + RUNNING=$(curl -s --insecure -H "Content-Type: application/x-www-form-urlencoded" -H "CSRFPreventionToken: ${PROXMOX_CSRF}" -b "PVEAuthCookie=${PROXMOX_TOKEN}" -X GET "${PROXMOX_HOST}/api2/json/nodes/${nodename}/qemu/${VMID}/status/current" | jq --raw-output '.data.status') + done + info "Starting VM" + 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/${nodename}/qemu/${VMID}/status/start" &> /dev/null +else + info "No restarting" +fi + +info "Update Netbox" +clusterid=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/dcim/devices/?name=${nodename}" | jq --raw-output '.results[0].cluster.id') +deviceid=$(curl -s -X GET -H "Authorization: Token ${NETBOX_TOKEN}" -H "Accept: application/json; indent=4" "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/virtual-machines/?name=${VMNAME}" | jq --raw-output ".results[0].id") +info "update" +curl -s -X PUT -H "Content-Type: application/json" -H "Authorization: Token ${NETBOX_TOKEN}" --data '{"name": "'${VMNAME}'", "cluster": '${clusterid}', "memory": '${RAM}'}' "${NETBOX_URL}${NETBOX_API_PATH}/virtualization/virtual-machines/${deviceid}/" &> /dev/null +info "Update finish" +info "End"