mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
server: Fix network statistics for vpc (#3944)
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
This commit is contained in:
parent
76ba5c62d9
commit
63c91c1458
@ -26,6 +26,7 @@ import com.cloud.exception.InsufficientCapacityException;
|
|||||||
import com.cloud.exception.ResourceUnavailableException;
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
import com.cloud.network.router.VirtualRouter;
|
import com.cloud.network.router.VirtualRouter;
|
||||||
import com.cloud.user.Account;
|
import com.cloud.user.Account;
|
||||||
|
import com.cloud.vm.Nic;
|
||||||
|
|
||||||
public interface VirtualNetworkApplianceService {
|
public interface VirtualNetworkApplianceService {
|
||||||
/**
|
/**
|
||||||
@ -74,4 +75,6 @@ public interface VirtualNetworkApplianceService {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
boolean performRouterHealthChecks(long routerId);
|
boolean performRouterHealthChecks(long routerId);
|
||||||
|
|
||||||
|
<T extends VirtualRouter> void collectNetworkStatistics(T router, Nic nic);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -383,6 +383,7 @@ public class DomainRouterDaoImpl extends GenericDaoBase<DomainRouterVO, Long> im
|
|||||||
final RouterNetworkVO routerNtwkMap = new RouterNetworkVO(router.getId(), guestNetwork.getId(), guestNetwork.getGuestType());
|
final RouterNetworkVO routerNtwkMap = new RouterNetworkVO(router.getId(), guestNetwork.getId(), guestNetwork.getGuestType());
|
||||||
_routerNetworkDao.persist(routerNtwkMap);
|
_routerNetworkDao.persist(routerNtwkMap);
|
||||||
//2) create user stats entry for the network
|
//2) create user stats entry for the network
|
||||||
|
if (router.getVpcId() == null) {
|
||||||
UserStatisticsVO stats =
|
UserStatisticsVO stats =
|
||||||
_userStatsDao.findBy(router.getAccountId(), router.getDataCenterId(), guestNetwork.getId(), null, router.getId(), router.getType().toString());
|
_userStatsDao.findBy(router.getAccountId(), router.getDataCenterId(), guestNetwork.getId(), null, router.getId(), router.getType().toString());
|
||||||
if (stats == null) {
|
if (stats == null) {
|
||||||
@ -390,6 +391,7 @@ public class DomainRouterDaoImpl extends GenericDaoBase<DomainRouterVO, Long> im
|
|||||||
new UserStatisticsVO(router.getAccountId(), router.getDataCenterId(), null, router.getId(), router.getType().toString(), guestNetwork.getId());
|
new UserStatisticsVO(router.getAccountId(), router.getDataCenterId(), null, router.getId(), router.getType().toString(), guestNetwork.getId());
|
||||||
_userStatsDao.persist(stats);
|
_userStatsDao.persist(stats);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
txn.commit();
|
txn.commit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -732,100 +732,7 @@ Configurable, StateListener<VirtualMachine.State, VirtualMachine.Event, VirtualM
|
|||||||
s_logger.debug("Found " + routers.size() + " running routers. ");
|
s_logger.debug("Found " + routers.size() + " running routers. ");
|
||||||
|
|
||||||
for (final DomainRouterVO router : routers) {
|
for (final DomainRouterVO router : routers) {
|
||||||
final String privateIP = router.getPrivateIpAddress();
|
collectNetworkStatistics(router, null);
|
||||||
|
|
||||||
if (privateIP != null) {
|
|
||||||
final boolean forVpc = router.getVpcId() != null;
|
|
||||||
final List<? extends Nic> routerNics = _nicDao.listByVmId(router.getId());
|
|
||||||
for (final Nic routerNic : routerNics) {
|
|
||||||
final Network network = _networkModel.getNetwork(routerNic.getNetworkId());
|
|
||||||
// Send network usage command for public nic in VPC VR
|
|
||||||
// Send network usage command for isolated guest nic of non) VPC VR
|
|
||||||
|
|
||||||
//[TODO] Avoiding the NPE now, but I have to find out what is going on with the network. - Wilder Rodrigues
|
|
||||||
if (network == null) {
|
|
||||||
s_logger.error("Could not find a network with ID => " + routerNic.getNetworkId() + ". It might be a problem!");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (forVpc && network.getTrafficType() == TrafficType.Public || !forVpc && network.getTrafficType() == TrafficType.Guest
|
|
||||||
&& network.getGuestType() == Network.GuestType.Isolated) {
|
|
||||||
final NetworkUsageCommand usageCmd = new NetworkUsageCommand(privateIP, router.getHostName(), forVpc, routerNic.getIPv4Address());
|
|
||||||
final String routerType = router.getType().toString();
|
|
||||||
final UserStatisticsVO previousStats = _userStatsDao.findBy(router.getAccountId(), router.getDataCenterId(), network.getId(),
|
|
||||||
forVpc ? routerNic.getIPv4Address() : null, router.getId(), routerType);
|
|
||||||
NetworkUsageAnswer answer = null;
|
|
||||||
try {
|
|
||||||
answer = (NetworkUsageAnswer) _agentMgr.easySend(router.getHostId(), usageCmd);
|
|
||||||
} catch (final Exception e) {
|
|
||||||
s_logger.warn("Error while collecting network stats from router: " + router.getInstanceName() + " from host: " + router.getHostId(), e);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (answer != null) {
|
|
||||||
if (!answer.getResult()) {
|
|
||||||
s_logger.warn("Error while collecting network stats from router: " + router.getInstanceName() + " from host: " + router.getHostId()
|
|
||||||
+ "; details: " + answer.getDetails());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
if (answer.getBytesReceived() == 0 && answer.getBytesSent() == 0) {
|
|
||||||
s_logger.debug("Recieved and Sent bytes are both 0. Not updating user_statistics");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final NetworkUsageAnswer answerFinal = answer;
|
|
||||||
Transaction.execute(new TransactionCallbackNoReturn() {
|
|
||||||
@Override
|
|
||||||
public void doInTransactionWithoutResult(final TransactionStatus status) {
|
|
||||||
final UserStatisticsVO stats = _userStatsDao.lock(router.getAccountId(), router.getDataCenterId(), network.getId(),
|
|
||||||
forVpc ? routerNic.getIPv4Address() : null, router.getId(), routerType);
|
|
||||||
if (stats == null) {
|
|
||||||
s_logger.warn("unable to find stats for account: " + router.getAccountId());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (previousStats != null
|
|
||||||
&& (previousStats.getCurrentBytesReceived() != stats.getCurrentBytesReceived() || previousStats.getCurrentBytesSent() != stats
|
|
||||||
.getCurrentBytesSent())) {
|
|
||||||
s_logger.debug("Router stats changed from the time NetworkUsageCommand was sent. " + "Ignoring current answer. Router: "
|
|
||||||
+ answerFinal.getRouterName() + " Rcvd: " + answerFinal.getBytesReceived() + "Sent: " + answerFinal.getBytesSent());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stats.getCurrentBytesReceived() > answerFinal.getBytesReceived()) {
|
|
||||||
if (s_logger.isDebugEnabled()) {
|
|
||||||
s_logger.debug("Received # of bytes that's less than the last one. "
|
|
||||||
+ "Assuming something went wrong and persisting it. Router: " + answerFinal.getRouterName() + " Reported: "
|
|
||||||
+ toHumanReadableSize(answerFinal.getBytesReceived()) + " Stored: " + toHumanReadableSize(stats.getCurrentBytesReceived()));
|
|
||||||
}
|
|
||||||
stats.setNetBytesReceived(stats.getNetBytesReceived() + stats.getCurrentBytesReceived());
|
|
||||||
}
|
|
||||||
stats.setCurrentBytesReceived(answerFinal.getBytesReceived());
|
|
||||||
if (stats.getCurrentBytesSent() > answerFinal.getBytesSent()) {
|
|
||||||
if (s_logger.isDebugEnabled()) {
|
|
||||||
s_logger.debug("Received # of bytes that's less than the last one. "
|
|
||||||
+ "Assuming something went wrong and persisting it. Router: " + answerFinal.getRouterName() + " Reported: "
|
|
||||||
+ toHumanReadableSize(answerFinal.getBytesSent()) + " Stored: " + toHumanReadableSize(stats.getCurrentBytesSent()));
|
|
||||||
}
|
|
||||||
stats.setNetBytesSent(stats.getNetBytesSent() + stats.getCurrentBytesSent());
|
|
||||||
}
|
|
||||||
stats.setCurrentBytesSent(answerFinal.getBytesSent());
|
|
||||||
if (!_dailyOrHourly) {
|
|
||||||
// update agg bytes
|
|
||||||
stats.setAggBytesSent(stats.getNetBytesSent() + stats.getCurrentBytesSent());
|
|
||||||
stats.setAggBytesReceived(stats.getNetBytesReceived() + stats.getCurrentBytesReceived());
|
|
||||||
}
|
|
||||||
_userStatsDao.update(stats.getId(), stats);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (final Exception e) {
|
|
||||||
s_logger.warn("Unable to update user statistics for account: " + router.getAccountId() + " Rx: " + toHumanReadableSize(answer.getBytesReceived()) + "; Tx: "
|
|
||||||
+ toHumanReadableSize(answer.getBytesSent()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
s_logger.warn("Error while collecting network stats", e);
|
s_logger.warn("Error while collecting network stats", e);
|
||||||
@ -3057,6 +2964,11 @@ Configurable, StateListener<VirtualMachine.State, VirtualMachine.Event, VirtualM
|
|||||||
// Collect network usage before stopping Vm
|
// Collect network usage before stopping Vm
|
||||||
|
|
||||||
final DomainRouterVO router = _routerDao.findById(profile.getVirtualMachine().getId());
|
final DomainRouterVO router = _routerDao.findById(profile.getVirtualMachine().getId());
|
||||||
|
collectNetworkStatistics(router, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends VirtualRouter> void collectNetworkStatistics(final T router, final Nic nic) {
|
||||||
if (router == null) {
|
if (router == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3065,12 +2977,23 @@ Configurable, StateListener<VirtualMachine.State, VirtualMachine.Event, VirtualM
|
|||||||
|
|
||||||
if (privateIP != null) {
|
if (privateIP != null) {
|
||||||
final boolean forVpc = router.getVpcId() != null;
|
final boolean forVpc = router.getVpcId() != null;
|
||||||
final List<? extends Nic> routerNics = _nicDao.listByVmId(router.getId());
|
List<Nic> routerNics = new ArrayList<Nic>();
|
||||||
|
if (nic != null) {
|
||||||
|
routerNics.add(nic);
|
||||||
|
} else {
|
||||||
|
routerNics.addAll(_nicDao.listByVmId(router.getId()));
|
||||||
|
}
|
||||||
for (final Nic routerNic : routerNics) {
|
for (final Nic routerNic : routerNics) {
|
||||||
final Network network = _networkModel.getNetwork(routerNic.getNetworkId());
|
final Network network = _networkModel.getNetwork(routerNic.getNetworkId());
|
||||||
// Send network usage command for public nic in VPC VR
|
// Send network usage command for public nic in VPC VR
|
||||||
// Send network usage command for isolated guest nic of non VPC
|
// Send network usage command for isolated guest nic of non VPC
|
||||||
// VR
|
// VR
|
||||||
|
|
||||||
|
//[TODO] Avoiding the NPE now, but I have to find out what is going on with the network. - Wilder Rodrigues
|
||||||
|
if (network == null) {
|
||||||
|
s_logger.error("Could not find a network with ID => " + routerNic.getNetworkId() + ". It might be a problem!");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (forVpc && network.getTrafficType() == TrafficType.Public || !forVpc && network.getTrafficType() == TrafficType.Guest
|
if (forVpc && network.getTrafficType() == TrafficType.Public || !forVpc && network.getTrafficType() == TrafficType.Guest
|
||||||
&& network.getGuestType() == Network.GuestType.Isolated) {
|
&& network.getGuestType() == Network.GuestType.Isolated) {
|
||||||
final NetworkUsageCommand usageCmd = new NetworkUsageCommand(privateIP, router.getHostName(), forVpc, routerNic.getIPv4Address());
|
final NetworkUsageCommand usageCmd = new NetworkUsageCommand(privateIP, router.getHostName(), forVpc, routerNic.getIPv4Address());
|
||||||
|
|||||||
@ -40,6 +40,7 @@ import com.cloud.network.NetworkModel;
|
|||||||
import com.cloud.network.Networks.BroadcastDomainType;
|
import com.cloud.network.Networks.BroadcastDomainType;
|
||||||
import com.cloud.network.Networks.IsolationType;
|
import com.cloud.network.Networks.IsolationType;
|
||||||
import com.cloud.network.PublicIpAddress;
|
import com.cloud.network.PublicIpAddress;
|
||||||
|
import com.cloud.network.VpcVirtualNetworkApplianceService;
|
||||||
import com.cloud.network.dao.FirewallRulesDao;
|
import com.cloud.network.dao.FirewallRulesDao;
|
||||||
import com.cloud.network.dao.IPAddressDao;
|
import com.cloud.network.dao.IPAddressDao;
|
||||||
import com.cloud.network.dao.IPAddressVO;
|
import com.cloud.network.dao.IPAddressVO;
|
||||||
@ -84,6 +85,7 @@ public class NicPlugInOutRules extends RuleApplier {
|
|||||||
NetworkModel networkModel = visitor.getVirtualNetworkApplianceFactory().getNetworkModel();
|
NetworkModel networkModel = visitor.getVirtualNetworkApplianceFactory().getNetworkModel();
|
||||||
VirtualMachineManager itMgr = visitor.getVirtualNetworkApplianceFactory().getItMgr();
|
VirtualMachineManager itMgr = visitor.getVirtualNetworkApplianceFactory().getItMgr();
|
||||||
NicDao nicDao = visitor.getVirtualNetworkApplianceFactory().getNicDao();
|
NicDao nicDao = visitor.getVirtualNetworkApplianceFactory().getNicDao();
|
||||||
|
VpcVirtualNetworkApplianceService routerService = visitor.getVirtualNetworkApplianceFactory().getRouterService();
|
||||||
|
|
||||||
// de-associate IPs before unplugging nics
|
// de-associate IPs before unplugging nics
|
||||||
if (!nicsToUnplug.isEmpty()) {
|
if (!nicsToUnplug.isEmpty()) {
|
||||||
@ -107,6 +109,12 @@ public class NicPlugInOutRules extends RuleApplier {
|
|||||||
|
|
||||||
// 1) Unplug the nics
|
// 1) Unplug the nics
|
||||||
for (Entry<String, PublicIpAddress> entry : nicsToUnplug.entrySet()) {
|
for (Entry<String, PublicIpAddress> entry : nicsToUnplug.entrySet()) {
|
||||||
|
PublicIpAddress ip = entry.getValue();
|
||||||
|
NicVO nic = nicDao.findByIp4AddressAndNetworkIdAndInstanceId(ip.getNetworkId(), _router.getId(), ip.getAddress().addr());
|
||||||
|
if (nic != null) {
|
||||||
|
s_logger.info("Collect network statistics for nic " + nic + " from router " + _router);
|
||||||
|
routerService.collectNetworkStatistics(_router, nic);
|
||||||
|
}
|
||||||
Network publicNtwk = null;
|
Network publicNtwk = null;
|
||||||
try {
|
try {
|
||||||
publicNtwk = networkModel.getNetwork(entry.getValue().getNetworkId());
|
publicNtwk = networkModel.getNetwork(entry.getValue().getNetworkId());
|
||||||
|
|||||||
@ -26,6 +26,7 @@ import com.cloud.dc.dao.HostPodDao;
|
|||||||
import com.cloud.dc.dao.VlanDao;
|
import com.cloud.dc.dao.VlanDao;
|
||||||
import com.cloud.network.IpAddressManager;
|
import com.cloud.network.IpAddressManager;
|
||||||
import com.cloud.network.NetworkModel;
|
import com.cloud.network.NetworkModel;
|
||||||
|
import com.cloud.network.VpcVirtualNetworkApplianceService;
|
||||||
import com.cloud.network.dao.FirewallRulesDao;
|
import com.cloud.network.dao.FirewallRulesDao;
|
||||||
import com.cloud.network.dao.IPAddressDao;
|
import com.cloud.network.dao.IPAddressDao;
|
||||||
import com.cloud.network.dao.LoadBalancerDao;
|
import com.cloud.network.dao.LoadBalancerDao;
|
||||||
@ -98,6 +99,8 @@ public class VirtualNetworkApplianceFactory {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private NetworkTopologyContext _networkTopologyContext;
|
private NetworkTopologyContext _networkTopologyContext;
|
||||||
|
@Inject
|
||||||
|
private VpcVirtualNetworkApplianceService _routerService;
|
||||||
|
|
||||||
public NetworkModel getNetworkModel() {
|
public NetworkModel getNetworkModel() {
|
||||||
return _networkModel;
|
return _networkModel;
|
||||||
@ -190,4 +193,8 @@ public class VirtualNetworkApplianceFactory {
|
|||||||
public FirewallRulesDao getFirewallRulesDao() {
|
public FirewallRulesDao getFirewallRulesDao() {
|
||||||
return _rulesDao;
|
return _rulesDao;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public VpcVirtualNetworkApplianceService getRouterService() {
|
||||||
|
return _routerService;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,6 +41,7 @@ import com.cloud.user.Account;
|
|||||||
import com.cloud.user.User;
|
import com.cloud.user.User;
|
||||||
import com.cloud.utils.component.ManagerBase;
|
import com.cloud.utils.component.ManagerBase;
|
||||||
import com.cloud.vm.DomainRouterVO;
|
import com.cloud.vm.DomainRouterVO;
|
||||||
|
import com.cloud.vm.Nic;
|
||||||
import com.cloud.vm.VirtualMachineProfile;
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@ -280,4 +281,10 @@ public class MockVpcVirtualNetworkApplianceManager extends ManagerBase implement
|
|||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends VirtualRouter> void collectNetworkStatistics(T router, Nic nic) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -476,11 +476,6 @@ class CsIP:
|
|||||||
"-A PREROUTING -m state --state NEW -i %s -s %s ! -d %s/32 -j ACL_OUTBOUND_%s" %
|
"-A PREROUTING -m state --state NEW -i %s -s %s ! -d %s/32 -j ACL_OUTBOUND_%s" %
|
||||||
(self.dev, guestNetworkCidr, self.address['gateway'], self.dev)])
|
(self.dev, guestNetworkCidr, self.address['gateway'], self.dev)])
|
||||||
|
|
||||||
self.fw.append(["", "front", "-A NETWORK_STATS_%s -i %s -d %s" %
|
|
||||||
("eth1", "eth1", guestNetworkCidr)])
|
|
||||||
self.fw.append(["", "front", "-A NETWORK_STATS_%s -o %s -s %s" %
|
|
||||||
("eth1", "eth1", guestNetworkCidr)])
|
|
||||||
|
|
||||||
if self.is_private_gateway():
|
if self.is_private_gateway():
|
||||||
self.fw.append(["filter", "", "-A FORWARD -d %s -o %s -j ACL_INBOUND_%s" %
|
self.fw.append(["filter", "", "-A FORWARD -d %s -o %s -j ACL_INBOUND_%s" %
|
||||||
(self.address['network'], self.dev, self.dev)])
|
(self.address['network'], self.dev, self.dev)])
|
||||||
@ -518,6 +513,10 @@ class CsIP:
|
|||||||
["mangle", "", "-A VPN_STATS_%s -i %s -m mark --mark 0x524/0xffffffff" % (self.dev, self.dev)])
|
["mangle", "", "-A VPN_STATS_%s -i %s -m mark --mark 0x524/0xffffffff" % (self.dev, self.dev)])
|
||||||
self.fw.append(
|
self.fw.append(
|
||||||
["", "front", "-A FORWARD -j NETWORK_STATS_%s" % self.dev])
|
["", "front", "-A FORWARD -j NETWORK_STATS_%s" % self.dev])
|
||||||
|
self.fw.append(
|
||||||
|
["", "front", "-A NETWORK_STATS_%s -s %s -o %s" % (self.dev, self.cl.get_vpccidr(), self.dev)])
|
||||||
|
self.fw.append(
|
||||||
|
["", "front", "-A NETWORK_STATS_%s -d %s -i %s" % (self.dev, self.cl.get_vpccidr(), self.dev)])
|
||||||
|
|
||||||
self.fw.append(["", "front", "-A FORWARD -j NETWORK_STATS"])
|
self.fw.append(["", "front", "-A FORWARD -j NETWORK_STATS"])
|
||||||
self.fw.append(["", "front", "-A INPUT -j NETWORK_STATS"])
|
self.fw.append(["", "front", "-A INPUT -j NETWORK_STATS"])
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user