You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ch...@apache.org on 2013/10/08 15:38:36 UTC
[4/6] Contrail network virtualization plugin.
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7099686b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServerDBSyncImpl.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServerDBSyncImpl.java b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServerDBSyncImpl.java
new file mode 100644
index 0000000..8626ce1
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServerDBSyncImpl.java
@@ -0,0 +1,948 @@
+package net.juniper.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 net.juniper.contrail.model.FloatingIpModel;
+import net.juniper.contrail.model.FloatingIpPoolModel;
+import net.juniper.contrail.model.ServiceInstanceModel;
+import net.juniper.contrail.model.VMInterfaceModel;
+import net.juniper.contrail.model.VirtualMachineModel;
+import net.juniper.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/7099686b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServerEventHandler.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServerEventHandler.java b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServerEventHandler.java
new file mode 100644
index 0000000..91acb3a
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServerEventHandler.java
@@ -0,0 +1,5 @@
+package net.juniper.contrail.management;
+
+public interface ServerEventHandler {
+ public void subscribe();
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7099686b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServerEventHandlerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServerEventHandlerImpl.java b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServerEventHandlerImpl.java
new file mode 100644
index 0000000..4b76879
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServerEventHandlerImpl.java
@@ -0,0 +1,223 @@
+package net.juniper.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;
+ 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);
+ 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));
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7099686b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServiceManager.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServiceManager.java b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServiceManager.java
new file mode 100644
index 0000000..cad2ea8
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServiceManager.java
@@ -0,0 +1,23 @@
+package net.juniper.contrail.management;
+
+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;
+
+import net.juniper.contrail.api.response.ServiceInstanceResponse;
+
+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/7099686b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServiceManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServiceManagerImpl.java b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServiceManagerImpl.java
new file mode 100644
index 0000000..20796f7
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServiceManagerImpl.java
@@ -0,0 +1,232 @@
+package net.juniper.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 net.juniper.contrail.api.ApiConnector;
+import net.juniper.contrail.api.response.ServiceInstanceResponse;
+import net.juniper.contrail.api.types.ServiceInstance;
+import net.juniper.contrail.api.types.VirtualNetwork;
+import net.juniper.contrail.model.ServiceInstanceModel;
+import net.juniper.contrail.model.VirtualMachineModel;
+
+@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/7099686b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServiceVirtualMachine.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServiceVirtualMachine.java b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServiceVirtualMachine.java
new file mode 100644
index 0000000..87650c1
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/management/ServiceVirtualMachine.java
@@ -0,0 +1,13 @@
+package net.juniper.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/7099686b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/FloatingIpModel.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/FloatingIpModel.java b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/FloatingIpModel.java
new file mode 100644
index 0000000..0e519ea
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/FloatingIpModel.java
@@ -0,0 +1,195 @@
+package net.juniper.contrail.model;
+
+import java.io.IOException;
+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;
+import net.juniper.contrail.management.ContrailManager;
+
+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/7099686b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/FloatingIpPoolModel.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/FloatingIpPoolModel.java b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/FloatingIpPoolModel.java
new file mode 100644
index 0000000..e699fd1
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/FloatingIpPoolModel.java
@@ -0,0 +1,152 @@
+package net.juniper.contrail.model;
+
+import java.io.IOException;
+import java.util.TreeSet;
+
+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;
+import net.juniper.contrail.management.ContrailManager;
+
+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;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7099686b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/InstanceIpModel.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/InstanceIpModel.java b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/InstanceIpModel.java
new file mode 100644
index 0000000..f29852c
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/InstanceIpModel.java
@@ -0,0 +1,157 @@
+package net.juniper.contrail.model;
+
+import java.io.IOException;
+
+import org.apache.log4j.Logger;
+
+import net.juniper.contrail.api.ObjectReference;
+import net.juniper.contrail.api.types.InstanceIp;
+import net.juniper.contrail.api.types.VirtualMachineInterface;
+import net.juniper.contrail.api.types.VirtualNetwork;
+import net.juniper.contrail.api.ApiConnector;
+
+import com.cloud.exception.InternalErrorException;
+
+public class InstanceIpModel extends ModelObjectBase {
+ private static final Logger s_logger = Logger.getLogger(InstanceIpModel.class);
+
+ private String _name;
+ private String _uuid;
+
+ private String _ipAddress;
+
+ private VMInterfaceModel _vmiModel;
+
+ public InstanceIpModel(String vmName, int deviceId) {
+ _name = vmName + '-' + deviceId;
+ }
+
+ public void addToVMInterface(VMInterfaceModel vmiModel) {
+ _vmiModel = vmiModel;
+ if (vmiModel != null) {
+ vmiModel.addSuccessor(this);
+ s_logger.debug("vmiModel has " + vmiModel.successors().size() + " IP addresses");
+ }
+ }
+
+ @Override
+ public int compareTo(ModelObject o) {
+ InstanceIpModel other;
+ try {
+ other = (InstanceIpModel) o;
+ } catch (ClassCastException ex) {
+ String clsname = o.getClass().getName();
+ return InstanceIpModel.class.getName().compareTo(clsname);
+ }
+ return _name.compareTo(other._name);
+ }
+
+ @Override
+ public void delete(ModelController controller) throws IOException {
+ ApiConnector api = controller.getApiAccessor();
+ if (_uuid != null) {
+ api.delete(InstanceIp.class, _uuid);
+ }
+ _uuid = null;
+ }
+
+ @Override
+ public void destroy(ModelController controller) throws IOException {
+ }
+
+ public String getAddress() {
+ return _ipAddress;
+ }
+
+ public String getName() {
+ return _name;
+ }
+
+ public void setAddress(String ipaddress) {
+ _ipAddress = ipaddress;
+ }
+
+ @Override
+ public void update(ModelController controller)
+ throws InternalErrorException, IOException {
+ assert _vmiModel != null;
+
+ ApiConnector api = controller.getApiAccessor();
+ VirtualNetworkModel vnModel = _vmiModel.getVirtualNetworkModel();
+ assert vnModel != null;
+
+ VirtualMachineInterface vmi = _vmiModel.getVMInterface();
+ VirtualNetwork vnet = vnModel.getVirtualNetwork();
+ if (vnet == null) {
+ vnet = (VirtualNetwork) api.findById(VirtualNetwork.class, _vmiModel.getNetworkUuid());
+ }
+
+ String ipid = api.findByName(InstanceIp.class, null, _name);
+ if (ipid == null) {
+ InstanceIp ip_obj = new InstanceIp();
+ ip_obj.setName(_name);
+ ip_obj.setVirtualNetwork(vnet);
+ if (_ipAddress != null) {
+ ip_obj.setAddress(_ipAddress);
+ }
+ ip_obj.setVirtualMachineInterface(vmi);
+ if (!api.create(ip_obj)) {
+ throw new InternalErrorException("Unable to create instance-ip " + _name);
+ }
+ api.read(ip_obj);
+ _uuid = ip_obj.getUuid();
+ if (_ipAddress == null) {
+ if (!api.read(ip_obj)) {
+ throw new InternalErrorException("Unable to read instance-ip " + _name);
+ }
+ }
+ _ipAddress = ip_obj.getAddress();
+ } else {
+ // Ensure that the instance-ip has the correct value and is pointing at the VMI.
+ InstanceIp ip_obj = (InstanceIp) api.findById(InstanceIp.class, ipid);
+ if (ip_obj == null) {
+ throw new InternalErrorException("Unable to read instance-ip " + _name);
+ }
+ boolean update = false;
+ String ipnet_id = ObjectReference.getReferenceListUuid(ip_obj.getVirtualNetwork());
+ if (ipnet_id == null || !ipnet_id.equals(_vmiModel.getNetworkUuid())) {
+ ip_obj.setVirtualNetwork(vnet);
+ update = true;
+ }
+
+ if (_ipAddress != null && !ip_obj.getAddress().equals(_ipAddress)) {
+ ip_obj.setAddress(_ipAddress);
+ update = true;
+ }
+
+ String vmi_id = ObjectReference.getReferenceListUuid(ip_obj.getVirtualMachineInterface());
+ if (vmi_id == null || !vmi_id.equals(_vmiModel.getUuid())) {
+ if (vmi != null) {
+ ip_obj.setVirtualMachineInterface(vmi);
+ update = true;
+ }
+ }
+
+ if (update && !api.update(ip_obj)) {
+ throw new InternalErrorException("Unable to update instance-ip: " + ip_obj.getName());
+ }
+ api.read(ip_obj);
+ _uuid = ip_obj.getUuid();
+ _ipAddress = ip_obj.getAddress();
+ }
+ }
+
+ @Override
+ public boolean verify(ModelController controller) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean compare(ModelController controller, ModelObject current) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7099686b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/ModelController.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/ModelController.java b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/ModelController.java
new file mode 100644
index 0000000..2da18ca
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/ModelController.java
@@ -0,0 +1,67 @@
+package net.juniper.contrail.model;
+
+import com.cloud.dc.dao.VlanDao;
+import com.cloud.network.dao.IPAddressDao;
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.vm.dao.NicDao;
+import com.cloud.vm.dao.UserVmDao;
+
+import net.juniper.contrail.api.ApiConnector;
+import net.juniper.contrail.management.ContrailManager;
+
+/**
+ * Collection of state necessary for model object to update the Contrail API server.
+ *
+ */
+public class ModelController {
+ ApiConnector _api;
+ ContrailManager _manager;
+ UserVmDao _vmDao;
+ NetworkDao _networkDao;
+ NicDao _nicDao;
+ VlanDao _vlanDao;
+ IPAddressDao _ipAddressDao;
+
+ public ModelController(ContrailManager manager, ApiConnector api, UserVmDao vmDao, NetworkDao networkDao,
+ NicDao nicDao, VlanDao vlanDao, IPAddressDao ipAddressDao) {
+ _manager = manager;
+ assert api != null;
+ _api = api;
+ assert vmDao != null;
+ _vmDao = vmDao;
+ assert networkDao != null;
+ _networkDao = networkDao;
+ assert nicDao != null;
+ _nicDao = nicDao;
+ assert vlanDao != null;
+ _vlanDao = vlanDao;
+ assert ipAddressDao != null;
+ _ipAddressDao = ipAddressDao;
+ }
+ ApiConnector getApiAccessor() {
+ return _api;
+ }
+ ContrailManager getManager() {
+ return _manager;
+ }
+
+ UserVmDao getVmDao() {
+ return _vmDao;
+ }
+
+ NetworkDao getNetworkDao() {
+ return _networkDao;
+ }
+
+ NicDao getNicDao() {
+ return _nicDao;
+ }
+
+ VlanDao getVlanDao() {
+ return _vlanDao;
+ }
+
+ IPAddressDao getIPAddressDao() {
+ return _ipAddressDao;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7099686b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/ModelObject.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/ModelObject.java b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/ModelObject.java
new file mode 100644
index 0000000..2f27082
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/net/juniper/contrail/model/ModelObject.java
@@ -0,0 +1,101 @@
+package net.juniper.contrail.model;
+
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.util.TreeSet;
+
+import com.cloud.exception.InternalErrorException;
+
+/**
+ * ModelObject
+ *
+ * A model object represents the desired state of the system.
+ *
+ * The object constructor should set the uuid and the internal id of the cloudstack objects.
+ *
+ * The build method reads the master database (typically cloudstack mysql) and derives the state that
+ * we wish to reflect in the contrail API. This method should not modify the Contrail API state.
+ *
+ * The verify method reads the API server state and compares with cached properties.
+ *
+ * The update method pushes updates to the contrail API server.
+ */
+public interface ModelObject {
+ public static class ModelReference implements Comparable<ModelReference> {
+ WeakReference<ModelObject> reference;
+ ModelReference(ModelObject obj) {
+ reference = new WeakReference<ModelObject>(obj);
+ }
+
+ @Override
+ public int compareTo(ModelReference other) {
+ ModelObject lhs = reference.get();
+ ModelObject rhs = other.reference.get();
+ if (lhs == null) {
+ if (rhs == null) {
+ return 0;
+ }
+ return -1;
+ }
+
+ return lhs.compareTo(rhs);
+ }
+ @Override
+ public boolean equals(Object other) {
+ try {
+ ModelReference rhs = (ModelReference) other;
+ return compareTo(rhs) == 0;
+ } catch (ClassCastException ex) {
+ }
+ return false;
+ }
+ public ModelObject get() {
+ return reference.get();
+ }
+ };
+
+ public void addSuccessor(ModelObject child);
+
+ public TreeSet<ModelReference> ancestors();
+ public void clearSuccessors();
+ public int compareTo(ModelObject o);
+
+ /**
+ * Delete the object from the API server.
+ * @param controller
+ * @throws IOException
+ */
+ public void delete(ModelController controller) throws IOException;
+
+ /**
+ * Deletes the object from the data model graph.
+ *
+ * @param controller
+ * @throws IOException
+ */
+ public void destroy(ModelController controller) throws IOException;
+
+ public void removeSuccessor(ModelObject child);
+
+ public TreeSet<ModelObject> successors();
+
+ /**
+ * Push updates to Contrail API server. This API is only valid for objects in the database.
+ * @param controller
+ * @throws IOException
+ * @throws InternalErrorException
+ */
+ public void update(ModelController controller) throws InternalErrorException, IOException;
+
+ /**
+ * Check that the state of the current object matches the state of the API server.
+ * @param controller
+ * @return
+ */
+ public boolean verify(ModelController controller);
+
+ /*
+ * Compare the state of existing model object with latest model object
+ */
+ public boolean compare(ModelController controller, ModelObject current);
+}