Mercurial > hg > cc > azure
changeset 7:a7637c994964
cull_network.py, parse_load_balance.py, vmss_setup.sh x 2, vmss_create.sh:
From kenneth, slight mods in some cases
share.sh:
Distribute files to workers
wrun.sh, invoke.sh:
From last year, slight mods
author | Henry S. Thompson <ht@markup.co.uk> |
---|---|
date | Sun, 30 Sep 2018 20:53:43 +0000 |
parents | a3b30e707e83 |
children | 5db6015689a2 |
files | master/bin/cull_network.py master/bin/internal/invoke.sh master/bin/internal/parse_load_balance.py master/bin/internal/vmss_setup.sh master/bin/share.sh master/bin/vmss_create.sh master/bin/vmss_setup.sh master/bin/wrun.sh |
diffstat | 8 files changed, 242 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/bin/cull_network.py Sun Sep 30 20:53:43 2018 +0000 @@ -0,0 +1,50 @@ +#!/usr/bin/env python2 +#Print commands to delete load balancers, NICs, and IPs not attached to any VM +#Plenty of bugs here. Assumes a stock setup with nothing fancy. +import json +import subprocess + +def query(command): + return json.load(subprocess.Popen(command, stdout=subprocess.PIPE).stdout) + +lb = query(["az", "network", "lb", "list", "-o", "json"]) +vmss = query(["az", "vmss", "list", "-o", "json"]) + +in_use_lbs = [] +for m in vmss: + balancer = m["virtualMachineProfile"]["networkProfile"]["networkInterfaceConfigurations"][0]["ipConfigurations"][0]["loadBalancerBackendAddressPools"] + if balancer: + in_use_lbs.append('/'.join(balancer[0]["id"].split('/')[0:9])) + +allocated_lbs = ['/'.join(l["frontendIpConfigurations"][0]["id"].split('/')[0:9]) for l in lb] + +unused_lbs = set(allocated_lbs) - set(in_use_lbs) +for l in unused_lbs: + split = l.split('/') + print "az network lb delete -g " + split[4] + " -n " + split[8] + +#TODO: exclude the lbs that are to be deleted +ip_used_by_lb = [l["frontendIpConfigurations"][0]["publicIpAddress"]["id"] for l in lb] + + +vm = query(["az", "vm", "list", "-o", "json"]) +in_use_nics = [v["networkProfile"]["networkInterfaces"][0]["id"] for v in vm] +nics = query(["az", "network", "nic", "list", "-o", "json"]) +allocated_nics = [n["id"] for n in nics] +for n in set(allocated_nics) - set(in_use_nics): + split = n.split('/') + print "az network nic delete -g " + split[4] + " -n " + split[8] + +#TODO: exclude the nics that are to be deleted +ip_used_by_nic = [n["ipConfigurations"][0]["publicIpAddress"]["id"] for n in nics] +in_use_ips = ip_used_by_lb + ip_used_by_nic + +allocated_ips = [i["id"] for i in query(["az", "network", "public-ip", "list", "-o", "json"])] +for i in set(allocated_ips) - set(in_use_ips): + split = i.split('/') + print "az network public-ip delete -g " + split[4] + " -n " + split[8] + +nsg_all = [n['id'] for n in query(["az", "network", "nsg", "list", "-o", "json"])] +for i in set(nsg_all) - set([n['networkSecurityGroup']['id'] for n in nics]): + split = i.split('/') + print "az network nsg delete -g " + split[4] + " -n " + split[8]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/bin/internal/invoke.sh Sun Sep 30 20:53:43 2018 +0000 @@ -0,0 +1,32 @@ +#!/bin/bash +# Helper for ../wrun, q.v. +# Usage: invoke.sh [-x] me cmd ifile id port ip [args...] +# Runs +# cmd [id] args... +# via ssh to ip:port +# If ifile is not /dev/null, feed in as stdin +# Unless -x, worker id is passed as first arg +if [ "$1" = "-x" ] +then + shift + id= + me= +else + me=$1 + id=$4 +fi +cmd="$2" +ifile=$3 +port=$5 +ip=$6 +shift 6 +echo "#$(date)#$cmd#$ifile#$id#$port#$ip#$@#" 1>&2 +if [ "$ifile" != "/dev/null" ] +then + echo "# from $ifile" 1>&2 + scp -P $port $ifile $ip:ifile.txt && \ + ssh -t -p $port $ip "nohup $cmd $id $me ""$@"" > nohup.cc" +else + ssh -p $port $ip "$cmd $id $me ""$@" +fi || echo ssh failed, status=$? 1>&2 +echo "#$(date)#$id#" 1>&2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/bin/internal/parse_load_balance.py Sun Sep 30 20:53:43 2018 +0000 @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +#Parses the output of az network lb show --resource-group $resource --name ${name}LB -o json +#Prints a table of instanceId and port. +import sys +import json +if len(sys.argv) == 2: + ip = " " + sys.argv[1] +else: + ip = "" +for m in json.load(sys.stdin)['inboundNatRules']: + print(m['name'].split('.')[-1] + ' ' + str(m['frontendPort']) + ip)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/bin/internal/vmss_setup.sh Sun Sep 30 20:53:43 2018 +0000 @@ -0,0 +1,15 @@ +#!/bin/bash +set -e +#Arguments are instance port host --resource-group $resource --name $name +instance=$1 +port=$2 +host=$3 +shift 3 +#Accept host keys :-( +if ! ssh-keyscan -p $port $host >>~/.ssh/known_hosts 2>/dev/null; then + echo $host:$port does not seem to be up, might be overprovisioned 1>&2 + exit 1 +fi +#Copy azure credentials over and make delete/deallocate commands +(echo $@ --instance-ids $instance; cd ~; tar c .azure) |ssh -o ConnectTimeout=5 -p $port $host 'read a; echo -e '\''#!/bin/bash\n'\''az vmss deallocate $a >deallocate && echo -e '\''#!/bin/bash\n'\''az vmss delete-instances $a >delete && chmod +x deallocate delete && tar x && sudo mv deallocate delete /bin' +echo ssh -p $port $host " #id $instance"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/bin/share.sh Sun Sep 30 20:53:43 2018 +0000 @@ -0,0 +1,33 @@ +#!/bin/bash +# Share file(s) with all workers in a scale set +if [ $# -lt 2 ]; then + cat 1>&2 <<EOF +Usage: $0 SSname [-d dir] files... +Where name is the name of a VM scale set. + +Distribute files to every machine in the SS named SSname + if -d, into dir, otherwise home directory + by doing as it were + tar -czf - files | ssh machine "[cd $dir &&] tar -xzf -" +EOF + exit 1 +fi +group=cc +name=$1 +shift +if [ "$1" = "-d" ] +then + dodir="cd $2 && " + shift 2 +else + dodir="" +fi +cmd="${dodir}tar -xzf -" +np=$(az vmss get-instance-view -g $group -n $name | jq '.virtualMachine.statusesSummary | .[0].count') +echo "|$name|$cmd|$@|$np|" 1>&2 +az vmss list-instance-connection-info -g $group -n $name | tr -s ',": ' '\t' | \ + tail -n +2 | head -$np |cut -f 3-5 | tee /dev/stderr |\ + while read id ip port + do tar -czf - "$@" | "$(dirname "$0")"/internal/invoke.sh -x "" bash /dev/null "" $port $ip -c \""$cmd"\" + done +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/bin/vmss_create.sh Sun Sep 30 20:53:43 2018 +0000 @@ -0,0 +1,13 @@ +#!/bin/bash +set -e +if ([ "$1" != "--resource-group" ] && [ "$1" != "-g" ]) || ([ "$3" != "--name" ] && [ "$3" != "-n" ]); then + cat 1>&2 <<EOF +Usage: $0 --resource-group group --name name ... +All arguments are forwarded to az vmss create, so see that for help. +However, you must have --resource-group group --name name at the beginning. +That way they can be passed to $(dirname "$0")/vmss_setup.sh +EOF +fi +az vmss create "$@" +echo created, setting up... +"$(dirname "$0")"/vmss_setup.sh $1 $2 $3 $4
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/bin/vmss_setup.sh Sun Sep 30 20:53:43 2018 +0000 @@ -0,0 +1,20 @@ +#!/bin/bash +set -e -o pipefail +if [ $# != 4 ]; then + cat 1>&2 <<EOF +Usage: $0 --resource-group group --name name +Where name is the name of a VM scale set." + +This script: +1. Insecurely gets SSH host keys and adds them to your ~/.ssh/known_hosts . +2. Copies your ~/.azure to the machines so they have command line access. +3. Installs delete and deallocate commands so you can stop them from inside. +4. Prints SSH connection information. +EOF + exit 1 +fi +ip=$(az vmss list-instance-connection-info $@ --output tsv | head -n 1 | cut -d : -f 1) +echo IP address $ip 1>&2 +az network lb show $1 $2 $3 ${4}LB --o json | \ + "$(dirname "$0")"/internal/parse_load_balance.py $ip | \ + parallel --gnu --colsep ' ' "$(dirname "$0")"/internal/vmss_setup.sh {} $@
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/master/bin/wrun.sh Sun Sep 30 20:53:43 2018 +0000 @@ -0,0 +1,68 @@ +#!/bin/bash +set -e -o pipefail +if [ $# -lt 2 ]; then + cat 1>&2 <<EOF +Usage: $0 SSname cmd [-x] [-np n] [-f file] [...args] +Where name is the name of a VM scale set. + +Runs cmd on every machine in a scale set, + passing args and, + if -f, one line from file per worker + unless -x, worker id + by doing as it were + [ echo line-from-file |] ssh machine "$cmd [id] "$args"" +EOF + exit 1 +fi +group=cc +name=$1 +cmd="$2" +shift 2 +if [ "$1" = "-x" ] +then + id=-x + shift +else + id= +fi +if [ "$1" = "-np" ] +then + np=$2 + shift + shift +else + np=$(az vmss get-instance-view -g $group -n $name | jq '.virtualMachine.statusesSummary | .[0].count') +fi +echo "|$name|$cmd|$@|$np|" 1>&2 +me=$(az vm list-ip-addresses -g cc -n Deb1 | jq -r '.[0].virtualMachine.network.publicIpAddresses|.[0].ipAddress') +echo me=$me 1>&2 +if [ "$1" = "-f" ] +then + file=$2 + shift 2 + tfile=$(mktemp) + split -n r/$np -u --filter="cat > $tfile\$\$" $file & + # Wait for fifos to be built + while [ $np -gt $(ls ${tfile}* | wc -l) ]; do echo -n . 1>&2; sleep 1; done + echo 1>&2 + wc -l ${tfile}* 1>&2 +else + file=/dev/null +fi +echo "|$np|$file|$tfile|" 1>&2 +paste -d ' ' \ + <(if [ "$file" = "/dev/null" ] + then yes /dev/null|head -$np + else + echo ${tfile}?* | tr ' ' '\012' # the name of the file of + # input lines for each worker + fi + ) \ + <(az vmss list-instance-connection-info -g $group -n $name | tr -s ',": ' '\t' | \ + tail -n +2 | head -$np |cut -f 3-5 | \ + while read i ip port + do + echo $i $port $ip + done) | \ + parallel --gnu --colsep ' ' -j $np "$(dirname "$0")"/internal/invoke.sh $id $me "$cmd" {} "$@" || { r=$? ; echo parallel exited with status=$r 1>&2;} +if [ "${tfile}" ]; then rm ${tfile}*; fi