@Override public boolean processAnswers(long agentId, long seq, Answer[] answers) { List<Long> affectedVms = new ArrayList<Long>(); int commandNum = 0; for (Answer ans : answers) { if (ans instanceof SecurityGroupRuleAnswer) { SecurityGroupRuleAnswer ruleAnswer = (SecurityGroupRuleAnswer) ans; if (ans.getResult()) { s_logger.debug( "Successfully programmed rule " + ruleAnswer.toString() + " into host " + agentId); _workDao.updateStep(ruleAnswer.getVmId(), ruleAnswer.getLogSequenceNumber(), Step.Done); recordSuccess(ruleAnswer.getVmId()); } else { _workDao.updateStep(ruleAnswer.getVmId(), ruleAnswer.getLogSequenceNumber(), Step.Error); ; s_logger.debug( "Failed to program rule " + ruleAnswer.toString() + " into host " + agentId + " due to " + ruleAnswer.getDetails() + " and updated jobs"); if (ruleAnswer.getReason() == FailureReason.CANNOT_BRIDGE_FIREWALL) { s_logger.debug( "Not retrying security group rules for vm " + ruleAnswer.getVmId() + " on failure since host " + agentId + " cannot do bridge firewalling"); } else if (ruleAnswer.getReason() == FailureReason.PROGRAMMING_FAILED) { if (checkShouldRetryOnFailure(ruleAnswer.getVmId())) { s_logger.debug( "Retrying security group rules on failure for vm " + ruleAnswer.getVmId()); affectedVms.add(ruleAnswer.getVmId()); } else { s_logger.debug( "Not retrying security group rules for vm " + ruleAnswer.getVmId() + " on failure: too many retries"); } } } commandNum++; if (_workTracker != null) _workTracker.processAnswers(agentId, seq, answers); } } if (affectedVms.size() > 0) { _securityGroupManager.scheduleRulesetUpdateToHosts(affectedVms, false, new Long(10 * 1000l)); } return true; }
public void cleanupFinishedWork() { Date before = new Date(System.currentTimeMillis() - 6 * 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 processScheduledWork() { List<SecurityGroupWorkVO> scheduled = _workDao.findScheduledWork(); int numJobs = scheduled.size(); if (numJobs > 0) { s_logger.debug("Security group work: found scheduled jobs " + numJobs); Random rand = new Random(); for (int i = 0; i < numJobs; i++) { long delayMs = 100 + 10 * rand.nextInt(numJobs); _executorPool.schedule(new WorkerThread(), delayMs, TimeUnit.MILLISECONDS); } } }
private void cleanupUnfinishedWork() { Date before = new Date(System.currentTimeMillis() - 2 * _timeBetweenCleanups * 1000l); List<SecurityGroupWorkVO> 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()); ArrayList<Long> affectedVms = new ArrayList<Long>(); for (SecurityGroupWorkVO work : unfinished) { affectedVms.add(work.getInstanceId()); work.setStep(Step.Error); _workDao.update(work.getId(), work); } scheduleRulesetUpdateToHosts(affectedVms, false, null); } else { s_logger.debug( "Network Group Work cleanup found no unfinished work items older than " + before.toString()); } }
@DB public void work() { if (s_logger.isTraceEnabled()) { s_logger.trace("Checking the database"); } final SecurityGroupWorkVO work = _workDao.take(_serverId); if (work == null) { if (s_logger.isTraceEnabled()) { s_logger.trace("Security Group work: no work found"); } return; } Long userVmId = work.getInstanceId(); if (work.getStep() == Step.Done) { if (s_logger.isDebugEnabled()) { s_logger.debug( "Security Group work: found a job in done state, rescheduling for vm: " + userVmId); } ArrayList<Long> affectedVms = new ArrayList<Long>(); affectedVms.add(userVmId); scheduleRulesetUpdateToHosts(affectedVms, false, _timeBetweenCleanups * 1000l); return; } UserVm vm = null; Long seqnum = null; s_logger.debug("Working on " + work); final Transaction txn = Transaction.currentTxn(); txn.start(); boolean locked = false; try { vm = _userVMDao.acquireInLockTable(work.getInstanceId()); if (vm == null) { vm = _userVMDao.findById(work.getInstanceId()); if (vm == null) { s_logger.info("VM " + work.getInstanceId() + " is removed"); locked = true; return; } s_logger.warn("Unable to acquire lock on vm id=" + userVmId); return; } locked = true; 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) { SecurityIngressRulesCmd cmd = generateRulesetCmd( vm.getInstanceName(), vm.getPrivateIpAddress(), vm.getPrivateMacAddress(), vm.getId(), generateRulesetSignature(rules), seqnum, rules); Commands cmds = new Commands(cmd); try { _agentMgr.send(agentId, cmds, _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 (locked) { _userVMDao.releaseFromLockTable(userVmId); _workDao.updateStep(work.getId(), Step.Done); } txn.commit(); } }
@DB public void scheduleRulesetUpdateToHosts( List<Long> affectedVms, boolean updateSeqno, Long delayMs) { if (affectedVms.size() == 0) { return; } if (delayMs == null) { delayMs = new Long(100l); } Collections.sort(affectedVms); if (s_logger.isTraceEnabled()) { s_logger.trace( "Security Group Mgr: scheduling ruleset updates for " + affectedVms.size() + " vms"); } boolean locked = _workLock.lock(_globalWorkLockTimeout); if (!locked) { s_logger.warn("Security Group Mgr: failed to acquire global work lock"); return; } if (s_logger.isTraceEnabled()) { s_logger.trace("Security Group Mgr: acquired global work lock"); } Transaction txn = Transaction.currentTxn(); try { txn.start(); for (Long vmId : affectedVms) { if (s_logger.isTraceEnabled()) { s_logger.trace("Security Group Mgr: scheduling ruleset update for " + vmId); } VmRulesetLogVO log = null; SecurityGroupWorkVO work = null; 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 SecurityGroupWorkVO(vmId, null, null, SecurityGroupWork.Step.Scheduled, null); work = _workDao.persist(work); if (s_logger.isTraceEnabled()) { s_logger.trace( "Security Group Mgr: created new work item for " + vmId + "; id = " + work.getId()); } } work.setLogsequenceNumber(log.getLogsequence()); _workDao.update(work.getId(), work); } txn.commit(); for (Long vmId : affectedVms) { _executorPool.schedule(new WorkerThread(), delayMs, TimeUnit.MILLISECONDS); } } finally { _workLock.unlock(); if (s_logger.isTraceEnabled()) { s_logger.trace("Security Group Mgr: released global work lock"); } } }