diff --git a/core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 2cc9492b465..4099531df9b 100755 --- a/core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/core/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -496,6 +496,10 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa } protected Answer execute(NetworkUsageCommand cmd) { + if ( cmd.isForVpc() ) { + return VPCNetworkUsage(cmd); + } + if (s_logger.isInfoEnabled()) { s_logger.info("Executing resource NetworkUsageCommand " + _gson.toJson(cmd)); } @@ -510,6 +514,69 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa return answer; } + protected NetworkUsageAnswer VPCNetworkUsage(NetworkUsageCommand cmd) { + String privateIp = cmd.getPrivateIP(); + String option = cmd.getOption(); + String publicIp = cmd.getGatewayIP(); + + + String args = "-l " + publicIp+ " "; + if (option.equals("get")) { + args += "-g"; + } else if (option.equals("create")) { + args += "-c"; + String vpcCIDR = cmd.getVpcCIDR(); + args += " -v " + vpcCIDR; + } else if (option.equals("reset")) { + args += "-r"; + } else if (option.equals("vpn")) { + args += "-n"; + } else if (option.equals("remove")) { + args += "-d"; + } else { + return new NetworkUsageAnswer(cmd, "success", 0L, 0L); + } + + try { + if (s_logger.isTraceEnabled()) { + s_logger.trace("Executing /opt/cloud/bin/vpc_netusage.sh " + args + " on DomR " + privateIp); + } + + VmwareManager mgr = getServiceContext().getStockObject(VmwareManager.CONTEXT_STOCK_NAME); + + Pair resultPair = SshHelper.sshExecute(privateIp, DEFAULT_DOMR_SSHPORT, "root", mgr.getSystemVMKeyFile(), null, "/opt/cloud/bin/vpc_netusage.sh " + args); + + if (!resultPair.first()) { + return null; + } + + String result = resultPair.second(); + + if (option.equals("get")) { + long[] stats = new long[2]; + if (result != null) { + String[] splitResult = result.split(":"); + int i = 0; + while (i < splitResult.length - 1) { + stats[0] += (new Long(splitResult[i++])).longValue(); + stats[1] += (new Long(splitResult[i++])).longValue(); + } + return new NetworkUsageAnswer(cmd, "success", stats[0], stats[1]); + } + } + if (result == null || result.isEmpty()) { + throw new Exception(" vpc network usage plugin call failed "); + } + return new NetworkUsageAnswer(cmd, "success", 0L, 0L); + + } catch (Throwable e) { + s_logger.error("Unable to execute NetworkUsage command on DomR (" + privateIp + "), domR may not be ready yet. failure due to " + + VmwareHelper.getExceptionMessage(e), e); + } + + return null; + } + private SetStaticRouteAnswer execute(SetStaticRouteCommand cmd) { if (s_logger.isInfoEnabled()) { s_logger.info("Executing resource SetStaticRouteCommand: " + _gson.toJson(cmd)); diff --git a/core/src/com/cloud/hypervisor/xen/resource/XenServer56Resource.java b/core/src/com/cloud/hypervisor/xen/resource/XenServer56Resource.java index 15237c18905..bf486376f2a 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/XenServer56Resource.java +++ b/core/src/com/cloud/hypervisor/xen/resource/XenServer56Resource.java @@ -182,6 +182,8 @@ public class XenServer56Resource extends CitrixResourceBase { args += "-r"; } else if (option.equals("vpn")) { args += "-n"; + } else if (option.equals("remove")) { + args += "-d"; } else { return new NetworkUsageAnswer(cmd, "success", 0L, 0L); } diff --git a/patches/systemvm/debian/config/opt/cloud/bin/vpc_netusage.sh b/patches/systemvm/debian/config/opt/cloud/bin/vpc_netusage.sh index c70080b5010..b026eb4c2fe 100755 --- a/patches/systemvm/debian/config/opt/cloud/bin/vpc_netusage.sh +++ b/patches/systemvm/debian/config/opt/cloud/bin/vpc_netusage.sh @@ -16,6 +16,7 @@ source /root/func.sh source /opt/cloud/bin/vpc_func.sh vpnoutmark="0x525" +vpninmark="0x524" lock="biglock" locked=$(getLockFile $lock) if [ "$locked" != "1" ] @@ -24,48 +25,58 @@ then fi usage() { - printf "Usage: %s -[c|g|r] [-[a|d] ]\n" $(basename $0) >&2 + printf "Usage: %s -[c|g|r|n|d] [-l ] [-v ] \n" $(basename $0) >&2 } create_usage_rules () { - iptables -N NETWORK_STATS_$ethDev > /dev/null - iptables -I FORWARD -j NETWORK_STATS_$ethDev > /dev/null - iptables-save|grep "NETWORK_STATS_$ethDev -i $ethDev" > /dev/null + iptables-save|grep "NETWORK_STATS_$ethDev" > /dev/null if [ $? -gt 0 ] then - iptables -A NETWORK_STATS_$ethDev -i $ethDev -d $vcidr > /dev/null - fi - iptables-save|grep "NETWORK_STATS_$ethDev -o $ethDev" > /dev/null - if [ $? -gt 0 ] - then - iptables -A NETWORK_STATS_$ethDev -o $ethDev -s $vcidr > /dev/null - fi + iptables -N NETWORK_STATS_$ethDev > /dev/null; + iptables -I FORWARD -j NETWORK_STATS_$ethDev > /dev/null; + iptables -A NETWORK_STATS_$ethDev -i $ethDev -d $vcidr > /dev/null; + iptables -A NETWORK_STATS_$ethDev -o $ethDev -s $vcidr > /dev/null; + fi return $? } create_vpn_usage_rules () { - iptables -N VPN_STATS_$ethDev > /dev/null - iptables -I FORWARD -j VPN_STATS_$ethDev > /dev/null - iptables-save|grep "VPN_STATS_$ethDev -i $ethDev" > /dev/null + iptables-save|grep "VPN_STATS_$ethDev" > /dev/null if [ $? -gt 0 ] then - iptables -A VPN_STATS_$ethDev -i $ethDev -m mark --mark $vpnoutmark > /dev/null - fi - iptables-save|grep "VPN_STATS_$ethDev -o $ethDev" > /dev/null - if [ $? -gt 0 ] - then - iptables -A VPN_STATS_$ethDev -o $ethDev -m mark --mark $vpnoutmark > /dev/null + iptables -N VPN_STATS_$ethDev > /dev/null; + iptables -I FORWARD -j VPN_STATS_$ethDev > /dev/null; + iptables -A VPN_STATS_$ethDev -i $ethDev -m mark --mark $vpninmark > /dev/null; + iptables -A VPN_STATS_$ethDev -o $ethDev -m mark --mark $vpnoutmark > /dev/null; fi return $? } +remove_usage_rules () { + echo $ethDev >> /root/removedVifs + return $? +} + get_usage () { iptables -L NETWORK_STATS_$ethDev -n -v -x | awk '$1 ~ /^[0-9]+$/ { printf "%s:", $2}'; > /dev/null - if [ $? -gt 0 ] + if [ -f /root/removedVifs ] then - printf $? - return 1 - fi + var=`cat /root/removedVifs` + # loop through vifs to be cleared + for i in $var; do + # Make sure vif doesn't exist + if [ ! -f /sys/class/net/$i ] + then + # flush rules and remove chain + iptables -F NETWORK_STATS_$i > /dev/null; + iptables -X NETWORK_STATS_$i > /dev/null; + iptables -F VPN_STATS_$i > /dev/null; + iptables -X VPN_STATS_$i > /dev/null; + fi + done + rm /root/removedVifs + fi + return 1 } get_vpn_usage () { @@ -78,6 +89,7 @@ get_vpn_usage () { } + reset_usage () { iptables -Z NETWORK_STATS_$ethDev > /dev/null if [ $? -gt 0 -a $? -ne 2 ] @@ -94,8 +106,9 @@ rflag= lflag= vflag= nflag= +dflag= -while getopts 'cgnrl:v:' OPTION +while getopts 'cgndrl:v:' OPTION do case $OPTION in c) cflag=1 @@ -111,7 +124,9 @@ do vcidr="$OPTARG" ;; n) nflag=1 - ;; + ;; + d) dflag=1 + ;; i) #Do nothing, since it's parameter for host script ;; ?) usage @@ -123,9 +138,12 @@ done ethDev=$(getEthByIp $publicIp) if [ "$cflag" == "1" ] then - create_usage_rules - create_vpn_usage_rules - unlock_exit 0 $lock $locked + if [ "$ethDev" != "" ] + then + create_usage_rules + create_vpn_usage_rules + unlock_exit 0 $lock $locked + fi fi if [ "$gflag" == "1" ] @@ -140,6 +158,12 @@ then unlock_exit $? $lock $locked fi +if [ "$dflag" == "1" ] +then + remove_usage_rules + unlock_exit 0 $lock $locked +fi + if [ "$rflag" == "1" ] then reset_usage diff --git a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java index 9edc4dfa7d1..619575cccb2 100644 --- a/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java +++ b/server/src/com/cloud/network/router/VpcVirtualNetworkApplianceManagerImpl.java @@ -335,15 +335,13 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian PlugNicCommand plugNicCmd = new PlugNicCommand(nic, vm.getName()); Commands cmds = new Commands(OnError.Stop); - cmds.addCommand("plugnic", plugNicCmd); + cmds.addCommand("plugnic", plugNicCmd); _agentMgr.send(dest.getHost().getId(), cmds); - PlugNicAnswer plugNicAnswer = cmds.getAnswer(PlugNicAnswer.class); if (!(plugNicAnswer != null && plugNicAnswer.getResult())) { s_logger.warn("Unable to plug nic for vm " + vm.getHostName()); result = false; } - } catch (OperationTimedoutException e) { throw new AgentUnavailableException("Unable to plug nic for router " + vm.getHostName() + " in network " + network, dest.getHost().getId(), e); @@ -367,8 +365,12 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian if (router.getState() == State.Running) { try { + Commands cmds = new Commands(OnError.Stop); + if(network.getTrafficType() == TrafficType.Public){ + NetworkUsageCommand netUsageCmd = new NetworkUsageCommand(router.getPrivateIpAddress(), router.getInstanceName(), "remove", true, nic.getIp()); + cmds.addCommand(netUsageCmd); + } UnPlugNicCommand unplugNicCmd = new UnPlugNicCommand(nic, vm.getName()); - Commands cmds = new Commands(OnError.Stop); cmds.addCommand("unplugnic", unplugNicCmd); _agentMgr.send(dest.getHost().getId(), cmds); @@ -376,8 +378,14 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian if (!(unplugNicAnswer != null && unplugNicAnswer.getResult())) { s_logger.warn("Unable to unplug nic from router " + router); result = false; - } - + } else { + if(network.getTrafficType() == TrafficType.Public){ + NetworkUsageCommand netUsageCmd = new NetworkUsageCommand(router.getPrivateIpAddress(), router.getInstanceName(), "remove", true, nic.getIp()); + cmds = new Commands(OnError.Stop); + cmds.addCommand(netUsageCmd); + _agentMgr.send(dest.getHost().getId(), cmds); + } + } } catch (OperationTimedoutException e) { throw new AgentUnavailableException("Unable to unplug nic from rotuer " + router + " from network " + network, dest.getHost().getId(), e); @@ -570,7 +578,10 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian return false; } } - + + Commands netUsagecmds = new Commands(OnError.Continue); + VpcVO vpc = _vpcDao.findById(router.getVpcId()); + //2) Plug the nics for (String vlanTag : nicsToPlug.keySet()) { PublicIpAddress ip = nicsToPlug.get(vlanTag); @@ -605,6 +616,16 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian return false; } } + //Create network usage commands. Send commands to router after IPAssoc + NetworkUsageCommand netUsageCmd = new NetworkUsageCommand(router.getPrivateIpAddress(), router.getInstanceName(), true, defaultNic.getIp4Address(), vpc.getCidr()); + netUsagecmds.addCommand(netUsageCmd); + UserStatisticsVO stats = _userStatsDao.findBy(router.getAccountId(), router.getDataCenterIdToDeployIn(), + publicNtwk.getId(), publicNic.getIp4Address(), router.getId(), router.getType().toString()); + if (stats == null) { + stats = new UserStatisticsVO(router.getAccountId(), router.getDataCenterIdToDeployIn(), publicNic.getIp4Address(), router.getId(), + router.getType().toString(), publicNtwk.getId()); + _userStatsDao.persist(stats); + } } //3) apply the rules @@ -636,7 +657,10 @@ public class VpcVirtualNetworkApplianceManagerImpl extends VirtualNetworkApplian return sendCommandsToRouter(router, cmds); } }); - + if(result && netUsagecmds.size() > 0){ + //After successful ipassoc, send commands to router + sendCommandsToRouter(router, netUsagecmds); + } return result; }