Skip to content

Commit 6e83c77

Browse files
committed
vpc/server: Fix network statistics for vpc
This contains 3 main changes (1) add NETWORK_STATS_ethX for all nics with public ips in VPC VRs (current: NETWORK_STATS_eth1) (2) DO NOT create records in user_statistics for each VPC tier (only one record per public nic per VPC VR) (3) send NetworkUsageCommand before unplugging a NIC with public IPs from VPC VR
1 parent 186ac69 commit 6e83c77

7 files changed

Lines changed: 56 additions & 107 deletions

File tree

api/src/main/java/com/cloud/network/VirtualNetworkApplianceService.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.cloud.exception.ResourceUnavailableException;
2727
import com.cloud.network.router.VirtualRouter;
2828
import com.cloud.user.Account;
29+
import com.cloud.vm.Nic;
2930

3031
public interface VirtualNetworkApplianceService {
3132
/**
@@ -74,4 +75,6 @@ public interface VirtualNetworkApplianceService {
7475
* @return
7576
*/
7677
boolean performRouterHealthChecks(long routerId);
78+
79+
<T extends VirtualRouter> void collectNetworkStatistics(T router, Nic nic);
7780
}

engine/schema/src/main/java/com/cloud/vm/dao/DomainRouterDaoImpl.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -383,12 +383,14 @@ public void addRouterToGuestNetwork(final VirtualRouter router, final Network gu
383383
final RouterNetworkVO routerNtwkMap = new RouterNetworkVO(router.getId(), guestNetwork.getId(), guestNetwork.getGuestType());
384384
_routerNetworkDao.persist(routerNtwkMap);
385385
//2) create user stats entry for the network
386-
UserStatisticsVO stats =
387-
_userStatsDao.findBy(router.getAccountId(), router.getDataCenterId(), guestNetwork.getId(), null, router.getId(), router.getType().toString());
388-
if (stats == null) {
389-
stats =
390-
new UserStatisticsVO(router.getAccountId(), router.getDataCenterId(), null, router.getId(), router.getType().toString(), guestNetwork.getId());
391-
_userStatsDao.persist(stats);
386+
if (router.getVpcId() == null) {
387+
UserStatisticsVO stats =
388+
_userStatsDao.findBy(router.getAccountId(), router.getDataCenterId(), guestNetwork.getId(), null, router.getId(), router.getType().toString());
389+
if (stats == null) {
390+
stats =
391+
new UserStatisticsVO(router.getAccountId(), router.getDataCenterId(), null, router.getId(), router.getType().toString(), guestNetwork.getId());
392+
_userStatsDao.persist(stats);
393+
}
392394
}
393395
txn.commit();
394396
}

server/src/main/java/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java

Lines changed: 18 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -732,100 +732,7 @@ protected void runInContext() {
732732
s_logger.debug("Found " + routers.size() + " running routers. ");
733733

734734
for (final DomainRouterVO router : routers) {
735-
final String privateIP = router.getPrivateIpAddress();
736-
737-
if (privateIP != null) {
738-
final boolean forVpc = router.getVpcId() != null;
739-
final List<? extends Nic> routerNics = _nicDao.listByVmId(router.getId());
740-
for (final Nic routerNic : routerNics) {
741-
final Network network = _networkModel.getNetwork(routerNic.getNetworkId());
742-
// Send network usage command for public nic in VPC VR
743-
// Send network usage command for isolated guest nic of non) VPC VR
744-
745-
//[TODO] Avoiding the NPE now, but I have to find out what is going on with the network. - Wilder Rodrigues
746-
if (network == null) {
747-
s_logger.error("Could not find a network with ID => " + routerNic.getNetworkId() + ". It might be a problem!");
748-
continue;
749-
}
750-
if (forVpc && network.getTrafficType() == TrafficType.Public || !forVpc && network.getTrafficType() == TrafficType.Guest
751-
&& network.getGuestType() == Network.GuestType.Isolated) {
752-
final NetworkUsageCommand usageCmd = new NetworkUsageCommand(privateIP, router.getHostName(), forVpc, routerNic.getIPv4Address());
753-
final String routerType = router.getType().toString();
754-
final UserStatisticsVO previousStats = _userStatsDao.findBy(router.getAccountId(), router.getDataCenterId(), network.getId(),
755-
forVpc ? routerNic.getIPv4Address() : null, router.getId(), routerType);
756-
NetworkUsageAnswer answer = null;
757-
try {
758-
answer = (NetworkUsageAnswer) _agentMgr.easySend(router.getHostId(), usageCmd);
759-
} catch (final Exception e) {
760-
s_logger.warn("Error while collecting network stats from router: " + router.getInstanceName() + " from host: " + router.getHostId(), e);
761-
continue;
762-
}
763-
764-
if (answer != null) {
765-
if (!answer.getResult()) {
766-
s_logger.warn("Error while collecting network stats from router: " + router.getInstanceName() + " from host: " + router.getHostId()
767-
+ "; details: " + answer.getDetails());
768-
continue;
769-
}
770-
try {
771-
if (answer.getBytesReceived() == 0 && answer.getBytesSent() == 0) {
772-
s_logger.debug("Recieved and Sent bytes are both 0. Not updating user_statistics");
773-
continue;
774-
}
775-
final NetworkUsageAnswer answerFinal = answer;
776-
Transaction.execute(new TransactionCallbackNoReturn() {
777-
@Override
778-
public void doInTransactionWithoutResult(final TransactionStatus status) {
779-
final UserStatisticsVO stats = _userStatsDao.lock(router.getAccountId(), router.getDataCenterId(), network.getId(),
780-
forVpc ? routerNic.getIPv4Address() : null, router.getId(), routerType);
781-
if (stats == null) {
782-
s_logger.warn("unable to find stats for account: " + router.getAccountId());
783-
return;
784-
}
785-
786-
if (previousStats != null
787-
&& (previousStats.getCurrentBytesReceived() != stats.getCurrentBytesReceived() || previousStats.getCurrentBytesSent() != stats
788-
.getCurrentBytesSent())) {
789-
s_logger.debug("Router stats changed from the time NetworkUsageCommand was sent. " + "Ignoring current answer. Router: "
790-
+ answerFinal.getRouterName() + " Rcvd: " + answerFinal.getBytesReceived() + "Sent: " + answerFinal.getBytesSent());
791-
return;
792-
}
793-
794-
if (stats.getCurrentBytesReceived() > answerFinal.getBytesReceived()) {
795-
if (s_logger.isDebugEnabled()) {
796-
s_logger.debug("Received # of bytes that's less than the last one. "
797-
+ "Assuming something went wrong and persisting it. Router: " + answerFinal.getRouterName() + " Reported: "
798-
+ toHumanReadableSize(answerFinal.getBytesReceived()) + " Stored: " + toHumanReadableSize(stats.getCurrentBytesReceived()));
799-
}
800-
stats.setNetBytesReceived(stats.getNetBytesReceived() + stats.getCurrentBytesReceived());
801-
}
802-
stats.setCurrentBytesReceived(answerFinal.getBytesReceived());
803-
if (stats.getCurrentBytesSent() > answerFinal.getBytesSent()) {
804-
if (s_logger.isDebugEnabled()) {
805-
s_logger.debug("Received # of bytes that's less than the last one. "
806-
+ "Assuming something went wrong and persisting it. Router: " + answerFinal.getRouterName() + " Reported: "
807-
+ toHumanReadableSize(answerFinal.getBytesSent()) + " Stored: " + toHumanReadableSize(stats.getCurrentBytesSent()));
808-
}
809-
stats.setNetBytesSent(stats.getNetBytesSent() + stats.getCurrentBytesSent());
810-
}
811-
stats.setCurrentBytesSent(answerFinal.getBytesSent());
812-
if (!_dailyOrHourly) {
813-
// update agg bytes
814-
stats.setAggBytesSent(stats.getNetBytesSent() + stats.getCurrentBytesSent());
815-
stats.setAggBytesReceived(stats.getNetBytesReceived() + stats.getCurrentBytesReceived());
816-
}
817-
_userStatsDao.update(stats.getId(), stats);
818-
}
819-
});
820-
821-
} catch (final Exception e) {
822-
s_logger.warn("Unable to update user statistics for account: " + router.getAccountId() + " Rx: " + toHumanReadableSize(answer.getBytesReceived()) + "; Tx: "
823-
+ toHumanReadableSize(answer.getBytesSent()));
824-
}
825-
}
826-
}
827-
}
828-
}
735+
collectNetworkStatistics(router, null);
829736
}
830737
} catch (final Exception e) {
831738
s_logger.warn("Error while collecting network stats", e);
@@ -3057,6 +2964,11 @@ public void prepareStop(final VirtualMachineProfile profile) {
30572964
// Collect network usage before stopping Vm
30582965

30592966
final DomainRouterVO router = _routerDao.findById(profile.getVirtualMachine().getId());
2967+
collectNetworkStatistics(router, null);
2968+
}
2969+
2970+
@Override
2971+
public <T extends VirtualRouter> void collectNetworkStatistics(final T router, final Nic nic) {
30602972
if (router == null) {
30612973
return;
30622974
}
@@ -3065,12 +2977,23 @@ public void prepareStop(final VirtualMachineProfile profile) {
30652977

30662978
if (privateIP != null) {
30672979
final boolean forVpc = router.getVpcId() != null;
3068-
final List<? extends Nic> routerNics = _nicDao.listByVmId(router.getId());
2980+
List<Nic> routerNics = new ArrayList<Nic>();
2981+
if (nic != null) {
2982+
routerNics.add(nic);
2983+
} else {
2984+
routerNics.addAll(_nicDao.listByVmId(router.getId()));
2985+
}
30692986
for (final Nic routerNic : routerNics) {
30702987
final Network network = _networkModel.getNetwork(routerNic.getNetworkId());
30712988
// Send network usage command for public nic in VPC VR
30722989
// Send network usage command for isolated guest nic of non VPC
30732990
// VR
2991+
2992+
//[TODO] Avoiding the NPE now, but I have to find out what is going on with the network. - Wilder Rodrigues
2993+
if (network == null) {
2994+
s_logger.error("Could not find a network with ID => " + routerNic.getNetworkId() + ". It might be a problem!");
2995+
continue;
2996+
}
30742997
if (forVpc && network.getTrafficType() == TrafficType.Public || !forVpc && network.getTrafficType() == TrafficType.Guest
30752998
&& network.getGuestType() == Network.GuestType.Isolated) {
30762999
final NetworkUsageCommand usageCmd = new NetworkUsageCommand(privateIP, router.getHostName(), forVpc, routerNic.getIPv4Address());

server/src/main/java/com/cloud/network/rules/NicPlugInOutRules.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import com.cloud.network.Networks.BroadcastDomainType;
4141
import com.cloud.network.Networks.IsolationType;
4242
import com.cloud.network.PublicIpAddress;
43+
import com.cloud.network.VpcVirtualNetworkApplianceService;
4344
import com.cloud.network.dao.FirewallRulesDao;
4445
import com.cloud.network.dao.IPAddressDao;
4546
import com.cloud.network.dao.IPAddressVO;
@@ -84,6 +85,7 @@ public boolean accept(final NetworkTopologyVisitor visitor, final VirtualRouter
8485
NetworkModel networkModel = visitor.getVirtualNetworkApplianceFactory().getNetworkModel();
8586
VirtualMachineManager itMgr = visitor.getVirtualNetworkApplianceFactory().getItMgr();
8687
NicDao nicDao = visitor.getVirtualNetworkApplianceFactory().getNicDao();
88+
VpcVirtualNetworkApplianceService routerService = visitor.getVirtualNetworkApplianceFactory().getRouterService();
8789

8890
// de-associate IPs before unplugging nics
8991
if (!nicsToUnplug.isEmpty()) {
@@ -107,6 +109,12 @@ public boolean accept(final NetworkTopologyVisitor visitor, final VirtualRouter
107109

108110
// 1) Unplug the nics
109111
for (Entry<String, PublicIpAddress> entry : nicsToUnplug.entrySet()) {
112+
PublicIpAddress ip = entry.getValue();
113+
NicVO nic = nicDao.findByIp4AddressAndNetworkIdAndInstanceId(ip.getNetworkId(), _router.getId(), ip.getAddress().addr());
114+
if (nic != null) {
115+
s_logger.info("Collect network statistics for nic " + nic + " from router " + _router);
116+
routerService.collectNetworkStatistics(_router, nic);
117+
}
110118
Network publicNtwk = null;
111119
try {
112120
publicNtwk = networkModel.getNetwork(entry.getValue().getNetworkId());

server/src/main/java/com/cloud/network/rules/VirtualNetworkApplianceFactory.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.cloud.dc.dao.VlanDao;
2727
import com.cloud.network.IpAddressManager;
2828
import com.cloud.network.NetworkModel;
29+
import com.cloud.network.VpcVirtualNetworkApplianceService;
2930
import com.cloud.network.dao.FirewallRulesDao;
3031
import com.cloud.network.dao.IPAddressDao;
3132
import com.cloud.network.dao.LoadBalancerDao;
@@ -98,6 +99,8 @@ public class VirtualNetworkApplianceFactory {
9899

99100
@Inject
100101
private NetworkTopologyContext _networkTopologyContext;
102+
@Inject
103+
private VpcVirtualNetworkApplianceService _routerService;
101104

102105
public NetworkModel getNetworkModel() {
103106
return _networkModel;
@@ -190,4 +193,8 @@ public NetworkTopologyContext getNetworkTopologyContext() {
190193
public FirewallRulesDao getFirewallRulesDao() {
191194
return _rulesDao;
192195
}
196+
197+
public VpcVirtualNetworkApplianceService getRouterService() {
198+
return _routerService;
199+
}
193200
}

server/src/test/java/com/cloud/vpc/MockVpcVirtualNetworkApplianceManager.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import com.cloud.user.User;
4242
import com.cloud.utils.component.ManagerBase;
4343
import com.cloud.vm.DomainRouterVO;
44+
import com.cloud.vm.Nic;
4445
import com.cloud.vm.VirtualMachineProfile;
4546

4647
@Component
@@ -280,4 +281,10 @@ public boolean startSite2SiteVpn(DomainRouterVO router) throws ResourceUnavailab
280281
// TODO Auto-generated method stub
281282
return false;
282283
}
283-
}
284+
285+
@Override
286+
public <T extends VirtualRouter> void collectNetworkStatistics(T router, Nic nic) {
287+
// TODO Auto-generated method stub
288+
return;
289+
}
290+
}

systemvm/debian/opt/cloud/bin/cs/CsAddress.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -476,11 +476,6 @@ def fw_vpcrouter(self):
476476
"-A PREROUTING -m state --state NEW -i %s -s %s ! -d %s/32 -j ACL_OUTBOUND_%s" %
477477
(self.dev, guestNetworkCidr, self.address['gateway'], self.dev)])
478478

479-
self.fw.append(["", "front", "-A NETWORK_STATS_%s -i %s -d %s" %
480-
("eth1", "eth1", guestNetworkCidr)])
481-
self.fw.append(["", "front", "-A NETWORK_STATS_%s -o %s -s %s" %
482-
("eth1", "eth1", guestNetworkCidr)])
483-
484479
if self.is_private_gateway():
485480
self.fw.append(["filter", "", "-A FORWARD -d %s -o %s -j ACL_INBOUND_%s" %
486481
(self.address['network'], self.dev, self.dev)])
@@ -518,6 +513,10 @@ def fw_vpcrouter(self):
518513
["mangle", "", "-A VPN_STATS_%s -i %s -m mark --mark 0x524/0xffffffff" % (self.dev, self.dev)])
519514
self.fw.append(
520515
["", "front", "-A FORWARD -j NETWORK_STATS_%s" % self.dev])
516+
self.fw.append(
517+
["", "front", "-A NETWORK_STATS_%s -s %s -o %s" % (self.dev, self.cl.get_vpccidr(), self.dev)])
518+
self.fw.append(
519+
["", "front", "-A NETWORK_STATS_%s -d %s -i %s" % (self.dev, self.cl.get_vpccidr(), self.dev)])
521520

522521
self.fw.append(["", "front", "-A FORWARD -j NETWORK_STATS"])
523522
self.fw.append(["", "front", "-A INPUT -j NETWORK_STATS"])

0 commit comments

Comments
 (0)