Java tutorial
/** * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. * * This software is licensed under the GNU General Public License v3 or later. * * It is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package com.cloud.network.security; import java.util.ArrayList; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import javax.ejb.Local; import javax.naming.ConfigurationException; import org.apache.commons.codec.digest.DigestUtils; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; import com.cloud.agent.api.Command; import com.cloud.agent.api.NetworkIngressRulesCmd; import com.cloud.agent.api.NetworkIngressRulesCmd.IpPortAndProto; import com.cloud.configuration.dao.ConfigurationDao; import com.cloud.domain.DomainVO; import com.cloud.domain.dao.DomainDao; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.PermissionDeniedException; import com.cloud.exception.ResourceInUseException; import com.cloud.network.security.NetworkGroupWorkVO.Step; import com.cloud.network.security.dao.IngressRuleDao; import com.cloud.network.security.dao.NetworkGroupDao; import com.cloud.network.security.dao.NetworkGroupRulesDao; import com.cloud.network.security.dao.NetworkGroupVMMapDao; import com.cloud.network.security.dao.NetworkGroupWorkDao; import com.cloud.network.security.dao.VmRulesetLogDao; import com.cloud.server.Criteria; import com.cloud.server.ManagementServer; import com.cloud.user.Account; import com.cloud.user.AccountVO; import com.cloud.user.dao.AccountDao; import com.cloud.utils.Pair; import com.cloud.utils.component.ComponentLocator; import com.cloud.utils.component.Inject; import com.cloud.utils.concurrency.NamedThreadFactory; import com.cloud.utils.db.DB; import com.cloud.utils.db.Filter; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.State; import com.cloud.vm.UserVm; import com.cloud.vm.dao.UserVmDao; @Local(value = { NetworkGroupManager.class }) public class NetworkGroupManagerImpl implements NetworkGroupManager { public static final Logger s_logger = Logger.getLogger(NetworkGroupManagerImpl.class.getName()); @Inject NetworkGroupDao _networkGroupDao; @Inject IngressRuleDao _ingressRuleDao; @Inject NetworkGroupVMMapDao _networkGroupVMMapDao; @Inject NetworkGroupRulesDao _networkGroupRulesDao; @Inject UserVmDao _userVMDao; @Inject AccountDao _accountDao; @Inject ConfigurationDao _configDao; @Inject NetworkGroupWorkDao _workDao; @Inject VmRulesetLogDao _rulesetLogDao; @Inject DomainDao _domainDao; @Inject AgentManager _agentMgr; ScheduledExecutorService _executorPool; ScheduledExecutorService _cleanupExecutor; private long _serverId; private final long _timeBetweenCleanups = 30; //seconds boolean _enabled = false; NetworkGroupListener _answerListener; private final class NetworkGroupVOComparator implements Comparator<NetworkGroupVO> { @Override public int compare(NetworkGroupVO o1, NetworkGroupVO o2) { return o1.getId().compareTo(o2.getId()); } } public class WorkerThread implements Runnable { @Override public void run() { work(); } WorkerThread() { } } public class CleanupThread implements Runnable { @Override public void run() { cleanupFinishedWork(); cleanupUnfinishedWork(); } CleanupThread() { } } public static class PortAndProto implements Comparable<PortAndProto> { String proto; int startPort; int endPort; public PortAndProto(String proto, int startPort, int endPort) { this.proto = proto; this.startPort = startPort; this.endPort = endPort; } public String getProto() { return proto; } public int getStartPort() { return startPort; } public int getEndPort() { return endPort; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + endPort; result = prime * result + ((proto == null) ? 0 : proto.hashCode()); result = prime * result + startPort; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; PortAndProto other = (PortAndProto) obj; if (endPort != other.endPort) return false; if (proto == null) { if (other.proto != null) return false; } else if (!proto.equals(other.proto)) return false; if (startPort != other.startPort) return false; return true; } @Override public int compareTo(PortAndProto obj) { if (this == obj) return 0; if (obj == null) return 1; if (proto == null) { if (obj.proto != null) return -1; else return 0; } if (!obj.proto.equalsIgnoreCase(proto)) { return proto.compareTo(obj.proto); } if (startPort < obj.startPort) return -1; else if (startPort > obj.startPort) return 1; if (endPort < obj.endPort) return -1; else if (endPort > obj.endPort) return 1; return 0; } } @Override public void handleVmStateTransition(UserVm userVm, State vmState) { if (!_enabled) { return; } switch (vmState) { case Creating: case Destroyed: case Error: case Migrating: case Expunging: case Starting: case Unknown: return; case Running: handleVmStarted(userVm); break; case Stopping: case Stopped: handleVmStopped(userVm); break; } } public static class CidrComparator implements Comparator<String> { @Override public int compare(String cidr1, String cidr2) { return cidr1.compareTo(cidr2); //FIXME } } protected Map<PortAndProto, Set<String>> generateRulesForVM(Long userVmId) { Map<PortAndProto, Set<String>> allowed = new TreeMap<PortAndProto, Set<String>>(); List<NetworkGroupVMMapVO> groupsForVm = _networkGroupVMMapDao.listByInstanceId(userVmId); for (NetworkGroupVMMapVO mapVO : groupsForVm) { List<IngressRuleVO> rules = _ingressRuleDao.listByNetworkGroupId(mapVO.getNetworkGroupId()); for (IngressRuleVO rule : rules) { PortAndProto portAndProto = new PortAndProto(rule.getProtocol(), rule.getStartPort(), rule.getEndPort()); Set<String> cidrs = allowed.get(portAndProto); if (cidrs == null) { cidrs = new TreeSet<String>(new CidrComparator()); } if (rule.getAllowedNetworkId() != null) { List<NetworkGroupVMMapVO> allowedInstances = _networkGroupVMMapDao .listByNetworkGroup(rule.getAllowedNetworkId(), State.Running); for (NetworkGroupVMMapVO ngmapVO : allowedInstances) { String cidr = ngmapVO.getGuestIpAddress(); if (cidr != null) { cidr = cidr + "/32"; cidrs.add(cidr); } } } else if (rule.getAllowedSourceIpCidr() != null) { cidrs.add(rule.getAllowedSourceIpCidr()); } if (cidrs.size() > 0) allowed.put(portAndProto, cidrs); } } return allowed; } private String generateRulesetSignature(Map<PortAndProto, Set<String>> allowed) { String ruleset = allowed.toString(); return DigestUtils.md5Hex(ruleset); } protected void handleVmStarted(UserVm userVm) { Set<Long> affectedVms = getAffectedVmsForVmStart(userVm); scheduleRulesetUpdateToHosts(affectedVms, true, null); } @DB public void scheduleRulesetUpdateToHosts(Set<Long> affectedVms, boolean updateSeqno, Long delayMs) { if (!_enabled) { return; } if (delayMs == null) delayMs = new Long(100l); for (Long vmId : affectedVms) { Transaction txn = Transaction.currentTxn(); txn.start(); VmRulesetLogVO log = null; NetworkGroupWorkVO work = null; UserVm vm = null; try { vm = _userVMDao.acquire(vmId); if (vm == null) { s_logger.warn("Failed to acquire lock on vm id " + vmId); continue; } log = _rulesetLogDao.findByVmId(vmId); if (log == null) { log = new VmRulesetLogVO(vmId); log = _rulesetLogDao.persist(log); } if (log != null && updateSeqno) { log.incrLogsequence(); _rulesetLogDao.update(log.getId(), log); } work = _workDao.findByVmIdStep(vmId, Step.Scheduled); if (work == null) { work = new NetworkGroupWorkVO(vmId, null, null, NetworkGroupWorkVO.Step.Scheduled, null); work = _workDao.persist(work); } work.setLogsequenceNumber(log.getLogsequence()); _workDao.update(work.getId(), work); } finally { if (vm != null) { _userVMDao.release(vmId); } } txn.commit(); _executorPool.schedule(new WorkerThread(), delayMs, TimeUnit.MILLISECONDS); } } protected Set<Long> getAffectedVmsForVmStart(UserVm userVm) { Set<Long> affectedVms = new HashSet<Long>(); affectedVms.add(userVm.getId()); List<NetworkGroupVMMapVO> groupsForVm = _networkGroupVMMapDao.listByInstanceId(userVm.getId()); //For each group, find the ingress rules that allow the group for (NetworkGroupVMMapVO mapVO : groupsForVm) {//FIXME: use custom sql in the dao List<IngressRuleVO> allowingRules = _ingressRuleDao .listByAllowedNetworkGroupId(mapVO.getNetworkGroupId()); //For each ingress rule that allows a group that the vm belongs to, find the group it belongs to affectedVms.addAll(getAffectedVmsForIngressRules(allowingRules)); } return affectedVms; } protected Set<Long> getAffectedVmsForVmStop(UserVm userVm) { Set<Long> affectedVms = new HashSet<Long>(); List<NetworkGroupVMMapVO> groupsForVm = _networkGroupVMMapDao.listByInstanceId(userVm.getId()); //For each group, find the ingress rules that allow the group for (NetworkGroupVMMapVO mapVO : groupsForVm) {//FIXME: use custom sql in the dao List<IngressRuleVO> allowingRules = _ingressRuleDao .listByAllowedNetworkGroupId(mapVO.getNetworkGroupId()); //For each ingress rule that allows a group that the vm belongs to, find the group it belongs to affectedVms.addAll(getAffectedVmsForIngressRules(allowingRules)); } return affectedVms; } protected Set<Long> getAffectedVmsForIngressRules(List<IngressRuleVO> allowingRules) { Set<Long> distinctGroups = new HashSet<Long>(); Set<Long> affectedVms = new HashSet<Long>(); for (IngressRuleVO allowingRule : allowingRules) { distinctGroups.add(allowingRule.getNetworkGroupId()); } for (Long groupId : distinctGroups) { //allVmUpdates.putAll(generateRulesetForGroupMembers(groupId)); affectedVms.addAll(_networkGroupVMMapDao.listVmIdsByNetworkGroup(groupId)); } return affectedVms; } protected NetworkIngressRulesCmd generateRulesetCmd(String vmName, String guestIp, String guestMac, Long vmId, String signature, long seqnum, Map<PortAndProto, Set<String>> rules) { List<IpPortAndProto> result = new ArrayList<IpPortAndProto>(); for (PortAndProto pAp : rules.keySet()) { Set<String> cidrs = rules.get(pAp); if (cidrs.size() > 0) { IpPortAndProto ipPortAndProto = new NetworkIngressRulesCmd.IpPortAndProto(pAp.getProto(), pAp.getStartPort(), pAp.getEndPort(), cidrs.toArray(new String[cidrs.size()])); result.add(ipPortAndProto); } } return new NetworkIngressRulesCmd(guestIp, guestMac, vmName, vmId, signature, seqnum, result.toArray(new IpPortAndProto[result.size()])); } protected void handleVmStopped(UserVm userVm) { Set<Long> affectedVms = getAffectedVmsForVmStop(userVm); scheduleRulesetUpdateToHosts(affectedVms, true, null); } @Override @DB public List<IngressRuleVO> authorizeNetworkGroupIngress(AccountVO account, String groupName, String protocol, int startPort, int endPort, String[] cidrList, List<NetworkGroupVO> authorizedGroups) { if (!_enabled) { return null; } final Transaction txn = Transaction.currentTxn(); final Long accountId = account.getId(); final Set<NetworkGroupVO> authorizedGroups2 = new TreeSet<NetworkGroupVO>(new NetworkGroupVOComparator()); authorizedGroups2.addAll(authorizedGroups); //Ensure we don't re-lock the same row txn.start(); NetworkGroupVO networkGroup = _networkGroupDao.findByAccountAndName(accountId, groupName); if (networkGroup == null) { s_logger.warn("Network security group not found: name= " + groupName); return null; } //Prevents other threads/management servers from creating duplicate ingress rules NetworkGroupVO networkGroupLock = _networkGroupDao.acquire(networkGroup.getId()); if (networkGroupLock == null) { s_logger.warn("Could not acquire lock on network security group: name= " + groupName); return null; } List<IngressRuleVO> newRules = new ArrayList<IngressRuleVO>(); try { //Don't delete the group from under us. networkGroup = _networkGroupDao.lock(networkGroup.getId(), false); if (networkGroup == null) { s_logger.warn("Could not acquire lock on network group " + groupName); return null; } for (final NetworkGroupVO ngVO : authorizedGroups2) { final Long ngId = ngVO.getId(); //Don't delete the referenced group from under us if (ngVO.getId() != networkGroup.getId()) { final NetworkGroupVO tmpGrp = _networkGroupDao.lock(ngId, false); if (tmpGrp == null) { s_logger.warn("Failed to acquire lock on network group: " + ngId); txn.rollback(); return null; } } IngressRuleVO ingressRule = _ingressRuleDao.findByProtoPortsAndAllowedGroupId(networkGroup.getId(), protocol, startPort, endPort, ngVO.getId()); if (ingressRule != null) { continue; //rule already exists. } ingressRule = new IngressRuleVO(networkGroup.getId(), startPort, endPort, protocol, ngVO.getId(), ngVO.getName(), ngVO.getAccountName()); ingressRule = _ingressRuleDao.persist(ingressRule); newRules.add(ingressRule); } for (String cidr : cidrList) { IngressRuleVO ingressRule = _ingressRuleDao.findByProtoPortsAndCidr(networkGroup.getId(), protocol, startPort, endPort, cidr); if (ingressRule != null) { continue; } ingressRule = new IngressRuleVO(networkGroup.getId(), startPort, endPort, protocol, cidr); ingressRule = _ingressRuleDao.persist(ingressRule); newRules.add(ingressRule); } if (s_logger.isDebugEnabled()) { s_logger.debug("Added " + newRules.size() + " rules to network group " + groupName); } txn.commit(); final Set<Long> affectedVms = new HashSet<Long>(); affectedVms.addAll(_networkGroupVMMapDao.listVmIdsByNetworkGroup(networkGroup.getId())); scheduleRulesetUpdateToHosts(affectedVms, true, null); return newRules; } catch (Exception e) { s_logger.warn("Exception caught when adding ingress rules ", e); throw new CloudRuntimeException("Exception caught when adding ingress rules", e); } finally { if (networkGroupLock != null) { _networkGroupDao.release(networkGroupLock.getId()); } } } @Override @DB public boolean revokeNetworkGroupIngress(AccountVO account, String groupName, String protocol, int startPort, int endPort, String[] cidrList, List<NetworkGroupVO> authorizedGroups) { if (!_enabled) { return false; } int numDeleted = 0; final int numToDelete = cidrList.length + authorizedGroups.size(); final Transaction txn = Transaction.currentTxn(); final Long accountId = account.getId(); NetworkGroupVO networkGroup = _networkGroupDao.findByAccountAndName(accountId, groupName); if (networkGroup == null) { s_logger.warn("Network security group not found: name= " + groupName); return false; } try { txn.start(); networkGroup = _networkGroupDao.acquire(networkGroup.getId()); if (networkGroup == null) { s_logger.warn("Could not acquire lock on network security group: name= " + groupName); return false; } for (final NetworkGroupVO ngVO : authorizedGroups) { numDeleted += _ingressRuleDao.deleteByPortProtoAndGroup(networkGroup.getId(), protocol, startPort, endPort, ngVO.getId()); } for (final String cidr : cidrList) { numDeleted += _ingressRuleDao.deleteByPortProtoAndCidr(networkGroup.getId(), protocol, startPort, endPort, cidr); } s_logger.debug("revokeNetworkGroupIngress for group: " + groupName + ", numToDelete=" + numToDelete + ", numDeleted=" + numDeleted); final Set<Long> affectedVms = new HashSet<Long>(); affectedVms.addAll(_networkGroupVMMapDao.listVmIdsByNetworkGroup(networkGroup.getId())); scheduleRulesetUpdateToHosts(affectedVms, true, null); return true; } catch (Exception e) { s_logger.warn("Exception caught when deleting ingress rules ", e); throw new CloudRuntimeException("Exception caught when deleting ingress rules", e); } finally { if (networkGroup != null) { _networkGroupDao.release(networkGroup.getId()); } txn.commit(); } } @DB @Override public NetworkGroupVO createNetworkGroup(String name, String description, Long domainId, Long accountId, String accountName) { if (!_enabled) { return null; } final Transaction txn = Transaction.currentTxn(); AccountVO account = null; txn.start(); try { account = _accountDao.acquire(accountId); //to ensure duplicate group names are not created. if (account == null) { s_logger.warn("Failed to acquire lock on account"); return null; } NetworkGroupVO group = _networkGroupDao.findByAccountAndName(accountId, name); if (group == null) { group = new NetworkGroupVO(name, description, domainId, accountId, accountName); group = _networkGroupDao.persist(group); } return group; } finally { if (account != null) { _accountDao.release(accountId); } txn.commit(); } } @Override public boolean configure(String name, Map<String, Object> params) throws ConfigurationException { String enabled = _configDao.getValue("direct.attach.network.groups.enabled"); if ("true".equalsIgnoreCase(enabled)) { _enabled = true; } if (!_enabled) { return false; } _answerListener = new NetworkGroupListener(this, _agentMgr, _workDao); _agentMgr.registerForHostEvents(_answerListener, true, true, true); _serverId = ((ManagementServer) ComponentLocator.getComponent(ManagementServer.Name)).getId(); _executorPool = Executors.newScheduledThreadPool(10, new NamedThreadFactory("NWGRP")); _cleanupExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("NWGRP-Cleanup")); return true; } @Override public String getName() { return this.getClass().getName(); } @Override public boolean start() { if (!_enabled) { return true; } _cleanupExecutor.scheduleAtFixedRate(new CleanupThread(), _timeBetweenCleanups, _timeBetweenCleanups, TimeUnit.SECONDS); return true; } @Override public boolean stop() { return true; } @Override public NetworkGroupVO createDefaultNetworkGroup(Long accountId) { if (!_enabled) { return null; } NetworkGroupVO groupVO = _networkGroupDao.findByAccountAndName(accountId, NetworkGroupManager.DEFAULT_GROUP_NAME); if (groupVO == null) { Account accVO = _accountDao.findById(accountId); if (accVO != null) { return createNetworkGroup(NetworkGroupManager.DEFAULT_GROUP_NAME, NetworkGroupManager.DEFAULT_GROUP_DESCRIPTION, accVO.getDomainId(), accVO.getId(), accVO.getAccountName()); } } return groupVO; } @DB public void work() { s_logger.trace("Checking the database"); final NetworkGroupWorkVO work = _workDao.take(_serverId); if (work == null) { return; } Long userVmId = work.getInstanceId(); UserVm vm = null; Long seqnum = null; s_logger.info("Working on " + work.toString()); final Transaction txn = Transaction.currentTxn(); txn.start(); try { vm = _userVMDao.acquire(work.getInstanceId()); if (vm == null) { s_logger.warn("Unable to acquire lock on vm id=" + userVmId); return; } Long agentId = null; VmRulesetLogVO log = _rulesetLogDao.findByVmId(userVmId); if (log == null) { s_logger.warn("Cannot find log record for vm id=" + userVmId); return; } seqnum = log.getLogsequence(); if (vm != null && vm.getState() == State.Running) { Map<PortAndProto, Set<String>> rules = generateRulesForVM(userVmId); agentId = vm.getHostId(); if (agentId != null) { _rulesetLogDao.findByVmId(work.getInstanceId()); NetworkIngressRulesCmd cmd = generateRulesetCmd(vm.getInstanceName(), vm.getGuestIpAddress(), vm.getGuestMacAddress(), vm.getId(), generateRulesetSignature(rules), seqnum, rules); Command[] cmds = new Command[] { cmd }; try { _agentMgr.send(agentId, cmds, false, _answerListener); } catch (AgentUnavailableException e) { s_logger.debug("Unable to send updates for vm: " + userVmId + "(agentid=" + agentId + ")"); _workDao.updateStep(work.getInstanceId(), seqnum, Step.Done); } } } } finally { if (vm != null) { _userVMDao.release(userVmId); _workDao.updateStep(work.getId(), Step.Done); } txn.commit(); } } @Override @DB public boolean addInstanceToGroups(final Long userVmId, final List<NetworkGroupVO> groups) { if (groups != null) { final Set<NetworkGroupVO> uniqueGroups = new TreeSet<NetworkGroupVO>(new NetworkGroupVOComparator()); uniqueGroups.addAll(groups); final Transaction txn = Transaction.currentTxn(); txn.start(); UserVm userVm = _userVMDao.acquire(userVmId); //ensures that duplicate entries are not created. if (userVm == null) { s_logger.warn("Failed to acquire lock on user vm id=" + userVmId); } try { for (NetworkGroupVO networkGroup : uniqueGroups) { //don't let the group be deleted from under us. NetworkGroupVO ngrpLock = _networkGroupDao.lock(networkGroup.getId(), false); if (ngrpLock == null) { s_logger.warn("Failed to acquire lock on network group id=" + networkGroup.getId() + " name=" + networkGroup.getName()); txn.rollback(); return false; } if (_networkGroupVMMapDao.findByVmIdGroupId(userVmId, networkGroup.getId()) == null) { NetworkGroupVMMapVO groupVmMapVO = new NetworkGroupVMMapVO(networkGroup.getId(), userVmId); _networkGroupVMMapDao.persist(groupVmMapVO); } } txn.commit(); return true; } finally { if (userVm != null) { _userVMDao.release(userVmId); } } } return false; } @Override @DB public void removeInstanceFromGroups(Long userVmId) { final Transaction txn = Transaction.currentTxn(); txn.start(); UserVm userVm = _userVMDao.acquire(userVmId); //ensures that duplicate entries are not created in addInstance if (userVm == null) { s_logger.warn("Failed to acquire lock on user vm id=" + userVmId); } int n = _networkGroupVMMapDao.deleteVM(userVmId); s_logger.info("Disassociated " + n + " network groups " + " from uservm " + userVmId); _userVMDao.release(userVmId); txn.commit(); } @DB @Override public void deleteNetworkGroup(Long groupId, Long accountId) throws ResourceInUseException, PermissionDeniedException { if (!_enabled) { return; } final Transaction txn = Transaction.currentTxn(); txn.start(); final NetworkGroupVO group = _networkGroupDao.lock(groupId, true); if (group == null) { s_logger.info("Not deleting group -- cannot find id " + groupId); return; } if (group.getName().equalsIgnoreCase(NetworkGroupManager.DEFAULT_GROUP_NAME)) { txn.rollback(); throw new PermissionDeniedException("The network group default is reserved"); } List<IngressRuleVO> allowingRules = _ingressRuleDao.listByAllowedNetworkGroupId(groupId); if (allowingRules.size() != 0) { txn.rollback(); throw new ResourceInUseException( "Cannot delete group when there are ingress rules that allow this group"); } List<IngressRuleVO> rulesInGroup = _ingressRuleDao.listByNetworkGroupId(groupId); if (rulesInGroup.size() != 0) { txn.rollback(); throw new ResourceInUseException("Cannot delete group when there are ingress rules in this group"); } _networkGroupDao.delete(groupId); txn.commit(); } @Override public List<NetworkGroupRulesVO> searchForNetworkGroupRules(Criteria c) { Filter searchFilter = new Filter(NetworkGroupRulesVO.class, "id", true, c.getOffset(), c.getLimit()); Object accountId = c.getCriteria(Criteria.ACCOUNTID); Object domainId = c.getCriteria(Criteria.DOMAINID); Object networkGroup = c.getCriteria(Criteria.NETWORKGROUP); Object instanceId = c.getCriteria(Criteria.INSTANCEID); Object recursive = c.getCriteria(Criteria.ISRECURSIVE); Object keyword = c.getCriteria(Criteria.KEYWORD); SearchBuilder<NetworkGroupRulesVO> sb = _networkGroupRulesDao.createSearchBuilder(); sb.and("accountId", sb.entity().getAccountId(), SearchCriteria.Op.EQ); sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); sb.and("domainId", sb.entity().getDomainId(), SearchCriteria.Op.EQ); // only do a recursive domain search if the search is not limited by account or instance if ((accountId == null) && (instanceId == null) && (domainId != null) && Boolean.TRUE.equals(recursive)) { SearchBuilder<DomainVO> domainSearch = _domainDao.createSearchBuilder(); domainSearch.and("path", domainSearch.entity().getPath(), SearchCriteria.Op.LIKE); sb.join("domainSearch", domainSearch, sb.entity().getDomainId(), domainSearch.entity().getId()); } SearchCriteria sc = sb.create(); if (accountId != null) { sc.setParameters("accountId", accountId); if (networkGroup != null) { sc.setParameters("name", networkGroup); } else if (keyword != null) { SearchCriteria ssc = _networkGroupRulesDao.createSearchCriteria(); ssc.addOr("name", SearchCriteria.Op.LIKE, "%" + keyword + "%"); ssc.addOr("description", SearchCriteria.Op.LIKE, "%" + keyword + "%"); sc.addAnd("name", SearchCriteria.Op.SC, ssc); } } else if (instanceId != null) { return listNetworkGroupRulesByVM(((Long) instanceId).longValue()); } else if (domainId != null) { if (Boolean.TRUE.equals(recursive)) { DomainVO domain = _domainDao.findById((Long) domainId); sc.setJoinParameters("domainSearch", "path", domain.getPath() + "%"); } else { sc.setParameters("domainId", domainId); } } return _networkGroupRulesDao.search(sc, searchFilter); } private List<NetworkGroupRulesVO> listNetworkGroupRulesByVM(long vmId) { List<NetworkGroupRulesVO> results = new ArrayList<NetworkGroupRulesVO>(); List<NetworkGroupVMMapVO> networkGroupMappings = _networkGroupVMMapDao.listByInstanceId(vmId); if (networkGroupMappings != null) { for (NetworkGroupVMMapVO networkGroupMapping : networkGroupMappings) { NetworkGroupVO group = _networkGroupDao.findById(networkGroupMapping.getNetworkGroupId()); List<NetworkGroupRulesVO> rules = _networkGroupRulesDao.listNetworkGroupRules(group.getAccountId(), networkGroupMapping.getGroupName()); if (rules != null) { results.addAll(rules); } } } return results; } @Override public void fullSync(long agentId, HashMap<String, Pair<Long, Long>> newGroupStates) { Set<Long> affectedVms = new HashSet<Long>(); for (String vmName : newGroupStates.keySet()) { Long vmId = newGroupStates.get(vmName).first(); Long seqno = newGroupStates.get(vmName).second(); VmRulesetLogVO log = _rulesetLogDao.findByVmId(vmId); if (log != null && log.getLogsequence() != seqno) { affectedVms.add(vmId); } } if (affectedVms.size() > 0) { s_logger.info("Network Group full sync for agent " + agentId + " found " + affectedVms.size() + " vms out of sync"); scheduleRulesetUpdateToHosts(affectedVms, false, null); } } public void cleanupFinishedWork() { Date before = new Date(System.currentTimeMillis() - 24 * 3600 * 1000l); int numDeleted = _workDao.deleteFinishedWork(before); if (numDeleted > 0) { s_logger.info("Network Group Work cleanup deleted " + numDeleted + " finished work items older than " + before.toString()); } } private void cleanupUnfinishedWork() { Date before = new Date(System.currentTimeMillis() - 30 * 1000l); List<NetworkGroupWorkVO> unfinished = _workDao.findUnfinishedWork(before); if (unfinished.size() > 0) { s_logger.info("Network Group Work cleanup found " + unfinished.size() + " unfinished work items older than " + before.toString()); Set<Long> affectedVms = new HashSet<Long>(); for (NetworkGroupWorkVO work : unfinished) { affectedVms.add(work.getInstanceId()); } scheduleRulesetUpdateToHosts(affectedVms, false, null); } else { s_logger.debug( "Network Group Work cleanup found no unfinished work items older than " + before.toString()); } } @Override public String getNetworkGroupsNamesForVm(long vmId) { try { List<NetworkGroupVMMapVO> networkGroupsToVmMap = _networkGroupVMMapDao.listByInstanceId(vmId); int size = 0; int j = 0; StringBuilder networkGroupNames = new StringBuilder(); if (networkGroupsToVmMap != null) { size = networkGroupsToVmMap.size(); for (NetworkGroupVMMapVO nG : networkGroupsToVmMap) { //get the group id and look up for the group name NetworkGroupVO currentNetworkGroup = _networkGroupDao.findById(nG.getNetworkGroupId()); networkGroupNames.append(currentNetworkGroup.getName()); if (j < (size - 1)) { networkGroupNames.append(","); j++; } } } return networkGroupNames.toString(); } catch (Exception e) { s_logger.warn("Error trying to get network groups for a vm: " + e); return null; } } }