#!/bin/bash # Creates a new node by cloning the base (if necessary) and setting network # interface configuration. # # Example usage: # vn-newnode --node 2 --file ~/svn/virtnet/data/topologies/interfaces-topology-02-node-02 --iface neta --iface netb # creates a virtual machine called node2 using the interfaces file # interfaces-topology-02-node-2 and sets the internal network names for NIC2 and NIC3 # to neta and netb, respectively. # # Assumptions: # The base VM includes the virtnet SVN repository (specifically the # relevant interfaces files in data/topologies/) # # Design: # 1. Read the command line input parameters # 2. Clone the base VM to create the node # 3. Set the virtual NICs on the node by using VBoxManage modifyvm # 4. Set the hostname, forwarding and interfaces file on the node using # ssh # 5. Poweroff the node # # For more info see: http://sandilands.info/sgordon/virtnet # # $Revision$ # $Author$ # $Date$ # $URL$ # Script parameters # The name of the virtual machine to base the new node on # This vm must have a snapshot with the same name as the VM name basevm="base" # Maximum number of the NIC on base machine, e.g. if # NIC1: NAT # NIC2: internal # NIC3: internal # NIC4: internal # then nicmax=4 nicmax=4 # Port forward SSH base # E.g. with portbase=2200, then on node3 port will be 2200 + 3 = 2203 portbase=2200 # Guest login vmusername="root" vmpassword="network" # Location of virtnet directory on guest virtnetpath="/home/network/virtnet" # Location of interface files: local or base interfacelocation="local" # Read input parameters ifnum=0; while [ "$1" != "" ]; do case $1 in -f | --file ) shift; # interfaces file for the node, e.g. vn-if-topology2-node2 iffile=$1; ;; -n | --node ) shift; # node number, e.g. 2 nodeid=$1; ;; -i | --iface ) shift; # internal network name, e.g. neta # Repeat this option, in order, for multiple internal networks, e.g. # --iface neta --iface netb ifnet[$ifnum]=$1; ifnum=$(( ${ifnum} + 1 )); ;; * ) usage exit 1 esac shift done # Name of the new VM vmname="node${nodeid}"; ifmax=$((${#ifnet[@]} - 1 )); echo "vn: Starting to create new VM ${vmname}" # Clone the base VM to create the new VM echo "vn: Cloning ${basevm} ..." bash vn-clonebase ${basevm} ${vmname} clonefail=$? # Check if the clone failed if [ "${clonefail}" = "1" ]; then echo "vn: Cloning of ${basevm} to ${vmname} failed." echo "vn: Maybe the VM ${vmname} already exists and is currently running." echo "vn: You should manually remove/rename existing nodes in VirtualBox" echo "vn: e.g. change ${vmname} to old-${vmname}, then try to create the " echo "vn: topology again." echo "vn: ERROR. Exiting." exit 1 fi # Only proceed if VM is not running VBoxManage list runningvms | cut -d "\"" -f 2 | grep -w ${vmname} > /dev/null novm=$? if [ "${novm}" = "0" ]; then echo "vn: ${vmname} is already running. You must stop it before modifying the network interfaces" echo "vn: ERROR. Exiting." exit 1 fi # Unplug cables on all internal interfaces for (( nic=2; nic<=${nicmax}; nic++ )); do echo "vn: Disconnecting cable ${nic} on ${vmname}" VBoxManage modifyvm ${vmname} --cableconnected${nic} off done # Setup the interfaces for (( n=0; n<=${ifmax}; n++ )); do nic=$(( ${n} + 2 )); # Configure NIC and plug in cable echo "vn: Configuring NIC ${nic} on ${vmname}" VBoxManage modifyvm ${vmname} --nic${nic} intnet --intnet${nic} ${ifnet[${n}]} VBoxManage modifyvm ${vmname} --cableconnected${nic} on echo "vn: Setting port forwarding on ${vmname}" # Set the port for port forwarding on NAT interface port=$(( ${portbase} + ${nodeid} )); # Grab the existing rule name and delete it (in case its named different than ssh) rule=`VBoxManage showvminfo ${vmname} | grep "NIC 1 Rule" | cut -d "=" -f 2 | cut -d "," -f 1 | tr -d ' '` VBoxManage modifyvm ${vmname} --natpf1 delete ${rule} # Now add a new rule VBoxManage modifyvm ${vmname} --natpf1 ssh,tcp,,${port},,22 done # Start the VM VBoxManage list runningvms | cut -d "\"" -f 2 | grep -w ${vmname} > /dev/null novm=$? if [ "${novm}" = "0" ]; then echo "vn: Virtual machine ${vmname} is already running" else VBoxManage startvm --type headless ${vmname} echo "vn: Virtual machine ${vmname} is now running" fi # Set the hostname on the guest and copy the interfaces file ifcmd="true" if [ -n "${iffile}" ]; then if [ "${iffile}" != 1 ]; then ifcmd="cp ${iffile} /etc/network/interfaces" fi else ifcmd="true "; fi # Turn on forwarding if router # Its a router if more than 1 internal network if [ ${ifmax} -gt 0 ]; then routercmd="sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf"; else routercmd="true "; fi # Delete the old key (since most likely was used for other VMs) echo "vn: Removing SSH keys" ssh-keygen -q -f "${HOME}/.ssh/known_hosts" -R [localhost]:${port} # Use SSH to perform the following on the node: # - set the hostname using the script vn-sethostname # - configure forwarding (if necessary) # - copy the interface file to /etc/network/interfaces # - poweroff the node echo "vn: Setting interfaces on guest using SSH ..." idfile="`dirname $BASH_SOURCE`/../../data/defaults/root/.ssh/id_rsa" ssh -o "StrictHostKeyChecking no" -l ${vmusername} -i ${idfile} -p ${port} 127.0.0.1 "${virtnetpath}/bin/vn-sethostname ${basevm} ${vmname}" ssh -o "StrictHostKeyChecking no" -l ${vmusername} -i ${idfile} -p ${port} 127.0.0.1 "${routercmd}" # Copy the topology file to the VM, rather than using the topology file on it if [ "${interfacelocation}" = "local" ]; then scp -o "StrictHostKeyChecking no" -i ${idfile} -P ${port} ${iffile} ${vmusername}@127.0.0.1:/etc/network/interfaces else ssh -o "StrictHostKeyChecking no" -l ${vmusername} -i ${idfile} -p ${port} 127.0.0.1 "${ifcmd}" fi ssh -o "StrictHostKeyChecking no" -l ${vmusername} -i ${idfile} -p ${port} 127.0.0.1 "poweroff" echo "vn: New VM ${vmname} has been created" exit 0