cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From h...@apache.org
Subject [3/6] OpenContrail network plugin
Date Fri, 01 Nov 2013 16:55:58 GMT
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6b5fab2f/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/InstanceIpModel.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/InstanceIpModel.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/InstanceIpModel.java
new file mode 100644
index 0000000..7588ba7
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/InstanceIpModel.java
@@ -0,0 +1,174 @@
+// 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.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/6b5fab2f/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/ModelController.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/ModelController.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/ModelController.java
new file mode 100644
index 0000000..8d57879
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/ModelController.java
@@ -0,0 +1,85 @@
+// 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 org.apache.cloudstack.network.contrail.management.ContrailManager;
+
+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;
+
+/**
+ * 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/6b5fab2f/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/ModelObject.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/ModelObject.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/ModelObject.java
new file mode 100644
index 0000000..71d28ac
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/ModelObject.java
@@ -0,0 +1,118 @@
+// 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.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);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6b5fab2f/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/ModelObjectBase.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/ModelObjectBase.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/ModelObjectBase.java
new file mode 100644
index 0000000..f22c7c5
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/ModelObjectBase.java
@@ -0,0 +1,111 @@
+// 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.util.Comparator;
+import java.util.TreeSet;
+
+public abstract class ModelObjectBase implements ModelObject {
+    public static class UuidComparator implements Comparator<ModelObject> {
+        @Override
+        public int compare(ModelObject lhs, ModelObject rhs) {
+            if (lhs == null) {
+                if (rhs == null) {
+                    return 0;
+                }
+                return -1;
+            }
+            if (rhs == null) {
+                return 1;
+            }
+            return lhs.compareTo(rhs);
+        }
+    }
+    private TreeSet<ModelReference> _ancestors;
+    
+    private TreeSet<ModelObject> _successors;
+
+    ModelObjectBase() {
+        _ancestors = new TreeSet<ModelReference>();
+        _successors = new TreeSet<ModelObject>(new UuidComparator());
+    }
+    
+    @Override
+    public void addSuccessor(ModelObject child) {
+        _successors.add(child);
+        ModelObjectBase base = (ModelObjectBase) child;
+        base._ancestors.add(new ModelReference(this));
+    }
+    
+    @Override
+    public TreeSet<ModelReference> ancestors() {
+        return _ancestors;
+    }
+    
+    private void clearAncestorReference(ModelObjectBase child) {
+        ModelReference ref = null;
+        for (ModelReference objref : child._ancestors) {
+            if (objref.get() == this) {
+                ref = objref;
+                break;
+            }
+        }
+        if (ref != null) {
+            child._ancestors.remove(ref);
+        }
+    }
+    
+    @Override
+    public void clearSuccessors() {
+        for (ModelObject successor : _successors) {
+            clearAncestorReference((ModelObjectBase) successor);
+        }
+        _successors.clear();
+    }
+
+    @Override
+    public boolean equals(Object rhs) {
+        ModelObject other;
+        try {
+            other = (ModelObject) rhs;
+        } catch (ClassCastException ex) {
+            return false;
+        }
+        return compareTo(other) == 0;
+    }
+    
+    @Override
+    protected void finalize() {
+        clearSuccessors();
+    }
+
+    public boolean hasDescendents() {
+        return !successors().isEmpty();
+    }
+    
+    @Override
+    public void removeSuccessor(ModelObject child) {
+        clearAncestorReference((ModelObjectBase) child);
+        _successors.remove(child);
+    }
+
+    @Override
+    public TreeSet<ModelObject> successors() {
+        return _successors;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6b5fab2f/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/ServiceInstanceModel.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/ServiceInstanceModel.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/ServiceInstanceModel.java
new file mode 100644
index 0000000..20b80be
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/ServiceInstanceModel.java
@@ -0,0 +1,320 @@
+// 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.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.apache.cloudstack.network.contrail.management.ContrailManager;
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+
+import net.juniper.contrail.api.ObjectReference;
+import net.juniper.contrail.api.types.NetworkPolicy;
+import net.juniper.contrail.api.types.PolicyEntriesType;
+import net.juniper.contrail.api.types.PolicyEntriesType.PolicyRuleType;
+import net.juniper.contrail.api.types.Project;
+import net.juniper.contrail.api.types.ServiceInstance;
+import net.juniper.contrail.api.types.ServiceInstanceType;
+import net.juniper.contrail.api.types.ServiceTemplate;
+import net.juniper.contrail.api.types.ServiceTemplateType;
+import net.juniper.contrail.api.types.VirtualNetwork;
+import net.juniper.contrail.api.types.VirtualNetworkPolicyType;
+import net.juniper.contrail.api.ApiConnector;
+
+import com.cloud.offering.ServiceOffering;
+import com.cloud.template.VirtualMachineTemplate;
+import com.cloud.utils.exception.CloudRuntimeException;
+
+public class ServiceInstanceModel extends ModelObjectBase {
+    private static final Logger s_logger = Logger.getLogger(ServiceInstanceModel.class);
+
+    private String _uuid;
+    private String _fq_name;
+    private String _projectId;
+    private String _mgmtName;
+    private String _leftName;
+    private String _rightName;
+   
+    private String _templateName;
+    private String _templateId;
+    private String _templateUrl;
+    private VirtualNetwork _left;
+    private VirtualNetwork _right;
+    private ServiceTemplate _tmpl;
+    private ServiceInstance _serviceInstance;
+    private NetworkPolicy _policy;
+
+    /**
+     * Create a ServiceInstance as result of an API call.
+     * 
+     * @param owner
+     * @param name
+     * @param template
+     * @param serviceOffering
+     * @param left
+     * @param right
+     */
+    public ServiceInstanceModel(Project project, String name, VirtualMachineTemplate template,
+            ServiceOffering serviceOffering, VirtualNetwork left, VirtualNetwork right) {
+        String parent_name;
+        if (project != null) {
+            parent_name = StringUtils.join(project.getQualifiedName(), ':');
+        } else {
+            parent_name = ContrailManager.VNC_ROOT_DOMAIN + ":" + ContrailManager.VNC_DEFAULT_PROJECT;
+        }
+        _fq_name = parent_name + ":" + name;
+        
+        _mgmtName = ContrailManager.VNC_ROOT_DOMAIN + ":" + ContrailManager.VNC_DEFAULT_PROJECT + ":"
+                + ContrailManager.managementNetworkName;
+        _left = left;
+        _right = right;
+        _leftName = StringUtils.join(left.getQualifiedName(), ":");
+        _rightName = StringUtils.join(right.getQualifiedName(), ":");
+        
+        _templateName = template.getName();
+        _templateId = template.getUuid();
+        _templateUrl = template.getUrl();
+        
+        _projectId = project.getUuid();
+    }
+
+    /**
+     * Create an empty ServiceInstance.
+     * @param uuid
+     */
+    public ServiceInstanceModel(String uuid) {
+        _uuid  = uuid;
+    }
+    
+    public String getQualifiedName() {
+        return _fq_name;
+    }
+    
+    public String getName() {
+        return _fq_name.substring(_fq_name.lastIndexOf(':') + 1);
+    }
+    
+    private void applyNetworkPolicy(ModelController controller, NetworkPolicy policy,
+            VirtualNetwork left, VirtualNetwork right) {
+        left.setNetworkPolicy(policy, new VirtualNetworkPolicyType(
+                new VirtualNetworkPolicyType.SequenceType(1, 0), null));
+        // TODO: network_ipam_refs attr is missing
+        left.clearNetworkIpam();
+        try {
+            ApiConnector api = controller.getApiAccessor();
+            api.update(left);
+        } catch (IOException ex) {
+            throw new CloudRuntimeException("Unable to update virtual-network", ex);
+        }
+        
+        right.setNetworkPolicy(policy, new VirtualNetworkPolicyType(
+                new VirtualNetworkPolicyType.SequenceType(1, 0), null));
+        // TODO: network_ipam_refs attr is missing
+        right.clearNetworkIpam();
+        try {
+            ApiConnector api = controller.getApiAccessor();
+            api.update(right);
+        } catch (IOException ex) {
+            throw new CloudRuntimeException("Unable to update virtual-network", ex);
+        }
+    }
+
+    /**
+     * Recreate the model object from the Contrail API which is the master for this type of object.
+     * @param siObj
+     */
+    public void build(ModelController controller, ServiceInstance siObj) {
+        ApiConnector api = controller.getApiAccessor();
+        _serviceInstance = siObj;
+        _fq_name = StringUtils.join(siObj.getQualifiedName(), ':');
+        ServiceInstanceType props = siObj.getProperties();
+        // TODO: read management network names and cache network objects.
+        ObjectReference ref = siObj.getServiceTemplate().get(0);
+        if (ref != null) {
+            try {
+                ServiceTemplate tmpl = (ServiceTemplate) api.findById(ServiceTemplate.class, ref.getUuid());
+                _templateId = tmpl.getUuid();
+            } catch (IOException ex) {
+                s_logger.warn("service-template read", ex);
+            }
+        }
+        try {
+            Project project = (Project) api.findById(Project.class, siObj.getParentUuid());
+            if (project != null) {
+                _projectId = project.getUuid();
+            }
+            String policyId = api.findByName(NetworkPolicy.class, project, siObj.getName());
+            if (policyId != null) {
+                _policy = (NetworkPolicy) api.findById(NetworkPolicy.class, policyId);
+            }
+        } catch (IOException ex) {
+            s_logger.warn("network-policy read", ex);
+        }
+    }
+    
+    @Override
+    public int compareTo(ModelObject o) {
+        ServiceInstanceModel other;
+        try {
+            other = (ServiceInstanceModel) o;
+        } catch (ClassCastException ex) {
+            String clsname = o.getClass().getName();
+            return ServiceInstanceModel.class.getName().compareTo(clsname);
+        }
+        return _fq_name.compareTo(other._fq_name);
+    }
+    
+    private ServiceInstance createServiceInstance(ModelController controller) {
+        Project project  = null;
+        if (_projectId != null) {
+            try {
+                ApiConnector api = controller.getApiAccessor();
+                project = (Project) api.findById(Project.class, _projectId);
+           } catch (IOException ex) {
+                s_logger.warn("project read", ex);
+                throw new CloudRuntimeException("Unable to create service-instance object", ex);            
+           }
+        }
+
+        ServiceInstance si_obj = new ServiceInstance();
+        if (project != null) {
+            si_obj.setParent(project);
+        }
+        si_obj.setName(getName());
+        si_obj.setServiceTemplate(_tmpl);
+        si_obj.setProperties(new ServiceInstanceType(false, _mgmtName, _leftName, null, _rightName, null,
+                new ServiceInstanceType.ServiceScaleOutType(1, false)));
+        try {
+            ApiConnector api = controller.getApiAccessor();
+            api.create(si_obj);
+        } catch (IOException ex) {
+            s_logger.warn("service-instance create", ex);
+            throw new CloudRuntimeException("Unable to create service-instance object", ex);
+        }
+        
+        return si_obj;
+    }
+    
+    private NetworkPolicy createServicePolicy(ModelController controller) {
+        NetworkPolicy policy = new NetworkPolicy();
+        policy.setParent(_serviceInstance.getParent());
+        policy.setName(_serviceInstance.getName());
+        PolicyEntriesType policy_map = new PolicyEntriesType();
+        List<PolicyRuleType.AddressType> srcList = new ArrayList<PolicyRuleType.AddressType>();
+        srcList.add(new PolicyRuleType.AddressType(null, _leftName, null));
+        List<PolicyRuleType.AddressType> dstList = new ArrayList<PolicyRuleType.AddressType>();
+        dstList.add(new PolicyRuleType.AddressType(null, _rightName, null));
+        List<String> siList = new ArrayList<String>();
+        siList.add(StringUtils.join(_serviceInstance.getQualifiedName(), ':'));
+        List<PolicyRuleType.PortType> portAny = new ArrayList<PolicyRuleType.PortType>();
+        portAny.add(new PolicyRuleType.PortType(0, 65535));
+        
+        PolicyRuleType rule = new PolicyRuleType(
+                new PolicyRuleType.SequenceType(1, 0), /* uuid */ null, "<>", "any",
+                srcList, portAny, /* application */ null, dstList, portAny,
+                new PolicyRuleType.ActionListType("pass", "in-network", siList, null));
+        policy_map.addPolicyRule(rule);
+        policy.setEntries(policy_map);
+        
+        try {
+            ApiConnector api = controller.getApiAccessor();
+            if (!api.create(policy)) {
+                throw new CloudRuntimeException("Unable to create network-policy");
+            }
+        } catch (IOException ex) {
+            throw new CloudRuntimeException("Unable to create network-policy", ex);
+        }
+        return policy;
+    }
+    
+    @Override
+    public void delete(ModelController controller) throws IOException {
+        ApiConnector api = controller.getApiAccessor();
+        if (_serviceInstance != null) {
+            api.delete(_serviceInstance);
+        }
+    }
+    
+    @Override
+    public void destroy(ModelController controller) throws IOException {
+    }
+    
+    public ServiceInstance getServiceInstance() {
+        return _serviceInstance;
+    }
+
+    public String getUuid() {
+        return _uuid;
+    }
+    
+    private ServiceTemplate locateServiceTemplate(ModelController controller) {
+        ServiceTemplate tmpl;
+        try {
+            ApiConnector api = controller.getApiAccessor();
+            tmpl = (ServiceTemplate) api.findById(ServiceTemplate.class, _templateId);
+        } catch (IOException ex) {
+            s_logger.warn("service-template read", ex);
+            throw new CloudRuntimeException("Unable to create service-template object", ex);
+        }
+        if (tmpl == null) {
+            tmpl = new ServiceTemplate();
+            tmpl.setName(_templateName);
+            tmpl.setUuid(_templateId);
+            ServiceTemplateType props = new ServiceTemplateType("in-network", null, _templateUrl, false, null);
+            tmpl.setProperties(props);
+            try {
+                ApiConnector api = controller.getApiAccessor();
+                api.create(tmpl);
+            } catch (IOException ex) {
+                throw new CloudRuntimeException("Unable to create service-template object", ex);
+            }
+        }
+        return tmpl;
+    }
+
+    @Override
+    public void update(ModelController controller) {
+        _tmpl = locateServiceTemplate(controller);
+        if (_serviceInstance == null) {
+            _serviceInstance = createServiceInstance(controller);
+        }
+        _uuid = _serviceInstance.getUuid();
+        if (_policy == null) {
+            _policy = createServicePolicy(controller);
+            // TODO: update the network model objects and call update
+            applyNetworkPolicy(controller, _policy, _left, _right);
+        }
+    }
+
+    @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 true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6b5fab2f/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/VMInterfaceModel.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/VMInterfaceModel.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/VMInterfaceModel.java
new file mode 100644
index 0000000..3476569
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/VMInterfaceModel.java
@@ -0,0 +1,265 @@
+// 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 net.juniper.contrail.api.types.MacAddressesType;
+import net.juniper.contrail.api.types.VirtualMachineInterface;
+import net.juniper.contrail.api.types.VirtualMachineInterfacePropertiesType;
+import net.juniper.contrail.api.ApiConnector;
+
+import com.cloud.exception.InternalErrorException;
+import com.cloud.network.Network;
+import com.cloud.vm.NicVO;
+import com.cloud.vm.VMInstanceVO;
+
+public class VMInterfaceModel extends ModelObjectBase {
+    private static final Logger s_logger = Logger.getLogger(VMInterfaceModel.class);
+
+    private String _uuid;
+    
+    /**
+     * properties
+     */
+    private String _vmName;
+    private int _deviceId;
+    private boolean _netActive;
+    private boolean _nicActive;
+    private String _serviceTag;
+    private String _networkId;
+    private String _macAddress;
+
+    /**
+     * cached objects
+     */
+    private VirtualMachineModel _vmModel;
+    private VirtualNetworkModel _vnModel;
+    private VirtualMachineInterface _vmi;
+    
+    public VMInterfaceModel(String uuid) {
+        _uuid = uuid;
+    }
+    
+    public void addToVirtualMachine(VirtualMachineModel vmModel) {
+        _vmModel = vmModel;
+        if (vmModel != null) {
+            vmModel.addSuccessor(this);
+        }
+    }
+    
+    public void addToVirtualNetwork(VirtualNetworkModel vnModel) {
+        _vnModel = vnModel;
+        if (vnModel != null) {
+            vnModel.addSuccessor(this);
+        }
+    }
+    
+    public void build(ModelController controller, VMInstanceVO instance, NicVO nic) throws IOException {
+        setProperties(controller, instance, nic);
+
+        InstanceIpModel ipModel = getInstanceIp();
+        String ipAddress = nic.getIp4Address();
+        if (ipAddress != null) {
+            if (ipModel == null) {
+                ipModel = new InstanceIpModel(_vmName, _deviceId);
+                ipModel.addToVMInterface(this);
+            }
+            ipModel.setAddress(ipAddress);
+        } else if (ipModel != null) {
+            removeSuccessor(ipModel);
+        }
+        
+        _macAddress = nic.getMacAddress();
+    }
+
+    @Override
+    public int compareTo(ModelObject o) {
+        VMInterfaceModel other;
+        try {
+            other = (VMInterfaceModel) o;
+        } catch (ClassCastException ex) {
+            String clsname = o.getClass().getName();
+            return VMInterfaceModel.class.getName().compareTo(clsname);
+        }
+        return _uuid.compareTo(other._uuid);
+    }
+    
+    @Override
+    public void delete(ModelController controller) throws IOException {
+        for (ModelObject successor: successors()) {
+            successor.delete(controller);
+        }
+
+        ApiConnector api = controller.getApiAccessor();
+        api.delete(VirtualMachineInterface.class, _uuid);        
+    }
+
+    @Override
+    public void destroy(ModelController controller) throws IOException {
+        delete(controller);
+        
+        for (ModelObject successor: successors()) {
+            successor.destroy(controller);
+        }
+        clearSuccessors();
+    }
+    
+    public InstanceIpModel getInstanceIp() {
+        for (ModelObject successor : successors()) {
+            if (successor.getClass() == InstanceIpModel.class) {
+                return (InstanceIpModel) successor;
+            }
+        }
+        return null;
+    }
+    
+    public String getNetworkUuid() {
+        return _networkId;
+    }
+    
+    public VirtualNetworkModel getVirtualNetworkModel() {
+        return _vnModel;
+    }
+    
+    public String getUuid() {
+        return _uuid;
+    }
+    
+    public VirtualMachineInterface getVMInterface() {
+        return _vmi;
+    }
+    
+    public void setProperties(ModelController controller, VMInstanceVO instance, NicVO nic) throws IOException {
+        _vmName = instance.getInstanceName();
+        _deviceId = nic.getDeviceId();
+        Network network = controller.getNetworkDao().findById(nic.getNetworkId());
+
+        switch (nic.getState()) {
+        case Allocated:
+        case Reserved:
+            _nicActive = true;
+            break;
+        default:
+            _nicActive = false;
+            break;
+        }
+        
+        switch (network.getState()) {
+        case Implemented:
+        case Setup:
+            _netActive = true;
+            break;
+        default:
+            _netActive = false;
+            break;
+        }
+        assert _vnModel != null;
+        _networkId = _vnModel.getUuid();        
+    }
+    
+    public void setActive() {
+        _nicActive = true;
+    }
+    
+    void setServiceTag(String tag) {
+        _serviceTag = tag;
+    }
+    
+    @Override
+    public void update(ModelController controller) throws InternalErrorException, IOException {
+        if (!_netActive || !_nicActive) {
+            s_logger.debug("vm interface update, _netActive: " + _netActive + ", _nicActive: " + _nicActive);
+            delete(controller);
+            return;
+        }
+        if (_vmModel == null) {
+            throw new InternalErrorException("virtual-machine not set on VMI: " + _uuid);
+        }
+        if (_vnModel == null) {
+            throw new InternalErrorException("virtual-network not set on VMI: " + _uuid);
+        }
+        ContrailManager manager = controller.getManager();
+        ApiConnector api = controller.getApiAccessor();
+
+        VirtualMachineInterface vmi = (VirtualMachineInterface) api.findById(VirtualMachineInterface.class, _uuid);
+        boolean create = false;
+        if (vmi == null) {
+            create = true;
+            vmi = new VirtualMachineInterface();
+            vmi.setParent(_vmModel.getVirtualMachine());
+            vmi.setName(manager.getVifNameByVmName(_vmModel.getInstanceName(), _deviceId));
+            vmi.setUuid(_uuid);
+            vmi.setVirtualNetwork(_vnModel.getVirtualNetwork());
+        } else {
+            // Do not try to update VMI to routing-instance references. These are managed by schema-transformer.
+            vmi.clearRoutingInstance();
+        }
+        _vmi = vmi;
+        if (_macAddress != null) {
+            MacAddressesType mac = new MacAddressesType();
+            mac.addMacAddress(_macAddress);
+            vmi.setMacAddresses(mac);
+        }
+        
+        if (_serviceTag != null) {
+            vmi.setProperties(new VirtualMachineInterfacePropertiesType(_serviceTag, null));
+        }
+
+        if (create) {
+            if (!api.create(vmi)) {
+                throw new InternalErrorException("Unable to create virtual-machine-interface " +  _uuid);
+            }
+        } else {
+            if (!api.update(vmi)) {
+                throw new InternalErrorException("Unable to update virtual-machine-interface " +  _uuid);
+            }
+        }
+
+        api.read(vmi);
+        
+        int ipCount = 0;
+        for (ModelObject successor: successors()) {
+            if (successor.getClass() == InstanceIpModel.class) {
+                ipCount++;
+            }
+            successor.update(controller);
+        }
+        // TODO: if there are no instance-ip successors present and we have an instance-ip object reference
+        // delete the object.
+        if (ipCount == 0) {
+            s_logger.warn("virtual-machine-interface " + _uuid + " has no instance-ip");
+        }
+    }
+    
+    @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 true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6b5fab2f/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/VirtualMachineModel.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/VirtualMachineModel.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/VirtualMachineModel.java
new file mode 100644
index 0000000..ec20a94
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/VirtualMachineModel.java
@@ -0,0 +1,349 @@
+// 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.List;
+import java.util.Map;
+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.network.dao.NetworkDao;
+import com.cloud.network.dao.NetworkVO;
+import com.cloud.uservm.UserVm;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.NicVO;
+import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.dao.NicDao;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+import net.juniper.contrail.api.types.Project;
+import net.juniper.contrail.api.types.ServiceInstance;
+import net.juniper.contrail.api.types.VirtualMachine;
+import net.juniper.contrail.api.ApiConnector;
+
+public class VirtualMachineModel extends ModelObjectBase {
+    private static final Logger s_logger = Logger.getLogger(VirtualMachineModel.class);
+
+    private String _uuid;
+    private long _instanceId;
+    
+    /*
+     * current state for object properties 
+     */
+    private boolean _initialized;
+    private boolean _active;
+    private String _serviceUuid;
+    private String _instanceName;
+    private String _projectId;
+    
+    /*
+     * cached API server objects
+     */
+    private VirtualMachine _vm;
+    private ServiceInstanceModel _serviceModel;
+    
+    public VirtualMachineModel(VMInstanceVO vm, String uuid) {
+        _uuid = uuid;
+        if (vm != null) {
+            _instanceId = vm.getId();
+            _instanceName = vm.getInstanceName();
+        }
+    }
+    
+    /**
+     * Resynchronize internal state from the cloudstack DB object.
+     * @param instance
+     */
+    public void build(ModelController controller, VMInstanceVO instance) {
+        setProperties(controller, instance);
+        UserVm userVm = controller.getVmDao().findById(instance.getId());
+        if (userVm != null && userVm.getUserData() != null) {
+            s_logger.debug("vm " + instance.getInstanceName() + " user data: " + userVm.getUserData());
+            final Gson json = new Gson();
+            Map<String, String> kvmap = json.fromJson(userVm.getUserData(),
+                    new TypeToken<Map<String, String>>(){}.getType());
+            String data = kvmap.get("service-instance");
+            if (data != null) {
+                /* link the object with the service instance */
+                buildServiceInstance(controller, data);
+            }
+        }
+    }
+
+    /**
+     * Link the virtual machine with the service instance when recovering state from database.
+     * 
+     * @param controller
+     * @param serviceUuid
+     */
+    private void buildServiceInstance(ModelController controller, String serviceUuid) {
+        ContrailManager manager = controller.getManager();
+        ApiConnector api = controller.getApiAccessor();
+        _serviceUuid = serviceUuid;
+        
+        ServiceInstanceModel siModel = manager.getDatabase().lookupServiceInstance(serviceUuid);
+        if (siModel == null) {
+            ServiceInstance siObj;
+            try {
+                siObj = (ServiceInstance) api.findById(ServiceInstance.class, serviceUuid);
+            } catch (IOException ex) {
+                s_logger.warn("service-instance read", ex);
+                throw new CloudRuntimeException("Unable to read service-instance object", ex);
+            }
+            if (siObj == null) {
+                siModel = new ServiceInstanceModel(serviceUuid);
+                siModel.build(controller, siObj);
+            }
+        }
+        _serviceModel = siModel;
+    }
+
+    @Override
+    public int compareTo(ModelObject o) {
+        VirtualMachineModel other;
+        try {
+            other = (VirtualMachineModel) o;
+        } catch (ClassCastException ex) {
+            String clsname = o.getClass().getName();
+            return VirtualMachineModel.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(VirtualMachine.class, _uuid);
+        } catch (IOException ex) {
+            s_logger.warn("virtual-machine delete", ex);
+        }
+
+
+        if (_serviceModel != null) {
+            _serviceModel.delete(controller);
+        }
+    }
+
+    @Override
+    public void destroy(ModelController controller) throws IOException {
+        delete(controller);
+
+        for (ModelObject successor: successors()) {
+            successor.destroy(controller);
+        }
+
+        clearSuccessors();
+        
+        if (_serviceModel != null) {
+            _serviceModel.removeSuccessor(this);
+            _serviceModel.destroy(controller);
+            ContrailManager manager = controller.getManager();
+            manager.getDatabase().getServiceInstances().remove(_serviceModel);
+            _serviceModel = null;
+        }
+    }
+
+    public String getInstanceName() {
+        return _instanceName;
+    }
+    
+    public String getUuid() {
+        return _uuid;
+    }
+
+    
+    public VirtualMachine getVirtualMachine() {
+        return _vm;
+    }
+    
+    public VMInterfaceModel getVMInterface(String uuid) {
+        TreeSet<ModelObject> tree = successors();
+        VMInterfaceModel vmiKey = new VMInterfaceModel(uuid);
+        VMInterfaceModel current = (VMInterfaceModel) tree.ceiling(vmiKey);
+        if (current != null && current.getUuid().equals(uuid)) {
+            return current;
+        }
+        return null;
+    }
+    
+    public boolean isActive() {
+        return _active;
+    }
+    
+    boolean isActiveInstance(VMInstanceVO instance) {
+        switch (instance.getState()) {
+        case Migrating:
+        case Starting:
+        case Running:
+        case Shutdowned:
+        case Stopped:
+        case Stopping:
+            return true;
+            
+        case Destroyed:
+        case Error:
+        case Expunging:
+            return false;
+            
+        default:
+            s_logger.warn("Unknown VMInstance state " + instance.getState().getDescription());
+        }
+        return true;
+    }
+    
+    /**
+     * Initialize the object properties based on the DB object.
+     * Common code between plugin calls and DBSync.
+     */
+    public void setProperties(ModelController controller, VMInstanceVO instance) {
+        ContrailManager manager = controller.getManager();
+        _instanceName = instance.getInstanceName();
+        _active = isActiveInstance(instance);
+        
+        try {
+            _projectId = manager.getProjectId(instance.getDomainId(), instance.getAccountId());
+        } catch (IOException ex) {
+            s_logger.warn("project read", ex);
+            throw new CloudRuntimeException(ex);
+        }
+        _initialized = true;
+    }
+
+    /**
+     * Link the virtual machine with a service instance via programmatic API call.
+     * @throws IOException 
+     */
+    public void setServiceInstance(ModelController controller, VMInstanceVO instance,
+            ServiceInstanceModel serviceModel) throws IOException {
+        _serviceUuid = serviceModel.getUuid();
+        _serviceModel = serviceModel;
+        serviceModel.addSuccessor(this);
+        setServiceInstanceNics(controller, instance);
+    }
+    
+    private void setServiceInstanceNics(ModelController controller, VMInstanceVO instance) throws IOException {
+        NicDao nicDao = controller.getNicDao();
+        ContrailManager manager = controller.getManager();
+        NetworkDao networkDao = controller.getNetworkDao();
+        
+        List<NicVO> nics = nicDao.listByVmId(_instanceId);
+        for (NicVO nic : nics) {
+            String tag;
+            
+            switch (nic.getDeviceId()) {
+            case 0:
+                tag = "management";
+                break;
+            case 1:
+                tag = "left";
+                break;
+            case 2:
+                tag = "right";
+                break;
+            default:
+                tag = null;
+            }
+
+            VMInterfaceModel vmiModel = getVMInterface(nic.getUuid());
+            if (vmiModel == null) {
+                vmiModel = new VMInterfaceModel(nic.getUuid());
+                vmiModel.addToVirtualMachine(this);
+                NetworkVO network = networkDao.findById(nic.getNetworkId());
+                VirtualNetworkModel vnModel = manager.getDatabase().lookupVirtualNetwork(
+                        network.getUuid(), manager.getCanonicalName(network), network.getTrafficType());
+                assert vnModel != null;
+                vmiModel.addToVirtualNetwork(vnModel);
+            }
+            vmiModel.setProperties(controller, instance, nic);
+            vmiModel.setServiceTag(tag);
+        }
+    }
+    
+    @Override
+    public void update(ModelController controller) throws InternalErrorException, IOException {
+        assert _initialized;
+        ApiConnector api = controller.getApiAccessor();
+
+        VirtualMachine vm = _vm;
+        if (vm == null) {
+            _vm = vm = (VirtualMachine) api.findById(VirtualMachine.class, _uuid);
+            if (vm == null) {
+                vm = new VirtualMachine();
+                if (_projectId != null) {
+                    Project project;
+                    try {
+                        project = (Project) api.findById(Project.class, _projectId);
+                    } catch (IOException ex) {
+                        s_logger.debug("project read", ex);
+                        throw new CloudRuntimeException("Failed to read project", ex);                    
+                    }
+                    vm.setParent(project);
+                }
+                vm.setName(_instanceName);
+                vm.setUuid(_uuid);
+            }
+        }
+
+        if (_serviceModel != null) { 
+            vm.setServiceInstance(_serviceModel.getServiceInstance());
+        }
+
+        if (_vm == null) {
+            try {
+                api.create(vm);
+            } catch (Exception ex) {
+                s_logger.debug("virtual-machine create", ex);
+                throw new CloudRuntimeException("Failed to create virtual-machine", ex);
+            }
+            _vm = vm;
+        } else {
+            try {
+                api.update(vm);
+            } catch (IOException ex) {
+                s_logger.warn("virtual-machine update", ex);
+                throw new CloudRuntimeException("Unable to update virtual-machine object", ex);
+            }            
+        }
+
+        for (ModelObject successor: successors()) {
+            successor.update(controller);
+        }
+    }
+    
+    @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 true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6b5fab2f/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/VirtualNetworkModel.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/VirtualNetworkModel.java b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/VirtualNetworkModel.java
new file mode 100644
index 0000000..b4968ac
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/src/org/apache/cloudstack/network/contrail/model/VirtualNetworkModel.java
@@ -0,0 +1,494 @@
+// 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.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.cloudstack.network.contrail.management.ContrailManager;
+import org.apache.log4j.Logger;
+
+import com.cloud.dc.VlanVO;
+import com.cloud.dc.dao.VlanDao;
+import com.cloud.exception.InternalErrorException;
+import com.cloud.network.Network;
+import com.cloud.network.Networks.TrafficType;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.utils.net.NetUtils;
+
+import net.juniper.contrail.api.ObjectReference;
+import net.juniper.contrail.api.types.NetworkIpam;
+import net.juniper.contrail.api.types.Project;
+import net.juniper.contrail.api.types.SubnetType;
+import net.juniper.contrail.api.types.VirtualNetwork;
+import net.juniper.contrail.api.types.VnSubnetsType;
+import net.juniper.contrail.api.ApiConnector;
+
+public class VirtualNetworkModel extends ModelObjectBase {
+    private static final Logger s_logger = Logger.getLogger(VirtualNetworkModel.class);
+
+    private String _uuid;
+    private long _id;
+    private TrafficType _trafficType; 
+
+    /*
+     * current state for object properties 
+     */
+    private boolean _initialized;
+    private String _name;
+    private String _prefix;
+    private String _gateway;
+    private String _projectId;
+
+    /*
+     * cached API server objects
+     */
+    private VirtualNetwork _vn;
+    private NetworkIpam _ipam;
+
+    private FloatingIpPoolModel _fipPoolModel;
+
+    public VirtualNetworkModel(Network network, String uuid, String name, TrafficType trafficType) {
+        _uuid = uuid;
+        _name = name;
+        _trafficType = trafficType;
+        if (network != null) {
+            _id = network.getId();
+        }
+
+        if (isDynamicNetwork()) {
+            assert _uuid != null : "uuid is must for dynamic networks";
+        } else {
+            assert _name != null : "name is must for static networks";
+        }
+    }
+
+    /*
+     * Resynchronize internal state from the cloudstack DB object.
+     */
+    public void build(ModelController controller, Network network) {
+        setProperties(controller, network);
+    }
+
+    /**
+     * Determine whether this network is dynamically created by cloudstack or is created by default by the contrail
+     * API server.
+     * 
+     * @return
+     */
+    boolean isDynamicNetwork() {
+        return (_trafficType == TrafficType.Guest) || (_trafficType == TrafficType.Public);
+    }
+    
+    @Override
+    public int compareTo(ModelObject o) {
+        VirtualNetworkModel other;
+        try {
+            other = (VirtualNetworkModel) o;
+        } catch (ClassCastException ex) {
+            String clsname = o.getClass().getName();
+            return VirtualNetworkModel.class.getName().compareTo(clsname);
+        }
+        
+        if (!isDynamicNetwork()) {
+            if (!other.isDynamicNetwork()) {
+                // name is not unique since both management and storage networks may map to ip-fabric
+                int cmp = _name.compareTo(other.getName());
+                if (cmp != 0) {
+                    return cmp;
+                }
+                return _trafficType.compareTo(other._trafficType);
+            }
+            return -1;
+        } else if (!other.isDynamicNetwork()) {
+            return 1;
+        }
+                
+        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(VirtualNetwork.class, _uuid);
+        } catch (IOException ex) {
+            s_logger.warn("virtual-network 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 VirtualNetwork getVirtualNetwork() {
+        return _vn;
+    }
+
+    /**
+     * Initialize the object properties based on the DB object.
+     * Common code between plugin calls and DBSync.
+     */
+    public void setProperties(ModelController controller, Network network) {
+        ContrailManager manager = controller.getManager();
+        _name = manager.getCanonicalName(network);
+        _prefix = network.getCidr();
+        _gateway = network.getGateway();
+        
+        // For non-cloudstack managed network, find the uuid at this stage.
+        if (!isDynamicNetwork()) {
+            try {
+                _uuid = manager.findVirtualNetworkId(network);
+            } catch (IOException ex) {
+                s_logger.warn("Unable to read virtual-network", ex);
+            }
+        }
+        
+        try {
+            _projectId = manager.getProjectId(network.getDomainId(), network.getAccountId());
+        } catch (IOException ex) {
+            s_logger.warn("project read", ex);
+            throw new CloudRuntimeException(ex);
+        }
+      
+        _initialized = true;
+    }
+
+    @Override
+    public void update(ModelController controller) throws InternalErrorException, IOException {
+
+        assert _initialized;
+
+        ApiConnector api = controller.getApiAccessor();
+        VlanDao vlanDao = controller.getVlanDao();
+        VirtualNetwork vn = _vn;
+        
+        if (!isDynamicNetwork()) {
+            _vn = (VirtualNetwork) controller.getApiAccessor().findById(VirtualNetwork.class, _uuid);
+            return;
+        }
+        
+        assert _uuid != null : "uuid is not set";
+
+        if (_vn == null) {
+            vn = _vn = (VirtualNetwork) controller.getApiAccessor().findById(VirtualNetwork.class, _uuid);
+            if (vn == null) {
+                vn = new VirtualNetwork();
+                if (_projectId != null) {
+                    Project project;
+                    try {
+                        project = (Project) api.findById(Project.class, _projectId);
+                    } catch (IOException ex) {
+                        s_logger.debug("project read", ex);
+                        throw new CloudRuntimeException("Failed to read project", ex);                    
+                    }
+                    vn.setParent(project);
+                }
+                vn.setName(_name);
+                vn.setUuid(_uuid);
+            } 
+        }
+     
+        if (_ipam == null) {
+            NetworkIpam ipam = null;
+            try {
+                String ipam_id = api.findByName(NetworkIpam.class, null, "default-network-ipam");
+                if (ipam_id == null) {
+                    s_logger.debug("could not find default-network-ipam");
+                    return;
+                }
+                ipam = (NetworkIpam) api.findById(NetworkIpam.class, ipam_id);
+                if (ipam == null) {
+                    s_logger.debug("could not find NetworkIpam with ipam_id: " + ipam_id);
+                    return;
+                }
+            } catch (IOException ex) {
+                s_logger.error(ex);
+                return;
+            }
+            _ipam = ipam;
+        }
+
+        if (_prefix != null) {
+            VnSubnetsType subnet = new VnSubnetsType();
+            String[] addr_pair = _prefix.split("\\/");
+            subnet.addIpamSubnets(new SubnetType(addr_pair[0], Integer.parseInt(addr_pair[1])), _gateway);
+            vn.setNetworkIpam(_ipam, subnet);
+        } else if (_trafficType == TrafficType.Public) {
+            vn.clearNetworkIpam();
+            /* Subnet information for Public is stored in the vlan table */
+            List<VlanVO> vlan_list = vlanDao.listVlansByNetworkId(_id);
+            for (VlanVO vlan : vlan_list) {
+                String cidr = NetUtils.ipAndNetMaskToCidr(vlan.getVlanGateway(), vlan.getVlanNetmask());
+                int slash = cidr.indexOf('/');
+                String ip_addr = cidr.substring(0, slash);
+                int plen = Integer.parseInt(cidr.substring(slash + 1));
+                VnSubnetsType subnet = new VnSubnetsType();
+                subnet.addIpamSubnets(new SubnetType(ip_addr, plen), vlan.getVlanGateway());
+                vn.addNetworkIpam(_ipam, subnet);
+            }
+        } 
+
+        if (_vn == null) {
+            try {
+                api.create(vn);
+            } catch (Exception ex) {
+                s_logger.debug("virtual-network create", ex);
+                throw new CloudRuntimeException("Failed to create virtual-network", ex);
+            }
+            _vn = vn;
+        } else {
+            try {
+                api.update(vn);
+            } catch (IOException ex) {
+                s_logger.warn("virtual-network update", ex);
+                throw new CloudRuntimeException("Unable to update virtual-network object", ex);
+            }            
+        }
+
+        for (ModelObject successor: successors()) {
+            successor.update(controller);
+        }
+    }
+
+    public void read(ModelController controller) {
+        ApiConnector api = controller.getApiAccessor();
+        VlanDao vlanDao = controller.getVlanDao();
+        try {
+            _vn = (VirtualNetwork) api.findById(VirtualNetwork.class, _uuid);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        if (_vn == null) {
+            return;
+        }
+        if (_ipam == null) {
+            NetworkIpam ipam = null;
+            try {
+                String ipam_id = api.findByName(NetworkIpam.class, null, "default-network-ipam");
+                if (ipam_id == null) {
+                    s_logger.debug("could not find default-network-ipam");
+                    return;
+                }
+                ipam = (NetworkIpam) api.findById(NetworkIpam.class, ipam_id);
+                if (ipam == null) {
+                    s_logger.debug("could not find NetworkIpam with ipam_id: " + ipam_id);
+                    return;
+                }
+            } catch (IOException ex) {
+                s_logger.error(ex);
+                return;
+            }
+            _ipam = ipam;
+        }
+
+        if (_prefix != null) {
+            VnSubnetsType subnet = new VnSubnetsType();
+            String[] addr_pair = _prefix.split("\\/");
+            subnet.addIpamSubnets(new SubnetType(addr_pair[0], Integer.parseInt(addr_pair[1])), _gateway);
+            _vn.setNetworkIpam(_ipam, subnet);
+        } else if (_trafficType == TrafficType.Public) {
+            _vn.clearNetworkIpam();
+            /* Subnet information for Public is stored in the vlan table */
+            List<VlanVO> vlan_list = vlanDao.listVlansByNetworkId(_id);
+            for (VlanVO vlan : vlan_list) {
+                String cidr = NetUtils.ipAndNetMaskToCidr(vlan.getVlanGateway(), vlan.getVlanNetmask());
+                int slash = cidr.indexOf('/');
+                String ip_addr = cidr.substring(0, slash);
+                int plen = Integer.parseInt(cidr.substring(slash + 1));
+                VnSubnetsType subnet = new VnSubnetsType();
+                subnet.addIpamSubnets(new SubnetType(ip_addr, plen), vlan.getVlanGateway());
+                _vn.addNetworkIpam(_ipam, subnet);
+            }
+        } 
+        return;
+    }
+
+    @Override
+    public boolean verify(ModelController controller) {
+        assert _initialized : "initialized is false";
+        assert _uuid != null : "uuid is not set";
+
+        ApiConnector api = controller.getApiAccessor();
+        VlanDao vlanDao = controller.getVlanDao();
+
+        try {
+            _vn = (VirtualNetwork) api.findById(VirtualNetwork.class, _uuid);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        if (_vn == null) {
+            return false;
+        }
+
+        if (!isDynamicNetwork()) {
+            return true;
+        }
+        
+        List<String> dbSubnets = new ArrayList<String>();
+        if (_trafficType == TrafficType.Public) {
+            List<VlanVO> vlan_list = vlanDao.listVlansByNetworkId(_id);
+            for (VlanVO vlan:vlan_list) {
+                String cidr = NetUtils.ipAndNetMaskToCidr(vlan.getVlanGateway(), vlan.getVlanNetmask());
+                dbSubnets.add(vlan.getVlanGateway() + cidr);
+            }
+        } else {
+            dbSubnets.add(this._gateway + this._prefix);  
+        }
+            
+        List<ObjectReference<VnSubnetsType>> ipamRefs = _vn.getNetworkIpam();
+        List<String> vncSubnets = new ArrayList<String>();
+        
+        if (ipamRefs == null && !dbSubnets.isEmpty()) {
+            return false;
+        }
+        
+        if (ipamRefs != null) {
+            for (ObjectReference<VnSubnetsType> ref: ipamRefs) {
+                VnSubnetsType vnSubnetType = ref.getAttr();
+                if (vnSubnetType != null) {
+                    List<VnSubnetsType.IpamSubnetType> subnets = vnSubnetType.getIpamSubnets();
+                    if (subnets != null && !subnets.isEmpty()) {
+                        VnSubnetsType.IpamSubnetType ipamSubnet = subnets.get(0);
+                        vncSubnets.add(ipamSubnet.getDefaultGateway() +
+                                ipamSubnet.getSubnet().getIpPrefix() +"/" + ipamSubnet.getSubnet().getIpPrefixLen());  
+                    }  
+                } 
+            }
+        }
+        // unordered, no duplicates hence perform negation operation as set 
+        Set<String> diff = new HashSet<String>(dbSubnets);
+        diff.removeAll(vncSubnets);
+        
+        if (!diff.isEmpty()) {
+            s_logger.debug("Subnets changed, network: " + this._name + 
+                    "; db: " + dbSubnets + ", vnc: " + vncSubnets + ", diff: " + diff);
+            return false;
+        }
+        
+        for (ModelObject successor: successors()) {
+            if (!successor.verify(controller)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean compare(ModelController controller, ModelObject o) {
+        VirtualNetworkModel latest;
+        ApiConnector api = controller.getApiAccessor();
+
+        assert this._vn != null : "vnc virtual network current is not initialized";
+
+        try {
+            latest = (VirtualNetworkModel) o;            
+        } catch (ClassCastException ex) {
+            s_logger.warn("Invalid model object is passed to cast to VirtualNetworkModel");
+            return false;
+        }
+        
+        try {
+            latest.read(controller);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+        assert latest._vn != null : "vnc virtual network new is not initialized";
+        
+        List<ObjectReference<VnSubnetsType>> currentIpamRefs = this._vn.getNetworkIpam();
+        List<ObjectReference<VnSubnetsType>> newIpamRefs = latest._vn.getNetworkIpam();
+        List<String> currentSubnets = new ArrayList<String>();
+        List<String> newSubnets = new ArrayList<String>();
+
+        
+        if ((currentIpamRefs == null && newIpamRefs != null) || 
+            (currentIpamRefs != null && newIpamRefs == null)) {  //Check for existence only
+            s_logger.debug("ipams differ: current=" + currentIpamRefs + ", new=" + newIpamRefs);
+            return false;
+        }        
+        if (currentIpamRefs == null) {
+            return true;
+        }
+        
+        for (ObjectReference<VnSubnetsType> ref: currentIpamRefs) {
+            VnSubnetsType vnSubnetType = ref.getAttr();
+            if (vnSubnetType != null) {
+                List<VnSubnetsType.IpamSubnetType> subnets = vnSubnetType.getIpamSubnets();
+                if (subnets != null && !subnets.isEmpty()) {
+                    VnSubnetsType.IpamSubnetType ipamSubnet = subnets.get(0);
+                    currentSubnets.add(ipamSubnet.getDefaultGateway() + ipamSubnet.getSubnet().getIpPrefix() +
+                            "/" + ipamSubnet.getSubnet().getIpPrefixLen());  
+                } 
+            } 
+        }
+        
+        for (ObjectReference<VnSubnetsType> ref: newIpamRefs) {
+            VnSubnetsType vnSubnetType = ref.getAttr();
+            if (vnSubnetType != null) {
+                List<VnSubnetsType.IpamSubnetType> subnets = vnSubnetType.getIpamSubnets();
+                if (subnets != null && !subnets.isEmpty()) {
+                    VnSubnetsType.IpamSubnetType ipamSubnet = subnets.get(0);
+                    newSubnets.add(ipamSubnet.getDefaultGateway() + ipamSubnet.getSubnet().getIpPrefix() +
+                            "/" + ipamSubnet.getSubnet().getIpPrefixLen());  
+                } 
+            } 
+        }
+        
+        Set<String> diff = new HashSet<String>(currentSubnets);
+        diff.removeAll(newSubnets);
+        
+        if (!diff.isEmpty()) {
+            s_logger.debug("Subnets differ, network: " + this._name + 
+                    "; db: " + currentSubnets + ", vnc: " + newSubnets + ", diff: " + diff);
+            return false;
+        }
+                
+        return true;
+    }
+
+    public FloatingIpPoolModel getFipPoolModel() {
+        return _fipPoolModel;
+    }
+    public void setFipPoolModel(FloatingIpPoolModel fipPoolModel) {
+        _fipPoolModel = fipPoolModel;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/6b5fab2f/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/ApiConnectorMockito.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/ApiConnectorMockito.java b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/ApiConnectorMockito.java
new file mode 100644
index 0000000..e70ac5e
--- /dev/null
+++ b/plugins/network-elements/juniper-contrail/test/org/apache/cloudstack/network/contrail/management/ApiConnectorMockito.java
@@ -0,0 +1,149 @@
+// 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.List;
+import java.util.Map;
+
+import net.juniper.contrail.api.ApiConnector;
+import net.juniper.contrail.api.ApiConnectorMock;
+import net.juniper.contrail.api.ApiObjectBase;
+import net.juniper.contrail.api.ApiPropertyBase;
+import net.juniper.contrail.api.ObjectReference;
+import net.juniper.contrail.api.types.NetworkIpam;
+
+import org.apache.log4j.Logger;
+import static org.mockito.Mockito.*;
+
+import com.google.common.collect.ImmutableMap;
+
+public class ApiConnectorMockito implements ApiConnector {
+    private static final Logger s_logger =
+            Logger.getLogger(ApiConnectorMockito.class);
+
+    static final Map<String, ApiObjectBase> object_map = new ImmutableMap.Builder<String, ApiObjectBase>().
+            put("network-ipam:default-network-ipam", new NetworkIpam()).
+            build();
+    private ApiConnectorMock _mock;
+    private ApiConnector _spy;
+
+    public ApiConnectorMockito(String hostname, int port) {
+        _mock = new ApiConnectorMock(hostname, port);
+        _spy = spy(_mock);
+    }
+
+    public ApiConnector getSpy() {
+        return _spy;
+    }
+
+    @Override
+    public boolean create(ApiObjectBase arg0) throws IOException {
+        s_logger.debug("create " + arg0.getClass().getName() + " id: " + arg0.getUuid());
+        return _spy.create(arg0);
+    }
+
+    @Override
+    public void delete(ApiObjectBase arg0) throws IOException {
+        s_logger.debug("delete " + arg0.getClass().getName() + " id: " + arg0.getUuid());
+        _spy.delete(arg0);
+    }
+
+    @Override
+    public void delete(Class<? extends ApiObjectBase> arg0, String arg1)
+            throws IOException {
+        s_logger.debug("create " + arg0.getName() + " id: " + arg1);
+        _spy.delete(arg0, arg1);
+    }
+
+    @Override
+    public ApiObjectBase find(Class<? extends ApiObjectBase> arg0,
+            ApiObjectBase arg1, String arg2) throws IOException {
+        StringBuilder msg = new StringBuilder();
+        msg.append("find " + arg0.getName());
+        if (arg1 != null) {
+            msg.append(" parent: " + arg1.getName());
+        }
+        msg.append(" name: " + arg2);
+
+        return _mock.find(arg0, arg1, arg2);
+    }
+
+    @Override
+    public ApiObjectBase findByFQN(Class<? extends ApiObjectBase> arg0,
+            String arg1) throws IOException {
+        s_logger.debug("find " + arg0.getName() + " name: " + arg1);
+        return _mock.findByFQN(arg0, arg1);
+    }
+
+    @Override
+    public ApiObjectBase findById(Class<? extends ApiObjectBase> arg0,
+            String arg1) throws IOException {
+        s_logger.debug("find " + arg0.getName() + " id: " + arg1);
+        return _mock.findById(arg0, arg1);
+    }
+
+    @Override
+    public String findByName(Class<? extends ApiObjectBase> arg0,
+            List<String> arg1) throws IOException {
+        s_logger.debug("find " + arg0.getName() + " name: " + arg1);
+        return _mock.findByName(arg0, arg1);
+    }
+
+    @Override
+    public String findByName(Class<? extends ApiObjectBase> arg0,
+            ApiObjectBase arg1, String arg2) throws IOException {
+        StringBuilder msg = new StringBuilder();
+        msg.append("findByName " + arg0.getName());
+        if (arg1 != null) {
+            msg.append(" parent: " + arg1.getName());
+        }
+        msg.append(" name: " + arg2);
+        s_logger.debug(msg.toString());
+        return _mock.findByName(arg0, arg1, arg2);
+    }
+
+    @Override
+    public <T extends ApiPropertyBase> List<? extends ApiObjectBase> getObjects(
+            Class<? extends ApiObjectBase> arg0, List<ObjectReference<T>> arg1)
+                    throws IOException {
+        s_logger.debug("getObjects" + arg0.getName());
+        return _mock.getObjects(arg0, arg1);
+    }
+
+    @Override
+    public List<? extends ApiObjectBase> list(
+            Class<? extends ApiObjectBase> arg0, List<String> arg1)
+                    throws IOException {
+        s_logger.debug("list" + arg0.getName());
+        return _mock.list(arg0, arg1);
+    }
+
+    @Override
+    public boolean read(ApiObjectBase arg0) throws IOException {
+        s_logger.debug("read " + arg0.getClass().getName() + " id: " + arg0.getUuid());
+        return _mock.read(arg0);
+    }
+
+    @Override
+    public boolean update(ApiObjectBase arg0) throws IOException {
+        s_logger.debug("update " + arg0.getClass().getName() + " id: " + arg0.getUuid());
+        return _spy.update(arg0);
+    }
+
+}


Mime
View raw message