// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package com.cloud.vm; import java.lang.reflect.Method; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import org.apache.log4j.Logger; import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.framework.jobs.AsyncJob; import org.apache.cloudstack.framework.jobs.AsyncJobDispatcher; import org.apache.cloudstack.framework.jobs.AsyncJobManager; import org.apache.cloudstack.framework.jobs.dao.AsyncJobJoinMapDao; import org.apache.cloudstack.framework.jobs.dao.VmWorkJobDao; import org.apache.cloudstack.framework.jobs.impl.AsyncJobJoinMapVO; import org.apache.cloudstack.framework.jobs.impl.VmWorkJobVO; import com.cloud.user.AccountVO; import com.cloud.user.dao.AccountDao; import com.cloud.utils.component.AdapterBase; import com.cloud.vm.dao.VMInstanceDao; /** * Please note: VmWorkJobWakeupDispatcher is not currently in use. It is designed for event-driven based * job processing model. * * Current code base uses blocking calls to wait for job completion */ public class VmWorkJobWakeupDispatcher extends AdapterBase implements AsyncJobDispatcher { private static final Logger s_logger = Logger.getLogger(VmWorkJobWakeupDispatcher.class); @Inject private VmWorkJobDao _workjobDao; @Inject private AsyncJobJoinMapDao _joinMapDao; @Inject private AccountDao _accountDao; @Inject private VMInstanceDao _instanceDao; @Inject private VirtualMachineManager _vmMgr; @Inject private AsyncJobManager _asyncJobMgr; private final Map<String, Method> _handlerMap = new HashMap<String, Method>(); @Override public void runJob(AsyncJob job) { try { List<AsyncJobJoinMapVO> joinRecords = _joinMapDao.listJoinRecords(job.getId()); if (joinRecords.size() != 1) { s_logger.warn("AsyncJob-" + job.getId() + " received wakeup call with un-supported joining job number: " + joinRecords.size()); // if we fail wakeup-execution for any reason, avoid release sync-source if there is any job.setSyncSource(null); return; } AsyncJobJoinMapVO joinRecord = joinRecords.get(0); VmWorkJobVO joinedJob = _workjobDao.findById(joinRecord.getJoinJobId()); Class<?> workClz = null; try { workClz = Class.forName(job.getCmd()); } catch (ClassNotFoundException e) { s_logger.error("VM work class " + job.getCmd() + " is not found", e); return; } // get original work context information from joined job VmWork work = VmWorkSerializer.deserialize(workClz, joinedJob.getCmdInfo()); assert (work != null); AccountVO account = _accountDao.findById(work.getAccountId()); assert (account != null); VMInstanceVO vm = _instanceDao.findById(work.getVmId()); assert (vm != null); CallContext.register(work.getUserId(), work.getAccountId(), job.getRelated()); try { Method handler = getHandler(joinRecord.getWakeupHandler()); if (handler != null) { handler.invoke(_vmMgr); } else { assert (false); s_logger.error("Unable to find wakeup handler " + joinRecord.getWakeupHandler() + " when waking up job-" + job.getId()); } } finally { CallContext.unregister(); } } catch (Throwable e) { s_logger.warn("Unexpected exception in waking up job-" + job.getId()); // if we fail wakeup-execution for any reason, avoid release sync-source if there is any job.setSyncSource(null); } } private Method getHandler(String wakeupHandler) { synchronized (_handlerMap) { Class<?> clz = _vmMgr.getClass(); Method method = _handlerMap.get(wakeupHandler); if (method != null) return method; try { method = clz.getMethod(wakeupHandler); method.setAccessible(true); } catch (SecurityException e) { assert (false); s_logger.error("Unexpected exception", e); return null; } catch (NoSuchMethodException e) { assert (false); s_logger.error("Unexpected exception", e); return null; } _handlerMap.put(wakeupHandler, method); return method; } } }