blob: 05dcdce1a92fce752946f646ee7575e4a977106a [file] [log] [blame]
// 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));
}
}