diff options
| author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2011-07-19 10:01:31 -0700 |
|---|---|---|
| committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2011-07-19 10:01:31 -0700 |
| commit | ffdb5ae22c9fd339e1f5d32ee049056ad2799907 (patch) | |
| tree | b216b8bb54cc8edeab82a5f6ebdff2251343f745 | |
| parent | 21ed1342ea82dee06f258e8f85fe55161e7b8ce4 (diff) | |
| download | illumos-joyent-ffdb5ae22c9fd339e1f5d32ee049056ad2799907.tar.gz | |
OS-504 kvm brand hook needs to create vnics
| -rwxr-xr-x | usr/src/lib/brand/kvm/zone/statechange.ksh | 177 |
1 files changed, 176 insertions, 1 deletions
diff --git a/usr/src/lib/brand/kvm/zone/statechange.ksh b/usr/src/lib/brand/kvm/zone/statechange.ksh index 2b4da6f6dd..59a474e292 100755 --- a/usr/src/lib/brand/kvm/zone/statechange.ksh +++ b/usr/src/lib/brand/kvm/zone/statechange.ksh @@ -84,7 +84,182 @@ unlock_file() # setup_net() { - touch $ZONEPATH/netsetup + # XXX old code, is this still needed by anything? + # touch $ZONEPATH/netsetup + + for nic in $_ZONECFG_net_resources + do + # Get simplified versions of the network config. variables. + address=$(eval echo \$_ZONECFG_net_${nic}_address) + global_nic=$(eval echo \$_ZONECFG_net_${nic}_global_nic) + mac_addr=$(eval echo \$_ZONECFG_net_${nic}_mac_addr) + vlan_id=$(eval echo \$_ZONECFG_net_${nic}_vlan_id) + blocked_outgoing_ports=$(eval \ + echo \$_ZONECFG_net_${nic}_blocked_outgoing_ports) + zone_ip=$(eval echo \$_ZONECFG_net_${nic}_ip) + + # If address set, must be a shared stack zone + [[ -n $address ]] && exit 0 + + # If no global-nic, must be a dedicated physical NIC instead + # of a vnic + [[ -z $global_nic ]] && continue + + orig_global=$global_nic + global_nic=$(eval echo \$SYSINFO_NIC_${orig_global}) + + # For backwards compatibility with the other parts of the + # system, check if this zone already has this vnic setup. + # If so, move on to the next vnic. + dladm show-vnic -p -o LINK -z $ZONENAME $nic >/dev/null 2>&1 + (( $? == 0 )) && continue + + if [[ -z $global_nic ]]; then + echo "undefined VNIC $nic " \ + "(global NIC $orig_global)" + logger -p daemon.err "zone $ZONENAME " \ + "undefined VNIC $nic (global NIC $orig_global)" + exit 1 + fi + + lock_file + + # + # Create the vnic. + # + + opt_str="-p zone=$ZONENAME" + [[ -n $mac_addr ]] && opt_str="$opt_str -m $mac_addr" + + [[ -n $vlan_id && $vlan_id != 0 ]] && \ + opt_str="$opt_str -v $vlan_id" + + # + # Creating a VNIC in a zone is a multi-step process internally. + # This means there is a short window where the VNIC exists in + # the global zone and that could lead to a race condition if + # two zones boot at the same time with the same VNIC name. Use + # a temp. name to create the VNIC then rename it to have the + # correct name. + # + tname=tmp$$0 + dout=`dladm create-vnic -t -l $global_nic $opt_str $tname 2>&1` + if (( $? != 0 )); then + print -f "error creating VNIC %s (global NIC %s)\n" \ + "$nic" "$orig_global" + print -f "msg: %s\n" "$dout" + logger -p daemon.err "zone $ZONENAME error creating " \ + "VNIC $nic (global NIC $orig_global $global_nic)" + logger -p daemon.err "msg: $dout" + logger -p daemon.err "Failed cmd: dladm create-vnic " \ + "-t -l $global_nic $opt_str $tname" + + # Show more info if dup MAC addr. + echo $dout | egrep -s "MAC address is already in use" + if (( $? == 0 )); then + entry=`dladm show-vnic -olink,macaddress,zone \ + | nawk -v addr=$mac_addr '{ + if ($2 == addr) + print $0 + }'` + if [[ -n $entry ]]; then + print -f "LINK\tMACADDRESS\tZONE\n" + print -f "%s\n" "$entry" + fi + fi + exit 1 + fi + dladm rename-link -z $ZONENAME $tname $nic + if (( $? != 0 )); then + echo "error renaming VNIC $tname $nic" + logger -p daemon.err "zone $ZONENAME error renaming " \ + "VNIC $tname $nic" + exit 1 + fi + + if [[ -z $mac_addr ]]; then + # There was no assigned mac address + + # Get newly assigned mac address. + mac_addr=$(dladm show-vnic -z $ZONENAME -p -o \ + MACADDRESS ${nic}) + + # Save newly assigned mac address + [[ -n $mac_addr ]] && zonecfg -z $ZONENAME \ + "select net physical=$nic; " \ + "set mac-addr=$mac_addr; end; exit" + fi + + # Enable full antispoof + spoof_opts="ip-nospoof,mac-nospoof,restricted,dhcp-nospoof" + dladm set-linkprop -t -z $ZONENAME -p \ + "protection=${spoof_opts}" ${nic} + if (( $? != 0 )); then + echo "error setting VNIC protection $nic $spoof_opts" + logger -p daemon.err "zone $ZONENAME error setting " \ + "VNIC protection $nic $spoof_opts" + exit 1 + fi + + if [[ -n "${zone_ip}" ]]; then + dladm set-linkprop -t -z $ZONENAME \ + -p "allowed-ips=${zone_ip}" ${nic} + if (( $? != 0 )); then + echo "error setting VNIC allowed-ip " \ + "$nic $zone_ip" + logger -p daemon.err "zone $ZONENAME " \ + "error setting VNIC allowed-ip " \ + "$nic $zone_ip" + exit 1 + fi + fi + + # If on VMWare and we have external IPs, create a bridge to + # allow zones to reach the external gateway + if [[ ${orig_global} == "external" && \ + "${SYSINFO_Product}" == "VMware Virtual Platform" ]]; then + dladm show-bridge -p -o BRIDGE vmwareextbr \ + >/dev/null 2>&1 + if (( $? != 0 )); then + dladm create-bridge -l ${SYSINFO_NIC_external} \ + vmwareextbr + if (( $? != 0 )); then + echo "error creating bridge vmwareextbr" + logger -p daemon.err "error creating " \ + "bridge vmwareextbr" + exit 1 + fi + fi + fi + + if [[ -n $blocked_outgoing_ports ]]; then + OLDIFS=$IFS + IFS=, + for port in $blocked_outgoing_ports; do + # br='block remote'. Flow names should be < 31 + # chars in length so that they get unique + # kstats. + # Use the VNIC mac addr. to generate a unique + # name. + mac_addr=`dladm show-vnic -z $ZONENAME -p \ + -o MACADDRESS $nic | tr ':' '_'` + flowadm add-flow -t -l $nic -z $ZONENAME \ + -a transport=tcp,remote_port=$port \ + -p maxbw=0 f${mac_addr}_br_${port} + if (( $? != 0 )); then + echo "error adding flow " \ + "$nic f${mac_addr}_br_${port}" + logger -p daemon.err "zone $ZONENAME " \ + "error adding flow " \ + "$nic f${mac_addr}_br_${port}" + exit 1 + fi + done + IFS=$OLDIFS + fi + + unlock_file + done } # |
