You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by hu...@apache.org on 2013/11/01 17:55:59 UTC

[4/6] OpenContrail network plugin

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6b5fab2f/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServerDBSyncImpl.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServerDBSyncImpl.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServerDBSyncImpl.java
new file mode 100644
index 0000000..8cb4e8d
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServerDBSyncImpl.java
@@ -0,0 +1,965 @@
+// 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.io.IOException;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.locks.ReentrantLock;
+import java.lang.reflect.Method;
+
+import net.juniper.contrail.api.types.FloatingIp;
+import net.juniper.contrail.api.types.FloatingIpPool;
+import net.juniper.contrail.api.types.ServiceInstance;
+import net.juniper.contrail.api.types.VirtualNetwork;
+import net.juniper.contrail.api.types.VirtualMachine;
+import net.juniper.contrail.api.types.VirtualMachineInterface;
+import net.juniper.contrail.api.types.InstanceIp;
+import net.juniper.contrail.api.ApiConnector;
+import net.juniper.contrail.api.ApiObjectBase;
+import net.juniper.contrail.api.ApiPropertyBase;
+import net.juniper.contrail.api.ObjectReference;
+
+import org.apache.cloudstack.network.contrail.model.FloatingIpModel;
+import org.apache.cloudstack.network.contrail.model.FloatingIpPoolModel;
+import org.apache.cloudstack.network.contrail.model.ServiceInstanceModel;
+import org.apache.cloudstack.network.contrail.model.VMInterfaceModel;
+import org.apache.cloudstack.network.contrail.model.VirtualMachineModel;
+import org.apache.cloudstack.network.contrail.model.VirtualNetworkModel;
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import com.cloud.dc.dao.VlanDao;
+import com.cloud.domain.DomainVO;
+import com.cloud.domain.dao.DomainDao;
+import com.cloud.exception.InternalErrorException;
+import com.cloud.projects.ProjectVO;
+import com.cloud.projects.dao.ProjectDao;
+import com.cloud.network.IpAddress;
+import com.cloud.network.Networks.TrafficType;
+import com.cloud.vm.dao.NicDao;
+import com.cloud.vm.dao.VMInstanceDao;
+import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.NicVO;
+import com.cloud.network.addr.PublicIp;
+import com.cloud.network.dao.IPAddressVO;
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.NetworkVO;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
+
+import javax.inject.Inject;
+
+@Component
+public class ServerDBSyncImpl implements ServerDBSync {
+
+    @Inject DomainDao _domainDao;
+    @Inject ProjectDao _projectDao;
+    @Inject NetworkDao _networksDao;
+    @Inject VMInstanceDao _vmInstanceDao;
+    @Inject NicDao _nicDao;
+    @Inject VlanDao _vlanDao;
+    @Inject PhysicalNetworkDao _physicalNetworkDao;
+    @Inject PhysicalNetworkServiceProviderDao _physProviderDao;
+    @Inject ContrailManager _manager;
+    DBSyncGeneric _dbSync;
+    Class<?>[] _vncClasses;
+    // Read-Write (true) or Read-Only mode.
+    boolean _rw_mode;
+    private final ReentrantLock _lockSyncMode = new ReentrantLock(); 
+
+    ServerDBSyncImpl() {
+        _vncClasses = new Class[] {
+                net.juniper.contrail.api.types.Domain.class,
+                net.juniper.contrail.api.types.Project.class,
+                VirtualNetwork.class,
+                VirtualMachine.class,
+                ServiceInstance.class,
+                FloatingIp.class
+        };
+        _dbSync = new DBSyncGeneric(this);
+    }
+
+    private static final Logger s_logger = Logger.getLogger(ServerDBSync.class);
+
+    /*
+     * API for syncing all classes of vnc objects with cloudstack
+     *
+     * Sync cloudstack and vnc objects.
+     * Order has to be maintained 
+     */
+    @Override
+    public short syncAll(short syncMode) {
+        short syncState = SYNC_STATE_IN_SYNC;
+        
+        /* vnc classes need to be synchronized with cloudstack */
+        s_logger.debug("syncing cloudstack db with vnc");
+        try {
+            for(Class<?> cls : _vncClasses) {
+                
+                /* lock the sync mode*/
+                _lockSyncMode.lock();
+                _rw_mode = syncMode == DBSyncGeneric.SYNC_MODE_UPDATE;
+                _dbSync.setSyncMode(syncMode);
+                
+                if (_dbSync.getSyncMode() == DBSyncGeneric.SYNC_MODE_CHECK) {
+                    s_logger.debug("sync check start: " + DBSyncGeneric.getClassName(cls));
+                } else {
+                    s_logger.debug("sync start: " + DBSyncGeneric.getClassName(cls));
+                }
+
+                if (_dbSync.sync(cls) == false) {
+                    if (_dbSync.getSyncMode() == DBSyncGeneric.SYNC_MODE_CHECK) {
+                        s_logger.info("out of sync detected: " + DBSyncGeneric.getClassName(cls));
+                    } else {
+                        s_logger.info("out of sync detected and re-synced: " + DBSyncGeneric.getClassName(cls));
+                    }
+                    syncState = SYNC_STATE_OUT_OF_SYNC;
+                }
+                if (_dbSync.getSyncMode() == DBSyncGeneric.SYNC_MODE_CHECK) {
+                    s_logger.debug("sync check finish: " + DBSyncGeneric.getClassName(cls));
+                } else {
+                    s_logger.debug("sync finish: " + DBSyncGeneric.getClassName(cls));
+                }
+                /* unlock the sync mode */
+                _lockSyncMode.unlock();
+            } 
+        } catch(Exception ex) {
+            s_logger.warn("DB Synchronization", ex);
+            syncState = SYNC_STATE_UNKNOWN;
+            if (_lockSyncMode.isLocked()) {
+                _lockSyncMode.unlock();
+            }
+        }
+
+        return syncState;
+    } 
+    
+    @Override
+    public void syncClass(Class<?> cls) {
+
+        s_logger.debug("syncClass: " + cls.getName());
+        try {
+            s_logger.debug("sync start: " + DBSyncGeneric.getClassName(cls));
+            _lockSyncMode.lock();
+            _dbSync.setSyncMode(DBSyncGeneric.SYNC_MODE_UPDATE);
+            _dbSync.sync(cls);
+            _lockSyncMode.unlock();
+            s_logger.debug("sync finish: " + DBSyncGeneric.getClassName(cls));
+        } catch(Exception ex) {
+            s_logger.warn("Sync error: " + cls.getName(), ex);
+            if (_lockSyncMode.isLocked()) {
+                _lockSyncMode.unlock();
+            }            
+        }        
+    }
+
+    public <T extends ApiPropertyBase> void deleteChildren(List<ObjectReference<T>> childs,  Class<?> childCls, StringBuffer syncLogMesg) throws Exception {
+        final ApiConnector api = _manager.getApiConnector();
+        if (childs == null) {
+            syncLogMesg.append("no children of type: " + childCls.getName() + "\n");
+            return;
+        }
+        
+        syncLogMesg.append("delete children of type : " + DBSyncGeneric.getClassName(childCls) + "\n");
+        String deleteChildMethod = "delete" + DBSyncGeneric.getClassName(childCls);
+        Method method = null;
+        Method methods[] = this.getClass().getMethods();
+        for (int i = 0; i < methods.length; i++) {
+            if(methods[i].getName().equalsIgnoreCase(deleteChildMethod)) {
+                method = methods[i];
+                break;
+            }
+        }
+        int count = 0;
+        for (ObjectReference<T> childRef: childs) {
+            @SuppressWarnings("unchecked")
+            ApiObjectBase child = (ApiObjectBase) api.findById((Class<? extends ApiObjectBase>)childCls, childRef.getUuid());
+            if (method != null) { 
+               method.invoke(this, child, syncLogMesg);
+            } else {
+                deleteDefault(child, childCls, syncLogMesg);
+            }
+            count ++;
+        }
+        syncLogMesg.append("deleted children count : " + count + "\n"); 
+    }
+
+    public void deleteDefault(ApiObjectBase vnc, Class<?> cls, StringBuffer syncLogMesg) throws IOException {
+        final ApiConnector api = _manager.getApiConnector();
+        api.delete(vnc);
+        syncLogMesg.append(cls.getCanonicalName() + "# VNC: " + vnc.getName() + " deleted\n");
+    }
+
+    /*
+     *  Domain Synchronization methods
+     */
+    public boolean syncDomain() throws Exception {
+        final ApiConnector api = _manager.getApiConnector();
+        try {
+            List<?> dbList = _domainDao.listAll();
+            @SuppressWarnings("unchecked")
+            List<?> vncList = (List<net.juniper.contrail.api.types.Domain>) api.list(net.juniper.contrail.api.types.Domain.class, null);
+            return _dbSync.syncGeneric(net.juniper.contrail.api.types.Domain.class, dbList, vncList);
+        } catch (Exception ex) {
+            s_logger.warn("syncDomain", ex);
+            throw ex;
+        }
+    }
+
+    @Override
+    public void createDomain(DomainVO db, StringBuffer syncLogMesg) throws IOException {
+        final ApiConnector api = _manager.getApiConnector();
+        net.juniper.contrail.api.types.Domain vnc = new net.juniper.contrail.api.types.Domain();
+        vnc.setName(db.getName());
+        vnc.setUuid(db.getUuid());
+        if (!api.create(vnc)) {
+            s_logger.error("Unable to create domain " + vnc.getName());
+            syncLogMesg.append("Error: Virtual domain# VNC : Unable to create domain: " + 
+                    vnc.getName() + "\n");
+            return;
+        }
+        syncLogMesg.append("Domain# VNC: " + vnc.getName() + " created \n");
+    }
+
+    public void deleteDomain(net.juniper.contrail.api.types.Domain vnc, StringBuffer syncLogMesg) throws IOException {
+        final ApiConnector api = _manager.getApiConnector();
+        api.read(vnc);
+        syncLogMesg.append("Domain# DB: none; VNC: " + vnc.getName() + "(" + 
+                vnc.getUuid() + "); action: delete\n");
+
+        /* delete all projects under this domain */
+        try {
+            deleteChildren(vnc.getProjects(), net.juniper.contrail.api.types.Project.class, syncLogMesg);
+        } catch (Exception ex) {
+            s_logger.warn("deleteDomain", ex);
+        }
+
+        api.delete(vnc);
+        syncLogMesg.append("Domain# VNC: " + vnc.getName() + " deleted\n");
+    }
+
+    public Integer compareDomain(DomainVO db, net.juniper.contrail.api.types.Domain vnc, StringBuffer syncLogMesg) {
+        if (_manager.isSystemRootDomain(db) && _manager.isSystemRootDomain(vnc)) {
+            return _manager.getDomainCanonicalName(db).compareTo(vnc.getName());
+        } else if (_manager.isSystemRootDomain(db)) {
+            return -1;
+        } else if (_manager.isSystemRootDomain(vnc)) {
+            return 1;
+        }
+        return db.getUuid().compareTo(vnc.getUuid());
+    }
+
+    public Boolean filterDomain(net.juniper.contrail.api.types.Domain vnc, StringBuffer syncLogMesg)  {
+        if (_manager.isSystemRootDomain(vnc)) {
+            return true;
+        }
+        return false;
+    }
+
+    public Boolean equalDomain(DomainVO db, net.juniper.contrail.api.types.Domain vnc, StringBuffer syncLogMesg) {
+        syncLogMesg.append("Domain# DB: " + db.getName() + "; VNC: " + 
+                vnc.getName() + "; action: equal, no action\n");
+        return true;
+    }
+
+    public Comparator<?> dbComparatorDomain() {
+        Comparator<?> comparator = new Comparator<DomainVO>() {
+            public int compare(DomainVO u1, DomainVO u2) {
+                if (_manager.isSystemRootDomain(u1)) {
+                    return -1;
+                }
+                if (_manager.isSystemRootDomain(u2)) {
+                    return 1;
+                }
+                return u1.getUuid().compareTo(u2.getUuid());
+            }
+        };
+        return comparator;
+    }
+
+    public Comparator<?> vncComparatorDomain() {
+        Comparator<?> comparator = new Comparator<net.juniper.contrail.api.types.Domain> () {
+            public int compare(net.juniper.contrail.api.types.Domain u1, net.juniper.contrail.api.types.Domain u2) {
+                if (_manager.isSystemRootDomain(u1)) {
+                    return -1;
+                }
+                if (_manager.isSystemRootDomain(u2)) {
+                    return 1;
+                }
+                return u1.getUuid().compareTo(u2.getUuid());
+            }
+        };
+        return comparator;
+    }
+
+    /*
+     *  Project Synchronization methods
+     */
+    @SuppressWarnings("unchecked")
+    public boolean syncProject() throws Exception {
+        final ApiConnector api = _manager.getApiConnector();
+        try {
+            List<?> dbList = _projectDao.listAll();
+            List<?> vncList = (List<net.juniper.contrail.api.types.Project>) api.list(net.juniper.contrail.api.types.Project.class, null);
+            return _dbSync.syncGeneric(net.juniper.contrail.api.types.Project.class, dbList, vncList);
+        } catch (Exception ex) {
+            s_logger.warn("syncProject", ex);
+            throw ex;
+        }
+    }
+
+    @Override
+    public void createProject(ProjectVO db, StringBuffer syncLogMesg) throws IOException {
+        final ApiConnector api = _manager.getApiConnector();
+        net.juniper.contrail.api.types.Project vnc = new net.juniper.contrail.api.types.Project();
+        vnc.setName(db.getName());
+        vnc.setUuid(db.getUuid());
+        if (!api.create(vnc)) {
+            s_logger.error("Unable to create project: " + vnc.getName());
+            syncLogMesg.append("Error: Virtual project# VNC : Unable to create project: " + 
+                    vnc.getName() + "\n");
+            return;
+        }
+        syncLogMesg.append("Project# VNC: " + vnc.getName() + " created \n");
+    }
+
+    public void deleteProject(net.juniper.contrail.api.types.Project vnc, StringBuffer syncLogMesg) throws IOException {
+        final ApiConnector api = _manager.getApiConnector();
+        api.read(vnc);
+        syncLogMesg.append("Project# DB: none; VNC: " + vnc.getName() + "(" + 
+                vnc.getUuid() + "); action: delete\n");
+
+        try {
+            deleteChildren(vnc.getVirtualNetworks(), VirtualNetwork.class, syncLogMesg);
+            deleteChildren(vnc.getSecurityGroups(), net.juniper.contrail.api.types.SecurityGroup.class, syncLogMesg);
+            deleteChildren(vnc.getNetworkIpams(), net.juniper.contrail.api.types.NetworkIpam.class, syncLogMesg);
+            deleteChildren(vnc.getNetworkPolicys(), net.juniper.contrail.api.types.NetworkPolicy.class, syncLogMesg);
+        } catch (Exception ex) {
+            s_logger.warn("deleteProject", ex);
+        }
+
+        api.delete(vnc);
+        syncLogMesg.append("Project# VNC: " + vnc.getName() + " deleted\n");
+    }
+
+    public Integer compareProject(ProjectVO db, net.juniper.contrail.api.types.Project vnc, StringBuffer syncLogMesg) {
+        if (_manager.isSystemDefaultProject(db) && _manager.isSystemDefaultProject(vnc)) {
+            return _manager.getProjectCanonicalName(db).compareTo(vnc.getName());
+        } else if (_manager.isSystemDefaultProject(db)) {
+            return -1;
+        } else if (_manager.isSystemDefaultProject(vnc)) {
+            return 1;
+        }
+        return db.getUuid().compareTo(vnc.getUuid());
+    }
+
+    public Boolean filterProject(net.juniper.contrail.api.types.Project vnc, StringBuffer syncLogMesg)  {
+        if (_manager.isSystemDefaultProject(vnc)) {
+            syncLogMesg.append("VNC: " + vnc.getName() + " filtered; action: don't delete\n");
+            return true;
+        }
+        return false;
+    }
+
+    public Boolean equalProject(ProjectVO db, net.juniper.contrail.api.types.Project vnc, StringBuffer syncLogMesg) {
+        syncLogMesg.append("Project# DB: " + db.getName() + "; VNC: " + 
+                vnc.getName() + "; action: equal, no action\n");
+        return true;
+    }
+
+    public Comparator<?> dbComparatorProject() {
+        Comparator<?> comparator = new Comparator<ProjectVO>() {
+            public int compare(ProjectVO u1, ProjectVO u2) {
+                if (_manager.isSystemDefaultProject(u1)) {
+                    return -1;
+                } 
+                if (_manager.isSystemDefaultProject(u2)) {
+                    return 1;
+                }
+                return u1.getUuid().compareTo(u2.getUuid());
+            }
+        };
+        return comparator;
+    }
+
+    public Comparator<?> vncComparatorProject() {
+        Comparator<?> comparator = new Comparator<net.juniper.contrail.api.types.Project> () {
+            public int compare(net.juniper.contrail.api.types.Project u1, net.juniper.contrail.api.types.Project u2) {
+                if (_manager.isSystemDefaultProject(u1)) {
+                    return -1;
+                }
+                if (_manager.isSystemDefaultProject(u2)) {
+                    return 1;
+                }
+                return u1.getUuid().compareTo(u2.getUuid());
+            }
+        };
+        return comparator;
+    }
+
+    /*
+     * Security Groups
+     */
+    
+    public void deleteSecurityGroup(net.juniper.contrail.api.types.SecurityGroup vnc, StringBuffer syncLogMesg) throws IOException {
+        final ApiConnector api = _manager.getApiConnector();
+        api.delete(vnc);
+        syncLogMesg.append("SecurityGroup# VNC: " + vnc.getName() + " deleted\n");
+    }
+    
+    /*
+     *  Virtual Network Synchronization methods
+     */
+    @SuppressWarnings({ "unchecked" })
+    public boolean syncVirtualNetwork() throws Exception {
+        final ApiConnector api = _manager.getApiConnector();
+        try {
+
+            List<TrafficType> types = new ArrayList<TrafficType>();
+            types.add(TrafficType.Public);
+            types.add(TrafficType.Guest);            
+            List<NetworkVO> dbNets = _manager.findJuniperManagedNetworks(types);
+
+            List<VirtualNetwork> vList = (List<VirtualNetwork>) api.list(VirtualNetwork.class, null);
+            List<VirtualNetwork> vncList = new ArrayList<VirtualNetwork>(); 
+            for (VirtualNetwork vn:vList) {
+                if (!_manager.isSystemDefaultNetwork(vn)) {
+                    vncList.add(vn);
+                }
+            }
+            s_logger.debug("sync VN - DB size: " + dbNets.size() + " VNC Size: " + vncList.size());
+            return _dbSync.syncGeneric(VirtualNetwork.class, dbNets, vncList);
+        } catch (Exception ex) {
+            s_logger.warn("sync virtual-networks", ex);
+            throw ex;
+        }
+    }
+
+    public Comparator<NetworkVO> dbComparatorVirtualNetwork() {
+        Comparator<NetworkVO> comparator = new Comparator<NetworkVO>() {
+            public int compare(NetworkVO u1, NetworkVO u2) {
+                if (_manager.isSystemDefaultNetwork(u1) && _manager.isSystemDefaultNetwork(u2)) {
+                    return _manager.getCanonicalName(u1).compareTo(_manager.getCanonicalName(u2));
+                } else if (_manager.isSystemDefaultNetwork(u1)) {
+                    return -1;
+                } else if (_manager.isSystemDefaultNetwork(u2)) {
+                    return 1;
+                }
+                return u1.getUuid().compareTo(u2.getUuid());
+            }
+        };
+        return comparator;
+    }
+
+    public Comparator<?> vncComparatorVirtualNetwork() {
+        Comparator<?> comparator = new Comparator<VirtualNetwork>() {
+            public int compare(VirtualNetwork u1, VirtualNetwork u2) {
+                if (_manager.isSystemDefaultNetwork(u1) && _manager.isSystemDefaultNetwork(u2)) {
+                    return u1.getName().compareTo(u2.getName());
+                } else if (_manager.isSystemDefaultNetwork(u1)) {
+                    return -1;
+                } else if (_manager.isSystemDefaultNetwork(u2)) {
+                    return 1;
+                }
+                return u1.getUuid().compareTo(u2.getUuid());
+            }
+        };
+        return comparator;
+    }
+
+    public void createVirtualNetwork(NetworkVO dbNet, StringBuffer syncLogMesg) throws IOException {
+        syncLogMesg.append("VN# DB: " + _manager.getCanonicalName(dbNet) +
+                "(" + dbNet.getUuid() + "); VNC: none;  action: create\n");
+        
+        if (_manager.getDatabase().lookupVirtualNetwork(dbNet.getUuid(), 
+                _manager.getCanonicalName(dbNet), dbNet.getTrafficType()) != null) {
+             s_logger.warn("VN model object is already present in DB: " + 
+                                   dbNet.getUuid() + ", name: " + dbNet.getName());      
+        }
+        
+        VirtualNetworkModel vnModel = new VirtualNetworkModel(dbNet, 
+                dbNet.getUuid(), _manager.getCanonicalName(dbNet), dbNet.getTrafficType());
+        vnModel.build(_manager.getModelController(), dbNet);
+
+        if (_rw_mode) {
+            try {
+                if (!vnModel.verify(_manager.getModelController())) {
+                    vnModel.update(_manager.getModelController());
+                }
+            } catch (InternalErrorException ex) {
+                s_logger.warn("create virtual-network", ex);
+                syncLogMesg.append("Error: VN# VNC : Unable to create network " + 
+                    dbNet.getName() + "\n");
+                return;
+            }
+            s_logger.debug("add model " + vnModel.getName());
+            _manager.getDatabase().getVirtualNetworks().add(vnModel);
+            syncLogMesg.append("VN# VNC: " + dbNet.getUuid() + ", " + vnModel.getName() + " created\n");
+        } else {
+            syncLogMesg.append("VN# VNC: " + vnModel.getName() + " created \n");
+        }
+    }
+
+
+    public void deleteVirtualNetwork(VirtualNetwork vnet, StringBuffer syncLogMesg) throws IOException {
+        final ApiConnector api = _manager.getApiConnector();
+        if (_manager.isSystemDefaultNetwork(vnet)) {
+            syncLogMesg.append("VN# System default virtual Network# VNC: " + vnet.getName() + " can not be deleted\n");
+            return;
+        }
+        api.read(vnet);
+
+        deleteInstanceIps(vnet.getInstanceIpBackRefs(), syncLogMesg);
+        
+        List<ObjectReference<ApiPropertyBase>> fipPools = vnet.getFloatingIpPools();
+        if (fipPools != null && !fipPools.isEmpty()) {
+            FloatingIpPool floatingIpPool = (FloatingIpPool) api.findById(FloatingIpPool.class, fipPools.get(0).getUuid());
+            if (floatingIpPool != null ) {
+                deleteFloatingIps(floatingIpPool.getFloatingIps(), syncLogMesg);
+            } 
+        }
+        
+        deleteVirtualMachineInterfaces(vnet.getVirtualMachineInterfaceBackRefs(), syncLogMesg);
+
+        syncLogMesg.append("VN# DB: none; VNC: " + vnet.getName() + "(" + vnet.getUuid() + "); action: delete\n");
+        api.delete(vnet);
+        syncLogMesg.append("VN# VNC: " + vnet.getName() + " deleted\n");
+    }
+
+    public Integer compareVirtualNetwork(NetworkVO dbn, VirtualNetwork vnet, StringBuffer syncLogMesg) {
+        if (_manager.isSystemDefaultNetwork(dbn) && _manager.isSystemDefaultNetwork(vnet)) {
+            return _manager.getCanonicalName(dbn).compareTo(vnet.getName());
+        } else if (_manager.isSystemDefaultNetwork(dbn)) {
+            return -1;
+        } else if (_manager.isSystemDefaultNetwork(vnet)) {
+            return 1;
+        }
+        return dbn.getUuid().compareTo(vnet.getUuid());
+    }
+
+    public Boolean filterVirtualNetwork(VirtualNetwork vnet, StringBuffer syncLogMesg)  {
+        if (_manager.isSystemDefaultNetwork(vnet)) {
+            syncLogMesg.append("VN# VNC: " + vnet.getName() + " filtered; action: don't delete\n");
+            return true;
+        }
+        return false;
+    }
+
+    public Boolean equalVirtualNetwork(NetworkVO dbn, VirtualNetwork vnet, StringBuffer syncLogMesg) {
+        syncLogMesg.append("VN# DB: " + _manager.getCanonicalName(dbn) + 
+                "; VNC: " + vnet.getName() + "; action: equal\n");
+        
+        VirtualNetworkModel current = _manager.getDatabase().lookupVirtualNetwork(vnet.getUuid(),
+                _manager.getCanonicalName(dbn), dbn.getTrafficType());
+
+        VirtualNetworkModel vnModel = new VirtualNetworkModel(dbn, vnet.getUuid(), 
+                _manager.getCanonicalName(dbn), dbn.getTrafficType());
+        vnModel.build(_manager.getModelController(), dbn);
+
+        if (_rw_mode) {
+            if (current != null) {
+                FloatingIpPoolModel fipPoolModel = current.getFipPoolModel();
+                if (fipPoolModel != null) {
+                   vnModel.setFipPoolModel(fipPoolModel);  
+                   fipPoolModel.addToVirtualNetwork(vnModel);
+                }
+                _manager.getDatabase().getVirtualNetworks().remove(current);
+            }
+            s_logger.debug("add model " + vnModel.getName());
+            _manager.getDatabase().getVirtualNetworks().add(vnModel);   
+            try {
+                if (!vnModel.verify(_manager.getModelController())) {
+                    vnModel.update(_manager.getModelController());
+                }
+            } catch (Exception ex) {
+                s_logger.warn("update virtual-network", ex);
+            }
+        } else {
+            //compare 
+            if (current != null && current.compare(_manager.getModelController(), vnModel) == false) {
+                syncLogMesg.append("VN# DB: " + _manager.getCanonicalName(dbn) + 
+                        "; VNC: " + vnet.getName() + "; attributes differ\n");
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /*
+     *  Virtual Machine Synchronization methods
+     */
+
+    public boolean syncVirtualMachine() {
+        final ApiConnector api = _manager.getApiConnector();
+        try {
+            List<VMInstanceVO> vmDbList = _vmInstanceDao.listAll(); 
+            @SuppressWarnings("unchecked")
+            List<VirtualMachine> vncVmList = (List<VirtualMachine>) api.list(VirtualMachine.class, null);
+            s_logger.debug("sync VM:  CS size: " + vmDbList.size() + " VNC size: " + vncVmList.size());
+            return _dbSync.syncGeneric(VirtualMachine.class, vmDbList, vncVmList);
+        } catch (Exception ex) {
+            s_logger.warn("sync virtual-machines", ex);
+        }
+        return false;
+    }
+
+    public Comparator<?> dbComparatorVirtualMachine() {
+        Comparator<?> comparator = new Comparator<VMInstanceVO>() {
+            public int compare(VMInstanceVO u1, VMInstanceVO u2) {
+                return u1.getUuid().compareTo(u2.getUuid());
+            }
+        };
+        return comparator;
+    }
+
+    public Comparator<?> vncComparatorVirtualMachine() {
+        Comparator<?> comparator = new Comparator<VirtualMachine> () {
+            public int compare(VirtualMachine u1, VirtualMachine u2) {
+                return u1.getUuid().compareTo(u2.getUuid());
+            }
+        };
+        return comparator;
+    }
+
+    public void createVirtualMachine(VMInstanceVO dbVm, StringBuffer syncLogMesg) throws IOException {
+        syncLogMesg.append("VM# DB: " + dbVm.getInstanceName() + "/" + dbVm.getUuid() + "; VNC: none; action: create\n");
+        VirtualMachineModel vmModel = new VirtualMachineModel(dbVm, dbVm.getUuid());
+        vmModel.build(_manager.getModelController(), dbVm);
+        buildNicResources(vmModel, dbVm, syncLogMesg);
+
+        if (_rw_mode) {
+            try {
+                vmModel.update(_manager.getModelController());
+            } catch (InternalErrorException ex) {
+                s_logger.warn("create virtual-machine", ex);
+                return;
+            }
+            _manager.getDatabase().getVirtualMachines().add(vmModel);
+            syncLogMesg.append("VM# VNC: " + dbVm.getUuid() + " created\n");
+        }
+    }
+
+    private void deleteVirtualMachineInterfaces(List<ObjectReference<ApiPropertyBase>> list, StringBuffer syncLogMesg) throws IOException {
+        if (list == null) {
+            return;
+        }
+        final ApiConnector api = _manager.getApiConnector();
+        for (ObjectReference<ApiPropertyBase> vmiRef: list) {
+            VirtualMachineInterface vmi = (VirtualMachineInterface) api.findById(VirtualMachineInterface.class, vmiRef.getUuid());
+            deleteInstanceIps(vmi.getInstanceIpBackRefs(), syncLogMesg);
+            deleteFloatingIps(vmi.getFloatingIpBackRefs(), syncLogMesg);
+            api.delete(VirtualMachineInterface.class, vmiRef.getUuid());
+            syncLogMesg.append("VNC vmi: " + vmi.getUuid() + " deleted\n");
+        }        
+    }
+
+    private void deleteInstanceIps(List<ObjectReference<ApiPropertyBase>> list, StringBuffer syncLogMesg) throws IOException {
+        if (list == null) {
+            return;
+        }
+        final ApiConnector api = _manager.getApiConnector();
+        for (ObjectReference<ApiPropertyBase> instIp: list) {
+            api.delete(InstanceIp.class, instIp.getUuid());
+            syncLogMesg.append("VNC instance ip: " + instIp.getUuid() + " deleted\n");
+        }
+        
+    }
+    
+    private void deleteFloatingIps(List<ObjectReference<ApiPropertyBase>> list, StringBuffer syncLogMesg) throws IOException {
+        if (list == null) {
+            return;
+        }
+        final ApiConnector api = _manager.getApiConnector();
+        for (ObjectReference<?> floatingIp: list) {
+            api.delete(FloatingIp.class, floatingIp.getUuid());
+            syncLogMesg.append("VNC instance ip: " + floatingIp.getUuid() + " deleted\n");
+        }
+    }
+
+    public void deleteVirtualMachine(VirtualMachine vncVm, StringBuffer syncLogMesg) {
+        final ApiConnector api = _manager.getApiConnector();
+        syncLogMesg.append("VM# DB:none; VNC: " + vncVm.getName() + "/" + vncVm.getUuid() + "; action: delete\n");
+        if (!_rw_mode) {
+            return;
+        }
+        try {
+            if (!api.read(vncVm)) {
+                 return;
+            }
+            deleteVirtualMachineInterfaces(vncVm.getVirtualMachineInterfaces(), syncLogMesg);
+            api.delete(VirtualMachine.class, vncVm.getUuid());
+        } catch (IOException ex) {
+            s_logger.warn("delete virtual-machine", ex);
+            return;
+        }
+        syncLogMesg.append("VM# VNC: " + vncVm.getName() + " deleted\n");
+    }
+
+    public Integer compareVirtualMachine(VMInstanceVO dbVm, VirtualMachine vncVm, StringBuffer syncLogMesg) {
+        String dbVmId = dbVm.getUuid();
+        String vncVmId = vncVm.getUuid();
+        return dbVmId.compareTo(vncVmId);
+    }    
+
+    public boolean filterVirtualMachine(VirtualMachine vncVm, StringBuffer syncLogMesg) {
+        return false;
+    }
+
+    private void buildNicResources(VirtualMachineModel vmModel, VMInstanceVO dbVm, StringBuffer syncLogMsg)
+            throws IOException {
+        List<NicVO> nics = _nicDao.listByVmId(dbVm.getId());
+        for (NicVO nic : nics) {
+            VMInterfaceModel vmiModel = vmModel.getVMInterface(nic.getUuid());
+            if (vmiModel == null) {
+                vmiModel = new VMInterfaceModel(nic.getUuid());
+                NetworkVO network = _networksDao.findById(nic.getNetworkId());
+                VirtualNetworkModel vnModel = _manager.getDatabase().lookupVirtualNetwork(
+                        network.getUuid(), _manager.getCanonicalName(network), network.getTrafficType());
+                if (vnModel == null)  {
+                    s_logger.warn("Unable to locate virtual-network for network id " + network.getId());
+                    continue;
+                }
+                vmiModel.addToVirtualMachine(vmModel);
+                vmiModel.addToVirtualNetwork(vnModel);
+            }
+            vmiModel.build(_manager.getModelController(), dbVm, nic);            
+        }        
+    }
+
+    public Boolean equalVirtualMachine(VMInstanceVO dbVm, VirtualMachine vncVm, StringBuffer syncLogMsg) {
+
+        syncLogMsg.append("VM# DB: " + dbVm.getInstanceName() + "/" + dbVm.getUuid() + 
+                "; VNC: " + vncVm.getUuid() + "; action: equal; DB VM State: " + dbVm.getState() + "\n");
+
+        VirtualMachineModel vmModel = new VirtualMachineModel(dbVm, dbVm.getUuid());
+        vmModel.build(_manager.getModelController(), dbVm);
+
+        if (vmModel.isActive()) {
+            try {
+                buildNicResources(vmModel, dbVm, syncLogMsg);
+            } catch (IOException ex) {
+                s_logger.warn("build nic information for " + dbVm.getInstanceName(), ex);
+            }
+        }
+
+        VirtualMachineModel current = _manager.getDatabase().lookupVirtualMachine(vncVm.getUuid());
+        if (_rw_mode) {
+            if (current != null) {
+                _manager.getDatabase().getVirtualMachines().remove(current);
+            }
+            _manager.getDatabase().getVirtualMachines().add(vmModel);   
+            try {
+                vmModel.update(_manager.getModelController());
+            } catch (Exception ex) {
+                s_logger.warn("update virtual-machine", ex);
+            }
+        } else {
+            //compare 
+            if (current != null && current.compare(_manager.getModelController(), vmModel) == false) {
+                syncLogMsg.append("VM # DB: " + dbVm.getInstanceName() + 
+                        "; VNC: " + vncVm.getName() + "; attributes differ\n");
+                return false;
+            }
+        }
+        return true;
+    }
+    
+     
+    public boolean syncFloatingIp() throws Exception {
+        
+        List<IPAddressVO> ipList = _manager.findJuniperManagedPublicIps();
+        List<FloatingIp> vncList = _manager.getFloatingIps();  
+        if (ipList == null) {
+            ipList = new ArrayList<IPAddressVO>();
+        }        
+        if (vncList == null) {
+            vncList = new ArrayList<FloatingIp>();
+        }
+        
+        boolean status = false;
+        try {
+            status =  _dbSync.syncGeneric(FloatingIp.class, ipList, vncList);
+        } catch (Exception ex) {
+            s_logger.warn("sync floating-ips", ex);
+            throw ex;
+        }        
+        return status;
+    }
+    
+    public Comparator<?> dbComparatorFloatingIp() {
+        Comparator<?> comparator = new Comparator<IpAddress>() {
+            public int compare(IpAddress u1, IpAddress u2) {
+                return u1.getUuid().compareTo(u2.getUuid());
+            }
+        };
+        return comparator;
+    }
+
+    public Comparator<?> vncComparatorFloatingIp() {
+        Comparator<?> comparator = new Comparator<FloatingIp> () {
+            public int compare(FloatingIp u1, FloatingIp u2) {
+                return u1.getUuid().compareTo(u2.getUuid());
+            }
+        };
+        return comparator;
+    }
+    
+    public Integer compareFloatingIp(IpAddress db, FloatingIp vnc, StringBuffer syncLogMesg) {
+        String dbId = db.getUuid();
+        String vncId = vnc.getUuid();
+        return dbId.compareTo(vncId);
+    } 
+    
+    public void createFloatingIp(IPAddressVO dbIp, StringBuffer syncLogMesg) throws Exception {
+
+        if (dbIp.getState() == IpAddress.State.Releasing) {
+            /* Don't need to push releasing ip */
+            syncLogMesg.append("fip# DB: " + dbIp.getUuid() + ", state releasing, don't create in vnc\n");
+            return;
+        }
+        syncLogMesg.append("fip# DB: " + dbIp.getAddress().addr() + "; VNC: none; action: create\n");
+        if (!_manager.createFloatingIp(PublicIp.createFromAddrAndVlan(dbIp, _vlanDao.findById(dbIp.getVlanId())))) {
+            syncLogMesg.append("fip# VNC: " + dbIp.getAddress().addr() + " unable to create\n");
+            return ;
+        }
+        syncLogMesg.append("fip# VNC: " + dbIp.getUuid() + " created\n");
+    }
+    
+    public void deleteFloatingIp(FloatingIp vnc, StringBuffer syncLogMesg) throws IOException {
+        final ApiConnector api = _manager.getApiConnector();
+        syncLogMesg.append("fip# DB: none; VNC: " + vnc.getAddress() + "(" + 
+                vnc.getUuid() + "); action: delete\n");
+        api.delete(vnc);
+        syncLogMesg.append("fip# VNC: " + vnc.getUuid() + " deleted\n");
+    }
+    
+    public Boolean equalFloatingIp(IPAddressVO db, FloatingIp vnc, StringBuffer syncLogMsg) 
+            throws IOException {
+
+        syncLogMsg.append("fip# DB: " + db.getAddress().addr() + 
+                "; VNC: " + vnc.getAddress() + "; action: equal" + "\n");
+
+        VirtualNetworkModel vnModel = _manager.lookupPublicNetworkModel();
+        assert vnModel != null : "public network vn model is null";
+
+        FloatingIpPoolModel fipPoolModel = vnModel.getFipPoolModel();
+        if (fipPoolModel == null) {
+            fipPoolModel = new FloatingIpPoolModel();
+            fipPoolModel.addToVirtualNetwork(vnModel);
+            fipPoolModel.build(_manager.getModelController());
+            try {
+                fipPoolModel.update(_manager.getModelController());
+                vnModel.setFipPoolModel(fipPoolModel);
+            } catch (Exception ex) {
+                s_logger.warn("floating-ip-pool create: ", ex);
+                return false;
+            }
+        }
+
+        FloatingIpModel current = fipPoolModel.getFloatingIpModel(db.getUuid());
+        if (current == null) {
+            s_logger.debug("add model " + db.getAddress().addr());
+            FloatingIpModel fipModel = new FloatingIpModel(db.getUuid());
+            fipModel.addToFloatingIpPool(fipPoolModel);
+            fipModel.build(_manager.getModelController(),  
+                    PublicIp.createFromAddrAndVlan(db, _vlanDao.findById(db.getVlanId())));
+            try {
+                fipModel.update(_manager.getModelController());
+            } catch (Exception ex) {
+                s_logger.warn("floating-ip create: ", ex);
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    public Integer compareServiceInstance(ServiceInstanceModel siModel, ServiceInstance siObj, StringBuffer logMsg) {
+        String fqn = StringUtils.join(siObj.getQualifiedName(), ':');
+        return siModel.getQualifiedName().compareTo(fqn);
+    }
+    
+    /**
+     * createServiceInstance
+     * 
+     * This method should never be invoked since the model objects have been installed already when sync is called.
+     * @param siModel
+     * @param logMsg
+     */
+    public void createServiceInstance(ServiceInstanceModel siModel, StringBuffer logMsg) {
+        assert false;
+    }
+    
+    public void deleteServiceInstance(ServiceInstance siObj, StringBuffer logMsg) {
+        final ApiConnector api = _manager.getApiConnector();
+        s_logger.debug("delete " + siObj.getQualifiedName());
+        if (!_rw_mode) {
+            return;
+        }
+        try {
+            api.delete(siObj);
+        } catch (IOException ex) {
+            s_logger.warn("service-instance delete", ex);
+        }
+    }
+
+    /**
+     * equalServiceInstance
+     * 
+     * @param siModel
+     * @param siObj
+     * @param logMsg
+     */
+    public void equalServiceInstance(ServiceInstanceModel siModel, ServiceInstance siObj, StringBuffer logMsg) {
+        s_logger.debug("equal " + siModel.getQualifiedName());
+    }
+    
+    static class ServiceInstanceComparator implements Comparator<ServiceInstance> {
+        @Override
+        public int compare(ServiceInstance obj1, ServiceInstance obj2) {
+            String name1 = StringUtils.join(obj1.getQualifiedName(), ':');
+            String name2 = StringUtils.join(obj2.getQualifiedName(), ':');
+            return name1.compareTo(name2);
+        }
+        
+    }
+    /**
+     * The service-instance model list is build as a result of synchronizing virtual-machines.
+     * @return
+     */
+    public boolean syncServiceInstance() {
+        final ApiConnector api = _manager.getApiConnector();
+        boolean inSync;
+        try {
+            @SuppressWarnings("unchecked")
+            List<ServiceInstance> siList = (List<ServiceInstance>) api.list(ServiceInstance.class, null);
+            java.util.Collections.sort(siList, new ServiceInstanceComparator());
+            DBSyncGeneric.SyncStats stats = new DBSyncGeneric.SyncStats();
+            _dbSync.syncCollections(ServiceInstance.class, _manager.getDatabase().getServiceInstances(), siList,
+                    _rw_mode, stats);
+            inSync = stats.create == 0 && stats.delete == 0;
+        } catch (Exception ex) {
+            s_logger.warn("synchronize service-instances", ex);
+            return false;
+        }
+        return inSync;
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6b5fab2f/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServerEventHandler.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServerEventHandler.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServerEventHandler.java
new file mode 100644
index 0000000..7fb94d8
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServerEventHandler.java
@@ -0,0 +1,22 @@
+// 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;
+
+public interface ServerEventHandler {
+    public void subscribe();
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6b5fab2f/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServerEventHandlerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServerEventHandlerImpl.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServerEventHandlerImpl.java
new file mode 100644
index 0000000..455e601
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServerEventHandlerImpl.java
@@ -0,0 +1,251 @@
+// 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 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;
+
+import org.apache.cloudstack.framework.messagebus.MessageBus;
+import org.apache.cloudstack.framework.messagebus.MessageDispatcher;
+import org.apache.cloudstack.framework.messagebus.MessageHandler;
+
+/*
+ * 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();
+    }
+
+    protected void finalize () {
+
+    }
+    
+    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);
+        
+        if (subject.equals("VLAN.IP.RANGE.CREATE")) {
+            _manager.createPublicNetworks();
+            return;
+        } else if (subject.equals("VLAN.IP.RANGE.DELETE")) {
+            // TODO
+            return;
+        }
+
+        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));
+        _messageBus.subscribe(EventTypes.EVENT_VLAN_IP_RANGE_CREATE, MessageDispatcher.getDispatcher(this));
+        _messageBus.subscribe(EventTypes.EVENT_VLAN_IP_RANGE_DELETE, MessageDispatcher.getDispatcher(this));
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6b5fab2f/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServiceManager.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServiceManager.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServiceManager.java
new file mode 100644
index 0000000..dcc643c
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServiceManager.java
@@ -0,0 +1,40 @@
+// 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 org.apache.cloudstack.network.contrail.api.response.ServiceInstanceResponse;
+
+import com.cloud.dc.DataCenter;
+import com.cloud.network.Network;
+import com.cloud.offering.ServiceOffering;
+import com.cloud.template.VirtualMachineTemplate;
+import com.cloud.user.Account;
+
+public interface ServiceManager {
+    /**
+     * Create a virtual machine that executes a network service appliance (e.g. vSRX)
+     * @param left Left or inside network (e.g. project network).
+     * @param right Right or outside network (e.g. public network).
+     * @return
+     */
+    public ServiceVirtualMachine createServiceInstance(DataCenter zone, Account owner, VirtualMachineTemplate template,
+            ServiceOffering serviceOffering, String name, Network left, Network right);
+
+    public void startServiceInstance(long instanceId);
+    public ServiceInstanceResponse createServiceInstanceResponse(long instanceId);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6b5fab2f/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServiceManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServiceManagerImpl.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServiceManagerImpl.java
new file mode 100644
index 0000000..47fc99e
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServiceManagerImpl.java
@@ -0,0 +1,249 @@
+// 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.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.api.ApiDBUtils;
+import com.cloud.dc.DataCenter;
+import com.cloud.deploy.DataCenterDeployment;
+import com.cloud.event.ActionEvent;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.network.Network;
+import com.cloud.network.NetworkModel;
+import com.cloud.network.Networks.TrafficType;
+import com.cloud.network.dao.NetworkVO;
+import com.cloud.offering.ServiceOffering;
+import com.cloud.projects.Project;
+import com.cloud.service.ServiceOfferingVO;
+import com.cloud.storage.VMTemplateVO;
+import com.cloud.template.VirtualMachineTemplate;
+import com.cloud.user.Account;
+import com.cloud.user.AccountService;
+import com.cloud.user.User;
+import com.cloud.user.UserVO;
+import com.cloud.user.dao.UserDao;
+import com.cloud.utils.Pair;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.UserVmVO;
+import com.cloud.vm.VirtualMachineManager;
+import com.cloud.vm.VirtualMachineName;
+import com.cloud.vm.dao.UserVmDao;
+import com.google.gson.Gson;
+
+import org.apache.cloudstack.context.CallContext;
+import org.apache.cloudstack.network.contrail.api.response.ServiceInstanceResponse;
+import org.apache.cloudstack.network.contrail.model.ServiceInstanceModel;
+import org.apache.cloudstack.network.contrail.model.VirtualMachineModel;
+
+import net.juniper.contrail.api.ApiConnector;
+import net.juniper.contrail.api.types.ServiceInstance;
+import net.juniper.contrail.api.types.VirtualNetwork;
+
+@Local(value =  {ServiceManager.class})
+public class ServiceManagerImpl implements ServiceManager {
+    private static final Logger s_logger = Logger.getLogger(ServiceManager.class);
+
+    @Inject UserDao  _userDao;
+    @Inject UserVmDao _vmDao;
+    @Inject VirtualMachineManager _vmManager;
+    @Inject NetworkModel _networkModel;
+    @Inject AccountService _accountService;
+    @Inject ContrailManager _manager;
+    
+    /**
+     * In the case of service instance the master object is in the contrail API server. This object stores the
+     * service instance parameters in the database.
+     * 
+     * @param owner     Used to determine the project.
+     * @param name      Service instance name (user specified).
+     * @param template  Image to execute.
+     * @param serviceOffering 
+     * @param left      Inside network.
+     * @param right     Outside network.
+     * @return
+     */
+        
+
+    /**
+     * create a new ServiceVM object.
+     * @return
+     */
+    @ActionEvent(eventType = EventTypes.EVENT_VM_CREATE, eventDescription="createServiceInstance", create = true)
+    private ServiceVirtualMachine createServiceVM(DataCenter zone, Account owner, VirtualMachineTemplate template,
+            ServiceOffering serviceOffering, String name, ServiceInstance siObj, Network left, Network right) {
+        long id = _vmDao.getNextInSequence(Long.class, "id");
+        
+        DataCenterDeployment plan = new DataCenterDeployment(zone.getId());
+        
+        LinkedHashMap<NetworkVO, NicProfile> networks = new LinkedHashMap<NetworkVO, NicProfile>();
+        NetworkVO linklocal = (NetworkVO) _networkModel.getSystemNetworkByZoneAndTrafficType(zone.getId(),
+                TrafficType.Management);
+        networks.put(linklocal, null);
+        networks.put((NetworkVO) left, null);
+        networks.put((NetworkVO) right, null);
+        
+        String instanceName = VirtualMachineName.getVmName(id, owner.getId(), "SRV");
+        ServiceVirtualMachine svm = new ServiceVirtualMachine(id, instanceName, name, template.getId(),
+                serviceOffering.getId(), template.getHypervisorType(), template.getGuestOSId(), zone.getId(), owner.getDomainId(),
+                owner.getAccountId(), false);
+  
+        // database synchronization code must be able to distinguish service instance VMs.
+        Map<String, String> kvmap = new HashMap<String, String>();
+        kvmap.put("service-instance", siObj.getUuid());
+        Gson json = new Gson();
+        String userData = json.toJson(kvmap);
+        svm.setUserData(userData);
+
+        try {
+            _vmManager.allocate(instanceName, template, serviceOffering, networks,
+                                plan, template.getHypervisorType());
+        } catch (InsufficientCapacityException ex) {
+            throw new CloudRuntimeException("Insufficient capacity", ex);
+        }
+        CallContext.current().setEventDetails("Vm Id: " + svm.getId());
+        return svm;
+    }
+    
+    @Override
+    public ServiceVirtualMachine createServiceInstance(DataCenter zone, Account owner, VirtualMachineTemplate template,
+            ServiceOffering serviceOffering, String name, Network left, Network right) {
+        s_logger.debug("createServiceInstance by " + owner.getAccountName());
+        // TODO: permission model.
+        // service instances need to be able to access the public network.
+        if (left.getTrafficType() == TrafficType.Guest) {
+            _networkModel.checkNetworkPermissions(owner, left);
+        }
+        if (right.getTrafficType() == TrafficType.Guest) {
+            _networkModel.checkNetworkPermissions(owner, right);
+        }
+        
+        final ApiConnector api = _manager.getApiConnector();
+        final VirtualNetwork netLeft;
+        try {
+            netLeft = (VirtualNetwork) api.findById(VirtualNetwork.class, left.getUuid());
+        } catch (IOException ex) {
+            throw new CloudRuntimeException("Unable to read virtual-network object", ex);
+        }
+        final VirtualNetwork netRight;
+        try {
+            netRight = (VirtualNetwork) api.findById(VirtualNetwork.class, right.getUuid());
+        } catch (IOException ex) {
+            throw new CloudRuntimeException("Unable to read virtual-network object", ex);
+        }
+
+        net.juniper.contrail.api.types.Project project;
+        try {
+            project = _manager.getVncProject(owner.getDomainId(), owner.getAccountId());
+        } catch (IOException ex) {
+            s_logger.warn("read project", ex);
+            throw new CloudRuntimeException(ex);
+        }
+        
+        try {
+            final String srvid = api.findByName(ServiceInstance.class, project, name);
+            if (srvid != null) {
+                throw new InvalidParameterValueException("service-instance " + name + " already exists uuid=" + srvid);
+            }
+        } catch (IOException ex) {
+            s_logger.warn("service-instance lookup", ex);
+            throw new CloudRuntimeException(ex);
+        }
+        
+        // 1. Create service-instance.
+        ServiceInstanceModel serviceModel = new ServiceInstanceModel(project, name, template, serviceOffering,
+                netLeft, netRight);
+
+        try {
+            serviceModel.update(_manager.getModelController());
+        } catch (Exception ex) {
+            s_logger.warn("service-instance update", ex);
+            throw new CloudRuntimeException(ex);
+        }
+        
+        s_logger.debug("service-instance object created");
+        
+        ServiceInstance siObj;
+        try {
+            _manager.getDatabase().getServiceInstances().add(serviceModel);
+            siObj = serviceModel.getServiceInstance();
+        } catch (Exception ex){
+            s_logger.warn("DB add", ex);
+            throw new CloudRuntimeException(ex);
+        }
+        
+        // 2. Create one virtual-machine.
+        String svmName = name.replace(" ", "_") + "-1";
+        ServiceVirtualMachine svm = createServiceVM(zone, owner, template, serviceOffering, svmName, siObj, left, right);
+ 
+        s_logger.debug("created VMInstance " + svm.getUuid());
+
+        // 3. Create the virtual-machine model and push the update.
+        VirtualMachineModel instanceModel = new VirtualMachineModel(svm, svm.getUuid());
+        _manager.getDatabase().getVirtualMachines().add(instanceModel);
+        try {
+            instanceModel.setServiceInstance(_manager.getModelController(), svm, serviceModel);
+            instanceModel.update(_manager.getModelController());
+        } catch (Exception ex) {
+            s_logger.warn("service virtual-machine update", ex);
+            throw new CloudRuntimeException(ex);
+        }
+        
+        return svm;
+    }
+
+    @Override
+    public void startServiceInstance(long instanceId) {
+        s_logger.debug("start service instance " + instanceId);
+
+        UserVmVO vm = _vmDao.findById(instanceId);
+        _vmManager.start(vm.getUuid(), null);
+    }
+
+    @Override
+    public ServiceInstanceResponse createServiceInstanceResponse(long instanceId) {
+        s_logger.debug("ServiceInstance response for id: " + instanceId);
+        UserVmVO vm = _vmDao.findById(instanceId);
+        ServiceInstanceResponse response = new ServiceInstanceResponse();
+        response.setId(vm.getUuid());
+        Account owner = _accountService.getAccount(vm.getAccountId());
+        if (owner.getType() == Account.ACCOUNT_TYPE_PROJECT) {
+            Project project = ApiDBUtils.findProjectByProjectAccountIdIncludingRemoved(owner.getAccountId());
+            response.setProjectId(project.getUuid());
+            response.setProjectName(project.getName());
+        } else {
+            response.setAccountName(owner.getAccountName());
+        }
+        return response;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6b5fab2f/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServiceVirtualMachine.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServiceVirtualMachine.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServiceVirtualMachine.java
new file mode 100644
index 0000000..7418792
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/management/ServiceVirtualMachine.java
@@ -0,0 +1,30 @@
+// 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 com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.vm.UserVmVO;
+
+public class ServiceVirtualMachine extends UserVmVO {
+    public ServiceVirtualMachine(long id, String instanceName, String name, long templateId, long serviceOfferingId,
+            HypervisorType hypervisorType, long guestOSId, long dataCenterId, long domainId, long accountId,
+            boolean haEnabled) {
+        super(id, instanceName, name, templateId, hypervisorType, guestOSId, false, false, domainId, accountId,
+              serviceOfferingId, null, name, null);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6b5fab2f/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/FloatingIpModel.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/FloatingIpModel.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/FloatingIpModel.java
new file mode 100644
index 0000000..a640b1e
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/FloatingIpModel.java
@@ -0,0 +1,213 @@
+// 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.model;
+
+import java.io.IOException;
+
+import org.apache.cloudstack.network.contrail.management.ContrailManager;
+import org.apache.log4j.Logger;
+
+import com.cloud.exception.InternalErrorException;
+import com.cloud.network.PublicIpAddress;
+import com.cloud.network.dao.IPAddressVO;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.NicVO;
+import com.cloud.vm.VMInstanceVO;
+
+import net.juniper.contrail.api.types.FloatingIp;
+import net.juniper.contrail.api.ApiConnector;
+
+public class FloatingIpModel extends ModelObjectBase {
+    private static final Logger s_logger = Logger.getLogger(FloatingIpModel.class);
+
+    private String _uuid;
+    private long _id;
+    private String _name;
+    private String _addr;
+    private boolean _initialized;
+
+    /*
+     * cached API server objects
+     */
+    private FloatingIp _fip;
+    private FloatingIpPoolModel _fipPoolModel;
+
+    public FloatingIpModel(String uuid) {
+       _uuid = uuid;
+    }
+
+    public void addToFloatingIpPool(FloatingIpPoolModel fipPoolModel) {
+        _fipPoolModel = fipPoolModel;
+        if (fipPoolModel != null) {
+            fipPoolModel.addSuccessor(this);
+        }
+    }
+
+    public void addToVMInterface(VMInterfaceModel vmiModel) {
+        if (vmiModel != null) {
+            vmiModel.addSuccessor(this);
+        }
+    }
+
+    /*
+     * Resynchronize internal state from the cloudstack DB object.
+     */
+    public void build(ModelController controller, PublicIpAddress ip) {
+        setProperties(controller, ip);
+    }
+
+    @Override
+    public int compareTo(ModelObject o) {
+        FloatingIpModel other;
+        try {
+            other = (FloatingIpModel) o;
+        } catch (ClassCastException ex) {
+            String clsname = o.getClass().getName();
+            return FloatingIpModel.class.getName().compareTo(clsname);
+        }
+
+        return _uuid.compareTo(other._uuid);
+    }
+
+    @Override
+    public void delete(ModelController controller) throws IOException {
+        ApiConnector api = controller.getApiAccessor();
+        for (ModelObject successor: successors()) {
+            successor.delete(controller);
+        }
+
+        try {
+            api.delete(FloatingIp.class, _uuid);
+        } catch (IOException ex) {
+            s_logger.warn("floating ip delete", ex);
+        }
+    }
+
+    @Override
+    public void destroy(ModelController controller) throws IOException {
+        delete(controller);
+
+        for (ModelObject successor: successors()) {
+            successor.destroy(controller);
+        }
+        clearSuccessors();
+    }
+
+    public String getName() {
+        return _name;
+    }
+
+    public String getUuid() {
+        return _uuid;
+    }
+
+
+    public FloatingIp getFloatingIp() {
+        return _fip;
+    }
+
+    /**
+     * Initialize the object properties based on the DB object.
+     * Common code between plugin calls and DBSync.
+     */
+    public void setProperties(ModelController controller, PublicIpAddress ip) {
+        _uuid = ip.getUuid();
+        _name = Long.toString(ip.getId());
+        _addr = ip.getAddress().addr();
+        _id = ip.getId();
+        assert _fipPoolModel != null : "floating ip uuid is not set";
+        _initialized = true;
+    }
+
+    @Override
+    public void update(ModelController controller) throws InternalErrorException, IOException {
+
+        assert _initialized;
+
+        ApiConnector api = controller.getApiAccessor();
+        ContrailManager manager = controller.getManager();
+        FloatingIp fip = _fip;
+
+        if (_fip == null) {
+            _fip = fip = (FloatingIp) controller.getApiAccessor().findById(FloatingIp.class, _uuid);
+            if (fip == null) {
+                fip = new FloatingIp();
+                fip.setUuid(_uuid);
+                fip.setAddress(_addr);
+                fip.setName(_name);
+                fip.setParent(_fipPoolModel.getFloatingIpPool());
+            }
+        }
+
+        IPAddressVO ipAddrVO = controller.getIPAddressDao().findById(_id);
+        assert ipAddrVO != null : "can not find address object in db";
+        Long vmId = ipAddrVO.getAssociatedWithVmId();
+        Long networkId = ipAddrVO.getAssociatedWithNetworkId();
+        if (vmId == null || networkId == null) {
+            s_logger.debug("Floating ip is not yet associated to either vm or network");
+            return;
+        }
+        NicVO nic = controller.getNicDao().findByNtwkIdAndInstanceId(networkId, vmId);
+        assert nic != null : "can not find nic for the given network and vm in db";
+
+        VMInstanceVO vm = controller.getVmDao().findById(vmId);
+        assert vm != null : "can not find vm in db";
+
+        VirtualMachineModel vmModel = manager.getDatabase().lookupVirtualMachine(vm.getUuid());
+        assert vmModel != null : "can not find vm model";
+
+        VMInterfaceModel vmiModel = vmModel.getVMInterface(nic.getUuid());
+        assert vmiModel != null && vmiModel.getVMInterface() != null : "can not find virtual machine interface";
+
+        fip.setVirtualMachineInterface(vmiModel.getVMInterface());
+
+        if (_fip == null) {
+            try {
+                api.create(fip);
+            } catch (Exception ex) {
+                s_logger.debug("floating ip create", ex);
+                throw new CloudRuntimeException("Failed to create floating ip", ex);
+            }
+            _fip = fip;
+        } else {
+            try {
+                api.update(fip);
+            } catch (IOException ex) {
+                s_logger.warn("floating ip update", ex);
+                throw new CloudRuntimeException("Unable to update floating ip object", ex);
+            }            
+        }
+
+        addToVMInterface(vmiModel);
+
+        for (ModelObject successor: successors()) {
+            successor.update(controller);
+        }
+    }
+
+    @Override
+    public boolean verify(ModelController controller) {
+        assert _initialized : "initialized is false";
+        return false;
+    }
+
+    @Override
+    public boolean compare(ModelController controller, ModelObject o) {
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6b5fab2f/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/FloatingIpPoolModel.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/FloatingIpPoolModel.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/FloatingIpPoolModel.java
new file mode 100644
index 0000000..1205c87
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/FloatingIpPoolModel.java
@@ -0,0 +1,170 @@
+// 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.model;
+
+import java.io.IOException;
+import java.util.TreeSet;
+
+import org.apache.cloudstack.network.contrail.management.ContrailManager;
+import org.apache.log4j.Logger;
+
+import com.cloud.exception.InternalErrorException;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+import net.juniper.contrail.api.types.FloatingIpPool;
+import net.juniper.contrail.api.ApiConnector;
+
+public class FloatingIpPoolModel extends ModelObjectBase {
+    private static final Logger s_logger = Logger.getLogger(FloatingIpPoolModel.class);
+
+    private String _name;
+
+    /*
+     * cached API server objects
+     */
+    private FloatingIpPool _fipPool;
+    private VirtualNetworkModel _vnModel;
+
+    public FloatingIpPoolModel() {
+
+    }
+
+    public void addToVirtualNetwork(VirtualNetworkModel vnModel) {
+        _vnModel = vnModel;
+        if (vnModel != null) {
+            vnModel.addSuccessor(this);
+        }
+    }
+
+    public FloatingIpModel getFloatingIpModel(String uuid) {
+        TreeSet<ModelObject> tree = successors();
+        FloatingIpModel fipKey = new FloatingIpModel(uuid);
+        FloatingIpModel current = (FloatingIpModel) tree.ceiling(fipKey);
+        if (current != null && current.getUuid().equals(uuid)) {
+            return current;
+        }
+        return null;
+    }
+
+    /*
+     * Resynchronize internal state from the cloudstack DB object.
+     */
+    public void build(ModelController controller) {
+        setProperties(controller);
+    }
+
+    @Override
+    public int compareTo(ModelObject o) {
+        /* there can be only one instance */
+        return 0;
+    }
+
+    @Override
+    public void delete(ModelController controller) throws IOException {
+        ApiConnector api = controller.getApiAccessor();
+        for (ModelObject successor: successors()) {
+            successor.delete(controller);
+        }
+        try {
+            if (_fipPool != null) {
+                api.delete(_fipPool);
+            }
+            _fipPool = null;
+        } catch (IOException ex) {
+            s_logger.warn("floating ip pool delete", ex);
+        }
+    }
+
+    @Override
+    public void destroy(ModelController controller) throws IOException {
+        delete(controller);
+        for (ModelObject successor: successors()) {
+            successor.destroy(controller);
+        }
+        clearSuccessors();
+    }
+
+    public String getName() {
+        return _name;
+    }
+
+    public FloatingIpPool getFloatingIpPool() {
+        return _fipPool;
+    }
+
+    /**
+     * Initialize the object properties based on the DB object.
+     * Common code between plugin calls and DBSync.
+     */
+    public void setProperties(ModelController controller) {
+        _name = "PublicIpPool";
+        assert _vnModel != null : "vn nodel is not initialized";
+    }
+
+    @Override
+    public void update(ModelController controller) throws InternalErrorException, IOException {
+
+        assert _vnModel != null : "vn model is not set";
+
+        ApiConnector api = controller.getApiAccessor();
+        ContrailManager manager = controller.getManager();
+        FloatingIpPool fipPool = _fipPool;
+
+        if (fipPool == null) {
+            String fipPoolName = manager.getDefaultPublicNetworkFQN() + ":PublicIpPool";
+            _fipPool = fipPool = (FloatingIpPool) controller.getApiAccessor().findByFQN(FloatingIpPool.class, fipPoolName);
+            if (fipPool == null) {
+                fipPool = new FloatingIpPool();
+                fipPool.setName(_name);
+                fipPool.setParent(_vnModel.getVirtualNetwork());
+            }
+        }
+
+        if (_fipPool == null) {
+            try {
+                api.create(fipPool);
+            } catch (Exception ex) {
+                s_logger.debug("floating ip pool create", ex);
+                throw new CloudRuntimeException("Failed to create floating ip pool", ex);
+            }
+            _fipPool = fipPool;
+        } else {
+            try {
+                api.update(fipPool);
+            } catch (IOException ex) {
+                s_logger.warn("floating ip pool update", ex);
+                throw new CloudRuntimeException("Unable to update floating ip ppol object", ex);
+            }            
+        }
+
+        for (ModelObject successor: successors()) {
+            successor.update(controller);
+        }
+    }
+
+    @Override
+    public boolean verify(ModelController controller) {
+        assert _vnModel != null : "vn model is not set";
+        return false;
+    }
+
+    @Override
+    public boolean compare(ModelController controller, ModelObject o) {
+        return true;
+    }
+}