| // 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 org.apache.cloudstack.network.contrail.management; |
| |
| import java.lang.reflect.Method; |
| import java.util.HashMap; |
| |
| import javax.inject.Inject; |
| |
| import org.apache.log4j.Logger; |
| import org.springframework.stereotype.Component; |
| |
| import org.apache.cloudstack.framework.messagebus.MessageBus; |
| import org.apache.cloudstack.framework.messagebus.MessageDispatcher; |
| import org.apache.cloudstack.framework.messagebus.MessageHandler; |
| |
| import com.cloud.domain.DomainVO; |
| import com.cloud.domain.dao.DomainDao; |
| import com.cloud.event.EventTypes; |
| import com.cloud.offerings.dao.NetworkOfferingDao; |
| import com.cloud.projects.ProjectVO; |
| import com.cloud.projects.dao.ProjectDao; |
| |
| /* |
| * When an Object is created/deleted in cloudstack DB, it has to be reflected in VNC. |
| * This class handles create, delete and update events of cloudstack db objects. |
| * |
| * - subscribe for interested events |
| * - create events will have db id of the object and hence db object and its parameters can be retrieved |
| * - delete events will have db id but the object no longer exists in db and hence complete class needs to be synchronized |
| * |
| */ |
| @Component |
| public class ServerEventHandlerImpl implements ServerEventHandler { |
| @Inject |
| NetworkOfferingDao _networkOfferingDao; |
| @Inject |
| DomainDao _domainDao; |
| @Inject |
| ProjectDao _projectDao; |
| @Inject |
| private MessageBus _messageBus; |
| @Inject |
| ServerDBSync _dbSync; |
| @Inject |
| ContrailManager _manager; |
| private HashMap<String, Method> _methodMap; |
| private HashMap<String, Class<?>> _classMap; |
| |
| private static final Logger s_logger = Logger.getLogger(MessageHandler.class); |
| |
| ServerEventHandlerImpl() { |
| setMethodMap(); |
| setClassMap(); |
| } |
| |
| private void setMethodMap() { |
| _methodMap = new HashMap<String, Method>(); |
| Method methods[] = this.getClass().getMethods(); |
| for (int i = 0; i < methods.length; i++) { |
| _methodMap.put(methods[i].getName(), methods[i]); |
| } |
| } |
| |
| private void setClassMap() { |
| _classMap = new HashMap<String, Class<?>>(); |
| _classMap.put("Domain", net.juniper.contrail.api.types.Domain.class); |
| _classMap.put("Project", net.juniper.contrail.api.types.Project.class); |
| } |
| |
| @MessageHandler(topic = ".*") |
| public void defaultMessageHandler(String subject, String topic, Object args) { |
| s_logger.info("DB Event Received - topic: " + topic + "; subject: " + subject); |
| |
| org.apache.cloudstack.framework.events.Event event = (org.apache.cloudstack.framework.events.Event)args; |
| |
| /* Method name should be on<ClassName><Operation> for example: onDomainCreate */ |
| Method method = null; |
| |
| try { |
| /* Only create event needs special implementation */ |
| if (event.getEventType().contains("CREATE")) { |
| String methodName = "on" + event.getResourceType() + "Create"; |
| method = _methodMap.get(methodName); |
| if (method == null) { |
| defaultCreateHandler(subject, topic, event); |
| } else { |
| method.invoke(this, subject, topic, event); |
| } |
| } else if (event.getEventType().contains("DELETE")) { |
| defaultDeleteHandler(subject, topic, event); |
| } else { |
| defaultHandler(subject, topic, event); |
| } |
| } catch (Exception e) { |
| s_logger.debug(e); |
| } |
| } |
| |
| /* Default create handler */ |
| void defaultCreateHandler(String subject, String topic, org.apache.cloudstack.framework.events.Event event) { |
| |
| s_logger.debug("Default handler is invoked for subject: " + subject + "; topic: " + topic); |
| s_logger.debug("description: " + event.getDescription()); |
| s_logger.debug("category: " + event.getEventCategory()); |
| s_logger.debug("type: " + event.getResourceType()); |
| s_logger.debug("event-type: " + event.getEventType()); |
| |
| Class<?> cls = _classMap.get(event.getResourceType()); |
| |
| if (cls != null) { |
| _dbSync.syncClass(cls); |
| } |
| |
| return; |
| } |
| |
| /* Default handler */ |
| void defaultDeleteHandler(String subject, String topic, org.apache.cloudstack.framework.events.Event event) { |
| |
| s_logger.debug("Default handler is invoked for subject: " + subject + "; topic: " + topic); |
| |
| s_logger.debug("description: " + event.getDescription()); |
| s_logger.debug("category: " + event.getEventCategory()); |
| s_logger.debug("type: " + event.getResourceType()); |
| s_logger.debug("event-type: " + event.getEventType()); |
| Class<?> cls = _classMap.get(event.getResourceType()); |
| if (cls != null) { |
| _dbSync.syncClass(cls); |
| } |
| return; |
| } |
| |
| /* Default handler */ |
| void defaultHandler(String subject, String topic, org.apache.cloudstack.framework.events.Event event) { |
| |
| s_logger.debug("Default handler is invoked for subject: " + subject + "; topic: " + topic); |
| |
| s_logger.debug("description: " + event.getDescription()); |
| s_logger.debug("category: " + event.getEventCategory()); |
| s_logger.debug("type: " + event.getResourceType()); |
| s_logger.debug("event-type: " + event.getEventType()); |
| Class<?> cls = _classMap.get(event.getResourceType()); |
| if (cls != null) { |
| _dbSync.syncClass(cls); |
| } |
| return; |
| } |
| |
| /* Description string contains substring of format "resourceType Id: <int>" for example: "Project id: 35" |
| * |
| * example: |
| * description: {"details":"Successfully completed deleting project. Project Id: 39","status":"Completed","event":"PROJECT.DELETE","account":"3afca502-d83c-11e2-b748-52540076b7ca","user":"3b111406-d83c-11e2-b748-52540076b7ca"} |
| * |
| * If the description string format is changed, this code has to be modified |
| */ |
| private long parseForId(String resourceType, String description) { |
| String typeStr = resourceType + " Id:"; |
| int idIdx = description.indexOf(typeStr) + typeStr.length(); |
| String idStr = description.substring(idIdx, description.indexOf('"', idIdx)); |
| long id = 0; |
| try { |
| id = Long.parseLong(idStr.trim()); |
| } catch (Exception e) { |
| s_logger.debug("Unable to parse id string<" + idStr.trim() + "> for long value, ignored"); |
| } |
| return id; |
| } |
| |
| public void onDomainCreate(String subject, String topic, org.apache.cloudstack.framework.events.Event event) { |
| s_logger.info("onDomainCreate; topic: " + topic + "; subject: " + subject); |
| try { |
| long id = parseForId(event.getResourceType(), event.getDescription()); |
| if (id != 0) { |
| DomainVO domain = _domainDao.findById(id); |
| if (domain != null) { |
| s_logger.info("createDomain for name: " + domain.getName() + "; uuid: " + domain.getUuid()); |
| StringBuffer logMesg = new StringBuffer(); |
| _dbSync.createDomain(domain, logMesg); |
| } else { |
| /* could not find db record, resync complete class */ |
| _dbSync.syncClass(net.juniper.contrail.api.types.Domain.class); |
| } |
| } else { |
| /* Unknown id, resync complete class */ |
| _dbSync.syncClass(net.juniper.contrail.api.types.Domain.class); |
| } |
| } catch (Exception e) { |
| s_logger.debug(e); |
| } |
| } |
| |
| public void onProjectCreate(String subject, String topic, org.apache.cloudstack.framework.events.Event event) { |
| s_logger.info("onProjectCreate; topic: " + topic + "; subject: " + subject); |
| try { |
| long id = parseForId(event.getResourceType(), event.getDescription()); |
| if (id != 0) { |
| ProjectVO project = _projectDao.findById(id); |
| if (project != null) { |
| s_logger.info("createProject for name: " + project.getName() + "; uuid: " + project.getUuid()); |
| StringBuffer logMesg = new StringBuffer(); |
| _dbSync.createProject(project, logMesg); |
| } else { |
| /* could not find db record, resync complete class */ |
| _dbSync.syncClass(net.juniper.contrail.api.types.Project.class); |
| } |
| } else { |
| /* Unknown id, resync complete class */ |
| _dbSync.syncClass(net.juniper.contrail.api.types.Project.class); |
| } |
| } catch (Exception e) { |
| s_logger.info(e); |
| } |
| |
| } |
| |
| @Override |
| public void subscribe() { |
| /* subscribe to DB events */ |
| _messageBus.subscribe(EventTypes.EVENT_PROJECT_CREATE, MessageDispatcher.getDispatcher(this)); |
| _messageBus.subscribe(EventTypes.EVENT_PROJECT_DELETE, MessageDispatcher.getDispatcher(this)); |
| _messageBus.subscribe(EventTypes.EVENT_DOMAIN_CREATE, MessageDispatcher.getDispatcher(this)); |
| _messageBus.subscribe(EventTypes.EVENT_DOMAIN_DELETE, MessageDispatcher.getDispatcher(this)); |
| } |
| } |