You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by bh...@apache.org on 2015/03/12 07:05:01 UTC

[09/12] git commit: updated refs/heads/master to c27c694

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c27c6943/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3FenceBuilder.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3FenceBuilder.java b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3FenceBuilder.java
new file mode 100755
index 0000000..b297cc9
--- /dev/null
+++ b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3FenceBuilder.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * 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 com.cloud.hypervisor.ovm3.resources;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.FenceAnswer;
+import com.cloud.agent.api.FenceCommand;
+import com.cloud.exception.AgentUnavailableException;
+import com.cloud.exception.OperationTimedoutException;
+import com.cloud.ha.FenceBuilder;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.Status;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.resource.ResourceManager;
+import com.cloud.utils.component.AdapterBase;
+import com.cloud.vm.VirtualMachine;
+
+@Local(value = FenceBuilder.class)
+public class Ovm3FenceBuilder extends AdapterBase implements FenceBuilder {
+    Map<String, Object> fenceParams;
+    private static final Logger LOGGER = Logger.getLogger(Ovm3FenceBuilder.class);
+    @Inject
+    AgentManager agentMgr;
+    @Inject
+    ResourceManager resourceMgr;
+
+
+    @Override
+    public boolean configure(String name, Map<String, Object> params)
+            throws ConfigurationException {
+        fenceParams = params;
+        return true;
+    }
+
+    @Override
+    public boolean start() {
+        /* start the agent here ? */
+        return true;
+    }
+
+    @Override
+    public boolean stop() {
+        /* stop the agent here ? */
+        return true;
+    }
+
+    public Ovm3FenceBuilder() {
+        super();
+    }
+
+    @Override
+    public Boolean fenceOff(VirtualMachine vm, Host host) {
+        if (host.getHypervisorType() != HypervisorType.Ovm3) {
+            LOGGER.debug("Don't know how to fence non Ovm3 hosts "
+                    + host.getHypervisorType());
+            return null;
+        } else {
+            LOGGER.debug("Fencing " + vm + " on host " + host
+                    + " with params: "+ fenceParams );
+        }
+
+        List<HostVO> hosts = resourceMgr.listAllHostsInCluster(host
+                .getClusterId());
+        FenceCommand fence = new FenceCommand(vm, host);
+
+        for (HostVO h : hosts) {
+            if (h.getHypervisorType() == HypervisorType.Ovm3 &&
+                    h.getStatus() == Status.Up &&
+                    h.getId() != host.getId()) {
+                FenceAnswer answer;
+                try {
+                    answer = (FenceAnswer) agentMgr.send(h.getId(), fence);
+                } catch (AgentUnavailableException | OperationTimedoutException e) {
+                    if (LOGGER.isDebugEnabled()) {
+                        LOGGER.debug("Moving on to the next host because "
+                                + h.toString() + " is unavailable", e);
+                    }
+                    continue;
+                }
+                if (answer != null && answer.getResult()) {
+                    return true;
+                }
+            }
+        }
+
+        if (LOGGER.isDebugEnabled()) {
+            LOGGER.debug("Unable to fence off " + vm.toString() + " on "
+                    + host.toString());
+        }
+
+        return false;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c27c6943/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3HypervisorGuru.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3HypervisorGuru.java b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3HypervisorGuru.java
new file mode 100755
index 0000000..526b061
--- /dev/null
+++ b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3HypervisorGuru.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * 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 com.cloud.hypervisor.ovm3.resources;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+
+import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
+import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
+import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
+import org.apache.cloudstack.storage.command.CopyCommand;
+import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.to.DataObjectType;
+import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.agent.api.to.NfsTO;
+import com.cloud.agent.api.to.VirtualMachineTO;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.hypervisor.HypervisorGuru;
+import com.cloud.hypervisor.HypervisorGuruBase;
+import com.cloud.storage.GuestOSVO;
+import com.cloud.storage.dao.GuestOSDao;
+import com.cloud.utils.Pair;
+import com.cloud.vm.VirtualMachineProfile;
+
+@Local(value = HypervisorGuru.class)
+public class Ovm3HypervisorGuru extends HypervisorGuruBase implements HypervisorGuru {
+    private final Logger LOGGER = Logger.getLogger(Ovm3HypervisorGuru.class);
+    @Inject
+    GuestOSDao guestOsDao;
+    @Inject
+    EndPointSelector endPointSelector;
+    @Inject
+    HostDao hostDao;
+
+    protected Ovm3HypervisorGuru() {
+        super();
+    }
+
+    @Override
+    public HypervisorType getHypervisorType() {
+        return HypervisorType.Ovm3;
+    }
+
+    @Override
+    public VirtualMachineTO implement(VirtualMachineProfile vm) {
+        VirtualMachineTO to = toVirtualMachineTO(vm);
+        to.setBootloader(vm.getBootLoaderType());
+
+        // Determine the VM's OS description
+        GuestOSVO guestOS = guestOsDao.findById(vm.getVirtualMachine()
+                .getGuestOSId());
+        to.setOs(guestOS.getDisplayName());
+
+        return to;
+    }
+
+    @Override
+    public boolean trackVmHostChange() {
+        return true;
+    }
+
+    /* I dislike the notion of having to place this here, and not being able to just override
+     *
+     * (non-Javadoc)
+     * @see com.cloud.hypervisor.HypervisorGuruBase#getCommandHostDelegation(long, com.cloud.agent.api.Command)
+     */
+    public Pair<Boolean, Long> getCommandHostDelegation(long hostId, Command cmd) {
+        LOGGER.debug("getCommandHostDelegation: " + cmd.getClass());
+        if (cmd instanceof StorageSubSystemCommand) {
+            StorageSubSystemCommand c = (StorageSubSystemCommand)cmd;
+            c.setExecuteInSequence(true);
+        }
+        if (cmd instanceof CopyCommand) {
+            CopyCommand cpyCommand = (CopyCommand)cmd;
+            DataTO srcData = cpyCommand.getSrcTO();
+            DataTO destData = cpyCommand.getDestTO();
+
+            if (srcData.getObjectType() == DataObjectType.SNAPSHOT && destData.getObjectType() == DataObjectType.TEMPLATE) {
+                LOGGER.debug("Snapshot to Template: " + cmd);
+                DataStoreTO srcStore = srcData.getDataStore();
+                DataStoreTO destStore = destData.getDataStore();
+                if (srcStore instanceof NfsTO && destStore instanceof NfsTO) {
+                    HostVO host = hostDao.findById(hostId);
+                    EndPoint ep = endPointSelector.selectHypervisorHost(new ZoneScope(host.getDataCenterId()));
+                    host = hostDao.findById(ep.getId());
+                    hostDao.loadDetails(host);
+                    // String snapshotHotFixVersion = host.getDetail(XenserverConfigs.XS620HotFix);
+                    // if (snapshotHotFixVersion != null && snapshotHotFixVersion.equalsIgnoreCase(XenserverConfigs.XSHotFix62ESP1004)) {
+                    return new Pair<Boolean, Long>(Boolean.TRUE,  Long.valueOf(ep.getId()));
+                }
+            }
+        }
+        return new Pair<Boolean, Long>(Boolean.FALSE, Long.valueOf(hostId));
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c27c6943/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3HypervisorResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3HypervisorResource.java b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3HypervisorResource.java
new file mode 100644
index 0000000..dac8f1c
--- /dev/null
+++ b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3HypervisorResource.java
@@ -0,0 +1,596 @@
+/*******************************************************************************
+ * 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 com.cloud.hypervisor.ovm3.resources;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.ejb.Local;
+import javax.inject.Inject;
+import javax.naming.ConfigurationException;
+
+import org.apache.cloudstack.storage.command.AttachCommand;
+import org.apache.cloudstack.storage.command.CopyCommand;
+import org.apache.cloudstack.storage.command.CreateObjectCommand;
+import org.apache.cloudstack.storage.command.DeleteCommand;
+import org.apache.cloudstack.storage.command.DettachCommand;
+import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.IAgentControl;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.AttachIsoCommand;
+// import com.cloud.agent.api.AttachVolumeCommand;
+import com.cloud.agent.api.CheckHealthCommand;
+import com.cloud.agent.api.CheckNetworkCommand;
+import com.cloud.agent.api.CheckOnHostCommand;
+import com.cloud.agent.api.CheckVirtualMachineCommand;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
+import com.cloud.agent.api.CreateStoragePoolCommand;
+import com.cloud.agent.api.DeleteStoragePoolCommand;
+import com.cloud.agent.api.FenceCommand;
+import com.cloud.agent.api.GetHostStatsCommand;
+import com.cloud.agent.api.GetStorageStatsCommand;
+import com.cloud.agent.api.GetVmStatsCommand;
+import com.cloud.agent.api.GetVncPortCommand;
+import com.cloud.agent.api.MaintainCommand;
+import com.cloud.agent.api.MigrateCommand;
+import com.cloud.agent.api.ModifyStoragePoolCommand;
+import com.cloud.agent.api.NetworkRulesSystemVmCommand;
+import com.cloud.agent.api.NetworkUsageCommand;
+import com.cloud.agent.api.PingCommand;
+import com.cloud.agent.api.PingRoutingCommand;
+import com.cloud.agent.api.PingTestCommand;
+import com.cloud.agent.api.PlugNicCommand;
+import com.cloud.agent.api.PrepareForMigrationCommand;
+import com.cloud.agent.api.ReadyCommand;
+import com.cloud.agent.api.RebootAnswer;
+import com.cloud.agent.api.RebootCommand;
+import com.cloud.agent.api.StartAnswer;
+import com.cloud.agent.api.StartCommand;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StartupRoutingCommand;
+import com.cloud.agent.api.StartupStorageCommand;
+import com.cloud.agent.api.StopAnswer;
+import com.cloud.agent.api.StopCommand;
+import com.cloud.agent.api.UnPlugNicCommand;
+import com.cloud.agent.api.check.CheckSshCommand;
+import com.cloud.agent.api.routing.NetworkElementCommand;
+import com.cloud.agent.api.storage.CopyVolumeCommand;
+import com.cloud.agent.api.storage.CreateCommand;
+import com.cloud.agent.api.storage.DestroyCommand;
+import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
+import com.cloud.agent.api.to.NicTO;
+import com.cloud.agent.api.to.VirtualMachineTO;
+import com.cloud.agent.resource.virtualnetwork.VirtualRoutingResource;
+import com.cloud.host.Host.Type;
+import com.cloud.hypervisor.ovm3.objects.CloudstackPlugin;
+import com.cloud.hypervisor.ovm3.objects.Common;
+import com.cloud.hypervisor.ovm3.objects.Connection;
+import com.cloud.hypervisor.ovm3.objects.Ovm3ResourceException;
+import com.cloud.hypervisor.ovm3.objects.OvmObject;
+import com.cloud.hypervisor.ovm3.objects.Xen;
+import com.cloud.hypervisor.ovm3.resources.helpers.Ovm3Configuration;
+import com.cloud.hypervisor.ovm3.resources.helpers.Ovm3HypervisorNetwork;
+import com.cloud.hypervisor.ovm3.resources.helpers.Ovm3StoragePool;
+import com.cloud.hypervisor.ovm3.resources.helpers.Ovm3VirtualRoutingSupport;
+import com.cloud.hypervisor.ovm3.resources.helpers.Ovm3VmGuestTypes;
+import com.cloud.hypervisor.ovm3.resources.helpers.Ovm3VmSupport;
+import com.cloud.hypervisor.ovm3.resources.helpers.Ovm3HypervisorSupport;
+import com.cloud.network.Networks.TrafficType;
+import com.cloud.resource.ServerResourceBase;
+import com.cloud.resource.hypervisor.HypervisorResource;
+import com.cloud.storage.resource.StorageSubsystemCommandHandler;
+import com.cloud.storage.resource.StorageSubsystemCommandHandlerBase;
+import com.cloud.template.VirtualMachineTemplate.BootloaderType;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachine.State;
+/**
+ * Hypervisor related
+ */
+@Local(value = HypervisorResource.class)
+public class Ovm3HypervisorResource extends ServerResourceBase implements
+        HypervisorResource {
+    private static final Logger LOGGER = Logger
+            .getLogger(Ovm3HypervisorResource.class);
+    @Inject
+    private VirtualRoutingResource vrResource;
+    private StorageSubsystemCommandHandler storageHandler;
+    private Connection c;
+    private Ovm3StoragePool storagepool;
+    private Ovm3StorageProcessor storageprocessor;
+    private Ovm3HypervisorSupport hypervisorsupport;
+    private Ovm3VmSupport vmsupport;
+    private Ovm3HypervisorNetwork hypervisornetwork;
+    private Ovm3VirtualRoutingResource virtualroutingresource;
+    private Ovm3VirtualRoutingSupport virtualroutingsupport;
+    private Ovm3Configuration configuration;
+    private Ovm3VmGuestTypes guesttypes;
+    private OvmObject ovmObject = new OvmObject();
+
+    /*
+     * TODO: Add a network map, so we know which tagged interfaces we can remove
+     * and switch to ConcurrentHashMap
+     */
+    private Map<String, Xen.Vm> vmMap = new HashMap<String, Xen.Vm>();
+
+    @Override
+    public Type getType() {
+        return Type.Routing;
+    }
+
+    /*
+     * configure is called before this, does setup of the connection and
+     * gets the params.
+     *
+     * @see com.cloud.resource.ServerResource#initialize()
+     */
+    @Override
+    public StartupCommand[] initialize() {
+        LOGGER.debug("Ovm3 resource intializing");
+        try {
+            StartupRoutingCommand srCmd = new StartupRoutingCommand();
+            StartupStorageCommand ssCmd = new StartupStorageCommand();
+
+            /* here stuff gets completed, but where should state live ? */
+            hypervisorsupport.fillHostInfo(srCmd);
+            hypervisorsupport.vmStateMapClear();
+            LOGGER.debug("Ovm3 pool " + ssCmd + " " + srCmd);
+            return new StartupCommand[] { srCmd, ssCmd };
+        } catch (Exception e) {
+            LOGGER.debug("Ovm3 resource initializes failed", e);
+            return new StartupCommand[] {};
+        }
+    }
+
+    @Override
+    public PingCommand getCurrentStatus(long id) {
+        try {
+            /* feels useless somehow */
+            Common test = new Common(c);
+            String ping = "put";
+            String pong = test.echo(ping);
+            if (pong.contains(ping)) {
+                hypervisorsupport.syncState();
+                CloudstackPlugin cSp = new CloudstackPlugin(c);
+                if (!cSp.dom0CheckStorageHealthCheck(configuration .getAgentScriptsDir(),
+                        configuration.getAgentCheckStorageScript(),
+                        configuration.getCsHostGuid(),
+                        configuration.getAgentStorageCheckTimeout(),
+                        configuration.getAgentStorageCheckInterval())
+                        && !cSp.dom0CheckStorageHealthCheck()) {
+                    LOGGER.error("Storage health check not running on "
+                            + configuration.getAgentHostname());
+                } else if (cSp.dom0CheckStorageHealthCheck()) {
+                    LOGGER.error("Storage health check started on "
+                            + configuration.getAgentHostname());
+                } else {
+                    LOGGER.debug("Storage health check running on "
+                            + configuration.getAgentHostname());
+                }
+                return new PingRoutingCommand(getType(), id,
+                        hypervisorsupport.hostVmStateReport());
+            } else {
+                LOGGER.debug("Agent did not respond correctly: " + ping
+                        + " but got " + pong);
+            }
+
+        } catch (Ovm3ResourceException | NullPointerException e) {
+            LOGGER.debug("Check agent status failed", e);
+            return null;
+        }
+        return null;
+    }
+
+    @Override
+    public Answer executeRequest(Command cmd) {
+        Class<? extends Command> clazz = cmd.getClass();
+        LOGGER.debug("executeRequest called: " + cmd.getClass());
+        if (cmd instanceof NetworkElementCommand) {
+            return vrResource.executeRequest((NetworkElementCommand) cmd);
+        } else if (clazz == NetworkRulesSystemVmCommand.class) {
+            return virtualroutingsupport
+                    .execute((NetworkRulesSystemVmCommand) cmd);
+        } else if (clazz == CheckSshCommand.class) {
+            return virtualroutingsupport.execute((CheckSshCommand) cmd);
+        } else if (clazz == NetworkUsageCommand.class) {
+            return virtualroutingsupport.execute((NetworkUsageCommand) cmd);
+        /* double check order! */
+        } else if (clazz == CopyCommand.class) {
+            return storageprocessor.execute((CopyCommand) cmd);
+        } else if (cmd instanceof StorageSubSystemCommand) {
+            return storageHandler.handleStorageCommands((StorageSubSystemCommand) cmd);
+        } else if (clazz == DeleteCommand.class) {
+            return storageprocessor.execute((DeleteCommand) cmd);
+        } else if (clazz == CreateCommand.class) {
+            return storageprocessor.execute((CreateCommand) cmd);
+        } else if (clazz == CreateObjectCommand.class) {
+            return storageprocessor.execute((CreateObjectCommand) cmd);
+        } else if (clazz == AttachIsoCommand.class) {
+            return storageprocessor.attachIso((AttachCommand) cmd);
+         } else if (clazz == DettachCommand.class) {
+            return storageprocessor.execute((DettachCommand) cmd);
+         } else if (clazz == AttachCommand.class) {
+            return storageprocessor.execute((AttachCommand) cmd);
+         } else if (clazz == CreatePrivateTemplateFromVolumeCommand.class) {
+             return storageprocessor
+                     .execute((CreatePrivateTemplateFromVolumeCommand) cmd);
+         } else if (clazz == DestroyCommand.class) {
+             return storageprocessor.execute((DestroyCommand) cmd);
+         } else if (clazz == CopyVolumeCommand.class) {
+             return storageprocessor.execute((CopyVolumeCommand) cmd);
+        } else if (clazz == CreateStoragePoolCommand.class) {
+            return storagepool.execute((CreateStoragePoolCommand) cmd);
+        } else if (clazz == ModifyStoragePoolCommand.class) {
+            return storagepool.execute((ModifyStoragePoolCommand) cmd);
+        } else if (clazz == PrimaryStorageDownloadCommand.class) {
+            return storagepool.execute((PrimaryStorageDownloadCommand) cmd);
+        } else if (clazz == DeleteStoragePoolCommand.class) {
+            return storagepool.execute((DeleteStoragePoolCommand) cmd);
+        } else if (clazz == GetStorageStatsCommand.class) {
+            return storagepool.execute((GetStorageStatsCommand) cmd);
+        } else if (clazz == GetHostStatsCommand.class) {
+            return hypervisorsupport.execute((GetHostStatsCommand) cmd);
+        } else if (clazz == CheckVirtualMachineCommand.class) {
+            return hypervisorsupport.execute((CheckVirtualMachineCommand) cmd);
+        } else if (clazz == MaintainCommand.class) {
+            return hypervisorsupport.execute((MaintainCommand) cmd);
+        } else if (clazz == CheckHealthCommand.class) {
+            return hypervisorsupport.execute((CheckHealthCommand) cmd);
+        } else if (clazz == ReadyCommand.class) {
+            return hypervisorsupport.execute((ReadyCommand) cmd);
+        } else if (clazz == FenceCommand.class) {
+            return hypervisorsupport.execute((FenceCommand) cmd);
+        } else if (clazz == CheckOnHostCommand.class) {
+            return hypervisorsupport.execute((CheckOnHostCommand)cmd);
+        } else if (clazz == PingTestCommand.class) {
+            return hypervisornetwork.execute((PingTestCommand) cmd);
+        } else if (clazz == CheckNetworkCommand.class) {
+            return hypervisornetwork.execute((CheckNetworkCommand) cmd);
+        } else if (clazz == GetVmStatsCommand.class) {
+            return vmsupport.execute((GetVmStatsCommand) cmd);
+        } else if (clazz == PrepareForMigrationCommand.class) {
+            return vmsupport.execute((PrepareForMigrationCommand) cmd);
+        } else if (clazz == MigrateCommand.class) {
+            return vmsupport.execute((MigrateCommand) cmd);
+        } else if (clazz == GetVncPortCommand.class) {
+            return vmsupport.execute((GetVncPortCommand) cmd);
+        } else if (clazz == PlugNicCommand.class) {
+            return vmsupport.execute((PlugNicCommand) cmd);
+        } else if (clazz == UnPlugNicCommand.class) {
+            return vmsupport.execute((UnPlugNicCommand) cmd);
+        } else if (clazz == StartCommand.class) {
+            return execute((StartCommand) cmd);
+        } else if (clazz == StopCommand.class) {
+            return execute((StopCommand) cmd);
+        } else if (clazz == RebootCommand.class) {
+            return execute((RebootCommand) cmd);
+        }
+        LOGGER.debug("Can't find class for executeRequest " + cmd.getClass() +", is your direct call missing?");
+        return Answer.createUnsupportedCommandAnswer(cmd);
+    }
+
+    @Override
+    public void disconnected() {
+        LOGGER.debug("disconnected seems unused everywhere else");
+    }
+
+    @Override
+    public IAgentControl getAgentControl() {
+        LOGGER.debug("we don't use IAgentControl");
+        return null;
+    }
+
+    @Override
+    public void setAgentControl(IAgentControl agentControl) {
+        LOGGER.debug("No use in setting IAgentControl");
+    }
+
+    @Override
+    public String getName() {
+        return configuration.getAgentName();
+    }
+
+    @Override
+    public void setName(String name) {
+        configuration.setAgentName(name);
+    }
+
+    @Override
+    public void setConfigParams(Map<String, Object> params) {
+        configuration.setRawParams(params);
+    }
+
+    @Override
+    public Map<String, Object> getConfigParams() {
+        return configuration.getRawParams();
+    }
+
+    @Override
+    public int getRunLevel() {
+        return 0;
+    }
+
+    @Override
+    public void setRunLevel(int level) {
+        LOGGER.debug("runlevel seems unused in other hypervisors");
+    }
+
+    /**
+     * Base configuration of the plugins components.
+     */
+    @Override
+    public boolean configure(String name, Map<String, Object> params)
+            throws ConfigurationException {
+        LOGGER.debug("configure " + name + " with params: " + params);
+        /* check if we're master or not and if we can connect */
+        try {
+            configuration = new Ovm3Configuration(params);
+            if (!configuration.getIsTest()) {
+                c = new Connection(configuration.getAgentIp(),
+                        configuration.getAgentOvsAgentPort(),
+                        configuration.getAgentOvsAgentUser(),
+                        configuration.getAgentOvsAgentPassword());
+                c.setHostName(configuration.getAgentHostname());
+            }
+            hypervisorsupport = new Ovm3HypervisorSupport(c, configuration);
+            if (!configuration.getIsTest()) {
+                hypervisorsupport.setupServer(configuration
+                        .getAgentSshKeyFileName());
+            }
+            hypervisorsupport.masterCheck();
+        } catch (Exception e) {
+            throw new CloudRuntimeException("Base checks failed for "
+                    + configuration.getAgentHostname(), e);
+        }
+        hypervisornetwork = new Ovm3HypervisorNetwork(c, configuration);
+        hypervisornetwork.configureNetworking();
+        virtualroutingresource = new Ovm3VirtualRoutingResource(c);
+        storagepool = new Ovm3StoragePool(c, configuration);
+        storagepool.prepareForPool();
+        storageprocessor = new Ovm3StorageProcessor(c, configuration,
+                storagepool);
+        vmsupport = new Ovm3VmSupport(c, configuration, hypervisorsupport,
+                storageprocessor, storagepool, hypervisornetwork);
+        vrResource = new VirtualRoutingResource(virtualroutingresource);
+        if (!vrResource.configure(name, params)) {
+            throw new ConfigurationException(
+                    "Unable to configure VirtualRoutingResource");
+        }
+        guesttypes = new Ovm3VmGuestTypes();
+        storageHandler = new StorageSubsystemCommandHandlerBase(storageprocessor);
+        virtualroutingsupport = new Ovm3VirtualRoutingSupport(c, configuration,
+                virtualroutingresource);
+        this.setConfigParams(params);
+        return true;
+    }
+
+    public void setConnection(Connection con) {
+        LOGGER.debug("override connection: " + con.getIp());
+        c = con;
+    }
+
+    @Override
+    public boolean start() {
+        return true;
+    }
+
+    @Override
+    public boolean stop() {
+        return true;
+    }
+
+    @Override
+    public synchronized StartAnswer execute(StartCommand cmd) {
+        VirtualMachineTO vmSpec = cmd.getVirtualMachine();
+        String vmName = vmSpec.getName();
+        State state = State.Stopped;
+        Xen xen = new Xen(c);
+
+        try {
+            hypervisorsupport.setVmStateStarting(vmName);
+            Xen.Vm vm = xen.getVmConfig();
+            /* max and min ? */
+            vm.setVmCpus(vmSpec.getCpus());
+            /* in mb not in bytes */
+            vm.setVmMemory(vmSpec.getMinRam() / 1024 / 1024);
+            vm.setVmUuid(UUID.nameUUIDFromBytes(vmSpec.getName().getBytes())
+                    .toString());
+            vm.setVmName(vmName);
+
+            String domType = guesttypes.getOvm3GuestType(vmSpec.getOs());
+            if (domType == null || domType.isEmpty()) {
+                domType = "default";
+                LOGGER.debug("VM Virt type missing setting to: " + domType);
+            } else {
+                LOGGER.debug("VM Virt type set to " + domType + " for "
+                        + vmSpec.getOs());
+            }
+            vm.setVmDomainType(domType);
+
+            if (vmSpec.getBootloader() == BootloaderType.CD) {
+                LOGGER.warn("CD booting is not supported");
+            }
+            /*
+             * officially CD boot is only supported on HVM, although there is a
+             * simple way around it..
+             */
+            vmsupport.createVbds(vm, vmSpec);
+
+            if (vmSpec.getType() != VirtualMachine.Type.User) {
+                // double check control network if we run a non user VM
+                hypervisornetwork.configureNetworking();
+                vm.setVmExtra(vmSpec.getBootArgs().replace(" ", "%"));
+                String svmPath = configuration.getAgentOvmRepoPath() + "/"
+                        + ovmObject.deDash(vm.getPrimaryPoolUuid()) + "/ISOs";
+                String svmIso = svmPath + "/"
+                        + storagepool.getSystemVMPatchIsoFile().getName();
+                vm.addIso(svmIso);
+            }
+            /* OVS/Network stuff should go here! */
+            vmsupport.createVifs(vm, vmSpec);
+            vm.setupVifs();
+
+            vm.setVnc("0.0.0.0", vmSpec.getVncPassword());
+            xen.createVm(ovmObject.deDash(vm.getPrimaryPoolUuid()),
+                    vm.getVmUuid());
+            xen.startVm(ovmObject.deDash(vm.getPrimaryPoolUuid()),
+                    vm.getVmUuid());
+            state = State.Running;
+
+            if (vmSpec.getType() != VirtualMachine.Type.User) {
+                String controlIp = null;
+                for (NicTO nic : vmSpec.getNics()) {
+                    if (nic.getType() == TrafficType.Control) {
+                        controlIp = nic.getIp();
+                    }
+                }
+                /* fix is in cloudstack.py for xend restart timer */
+                for (int count = 0; count < 60; count++) {
+                    CloudstackPlugin cSp = new CloudstackPlugin(c);
+                    /* skip a beat to make sure we didn't miss start */
+                    if (hypervisorsupport.getVmState(vmName) == null && count > 1) {
+                        String msg = "VM " + vmName + " went missing on "
+                                + configuration.getAgentHostname()
+                                + ", returning stopped";
+                        LOGGER.debug(msg);
+                        state = State.Stopped;
+                        return new StartAnswer(cmd, msg);
+                    }
+                    /* creative fix? */
+                    try {
+                        Boolean res = cSp.domrCheckSsh(controlIp);
+                        LOGGER.debug("connected to " + controlIp
+                                + " on attempt " + count + " result: " + res);
+                        if (res) {
+                            break;
+                        }
+                    } catch (Exception x) {
+                        LOGGER.trace(
+                                "unable to connect to " + controlIp
+                                        + " on attempt " + count + " "
+                                        + x.getMessage(), x);
+                    }
+                    Thread.sleep(5000);
+                }
+            }
+            /*
+             * Can't remember if HA worked if we were only a pool ?
+             */
+            if (configuration.getAgentInOvm3Pool()
+                    && configuration.getAgentInOvm3Cluster()) {
+                xen.configureVmHa(ovmObject.deDash(vm.getPrimaryPoolUuid()),
+                        vm.getVmUuid(), true);
+            }
+            /* should be starting no ? */
+            state = State.Running;
+            return new StartAnswer(cmd);
+        } catch (Exception e) {
+            LOGGER.debug("Start vm " + vmName + " failed", e);
+            state = State.Stopped;
+            return new StartAnswer(cmd, e.getMessage());
+        } finally {
+            hypervisorsupport.setVmState(vmName, state);
+        }
+    }
+
+    /**
+     * Removes the vm and its configuration from the hypervisor.
+     */
+    @Override
+    public StopAnswer execute(StopCommand cmd) {
+        String vmName = cmd.getVmName();
+        State state = State.Error;
+        hypervisorsupport.setVmState(vmName, State.Stopping);
+
+        try {
+            Xen vms = new Xen(c);
+            Xen.Vm vm = null;
+            vm = vms.getRunningVmConfig(vmName);
+
+            if (vm == null) {
+                state = State.Stopping;
+                LOGGER.debug("Unable to get details of vm: " + vmName
+                        + ", treating it as Stopping");
+                return new StopAnswer(cmd, "success", true);
+            }
+            String repoId = ovmObject.deDash(vm.getVmRootDiskPoolId());
+            String vmId = vm.getVmUuid();
+            /* can we do without the poolId ? */
+            vms.stopVm(repoId, vmId);
+            int tries = 30;
+            while (vms.getRunningVmConfig(vmName) != null && tries > 0) {
+                String msg = "Waiting for " + vmName + " to stop";
+                LOGGER.debug(msg);
+                tries--;
+                Thread.sleep(10 * 1000);
+            }
+            vms.deleteVm(repoId, vmId);
+            vmsupport.cleanup(vm);
+
+            if (vms.getRunningVmConfig(vmName) != null) {
+                String msg = "Stop " + vmName + " failed ";
+                LOGGER.debug(msg);
+                return new StopAnswer(cmd, msg, false);
+            }
+            state = State.Stopped;
+            return new StopAnswer(cmd, "success", true);
+        } catch (Exception e) {
+            LOGGER.debug("Stop " + vmName + " failed ", e);
+            return new StopAnswer(cmd, e.getMessage(), false);
+        } finally {
+            if (state != null) {
+                hypervisorsupport.setVmState(vmName, state);
+            } else {
+                hypervisorsupport.revmoveVmState(vmName);
+            }
+        }
+    }
+
+    @Override
+    public RebootAnswer execute(RebootCommand cmd) {
+        String vmName = cmd.getVmName();
+        hypervisorsupport.setVmStateStarting(vmName);
+        try {
+            Xen xen = new Xen(c);
+            Xen.Vm vm = xen.getRunningVmConfig(vmName);
+            if (vm == null) {
+                return new RebootAnswer(cmd, vmName + " not present", false);
+            }
+            xen.rebootVm(ovmObject.deDash(vm.getVmRootDiskPoolId()),
+                    vm.getVmUuid());
+            vm = xen.getRunningVmConfig(vmName);
+            Integer vncPort = vm.getVncPort();
+            return new RebootAnswer(cmd, null, vncPort);
+        } catch (Exception e) {
+            LOGGER.debug("Reboot " + vmName + " failed", e);
+            return new RebootAnswer(cmd, e.getMessage(), false);
+        } finally {
+            hypervisorsupport.setVmState(vmName, State.Running);
+        }
+    }
+
+    @Override
+    protected String getDefaultScriptsDir() {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c27c6943/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3StorageProcessor.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3StorageProcessor.java b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3StorageProcessor.java
new file mode 100644
index 0000000..b1a92bb
--- /dev/null
+++ b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3StorageProcessor.java
@@ -0,0 +1,835 @@
+/*******************************************************************************
+ * 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 com.cloud.hypervisor.ovm3.resources;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.UUID;
+
+import org.apache.cloudstack.storage.command.AttachAnswer;
+import org.apache.cloudstack.storage.command.AttachCommand;
+import org.apache.cloudstack.storage.command.CopyCmdAnswer;
+import org.apache.cloudstack.storage.command.CopyCommand;
+import org.apache.cloudstack.storage.command.CreateObjectAnswer;
+import org.apache.cloudstack.storage.command.CreateObjectCommand;
+import org.apache.cloudstack.storage.command.DeleteCommand;
+import org.apache.cloudstack.storage.command.DettachCommand;
+import org.apache.cloudstack.storage.command.ForgetObjectCmd;
+import org.apache.cloudstack.storage.command.IntroduceObjectCmd;
+import org.apache.cloudstack.storage.command.SnapshotAndCopyAnswer;
+import org.apache.cloudstack.storage.command.SnapshotAndCopyCommand;
+import org.apache.cloudstack.storage.to.SnapshotObjectTO;
+import org.apache.cloudstack.storage.to.TemplateObjectTO;
+import org.apache.cloudstack.storage.to.VolumeObjectTO;
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.CreatePrivateTemplateFromVolumeCommand;
+import com.cloud.agent.api.storage.CopyVolumeAnswer;
+import com.cloud.agent.api.storage.CopyVolumeCommand;
+import com.cloud.agent.api.storage.CreateAnswer;
+import com.cloud.agent.api.storage.CreateCommand;
+import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
+import com.cloud.agent.api.storage.DestroyCommand;
+import com.cloud.agent.api.to.DataObjectType;
+import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.agent.api.to.DataTO;
+import com.cloud.agent.api.to.DiskTO;
+import com.cloud.agent.api.to.NfsTO;
+import com.cloud.agent.api.to.StorageFilerTO;
+import com.cloud.agent.api.to.VolumeTO;
+import com.cloud.hypervisor.ovm3.objects.CloudstackPlugin;
+import com.cloud.hypervisor.ovm3.objects.Connection;
+import com.cloud.hypervisor.ovm3.objects.Linux;
+import com.cloud.hypervisor.ovm3.objects.Ovm3ResourceException;
+import com.cloud.hypervisor.ovm3.objects.OvmObject;
+import com.cloud.hypervisor.ovm3.objects.StoragePlugin;
+import com.cloud.hypervisor.ovm3.objects.Xen;
+import com.cloud.hypervisor.ovm3.objects.StoragePlugin.FileProperties;
+import com.cloud.hypervisor.ovm3.resources.helpers.Ovm3Configuration;
+import com.cloud.hypervisor.ovm3.resources.helpers.Ovm3StoragePool;
+import com.cloud.storage.Volume;
+import com.cloud.storage.Storage.ImageFormat;
+import com.cloud.storage.resource.StorageProcessor;
+import com.cloud.vm.DiskProfile;
+
+/**
+ * Storage related bits
+ */
+public class Ovm3StorageProcessor implements StorageProcessor {
+    private final Logger LOGGER = Logger.getLogger(Ovm3StorageProcessor.class);
+    private Connection c;
+    private OvmObject ovmObject = new OvmObject();
+    private Ovm3StoragePool pool;
+    private Ovm3Configuration config;
+
+    public Ovm3StorageProcessor(Connection conn, Ovm3Configuration ovm3config,
+            Ovm3StoragePool ovm3pool) {
+        c = conn;
+        config = ovm3config;
+        pool = ovm3pool;
+    }
+
+    public final Answer execute(final CopyCommand cmd) {
+        LOGGER.debug("execute: "+ cmd.getClass());
+        DataTO srcData = cmd.getSrcTO();
+        DataStoreTO srcStore = srcData.getDataStore();
+        DataTO destData = cmd.getDestTO();
+        DataStoreTO destStore = destData.getDataStore();
+        String msg = "Not implemented yet";
+        try {
+            /* target and source are NFS and TEMPLATE */
+            if ((srcStore instanceof NfsTO)
+                    && (srcData.getObjectType() == DataObjectType.TEMPLATE)
+                    && (destData.getObjectType() == DataObjectType.TEMPLATE)) {
+                return copyTemplateToPrimaryStorage(cmd);
+                /* we assume the cache for templates is local */
+            } else if ((srcData.getObjectType() == DataObjectType.TEMPLATE)
+                    && (destData.getObjectType() == DataObjectType.VOLUME)) {
+                if (srcStore.getUrl().equals(destStore.getUrl())) {
+                    return cloneVolumeFromBaseTemplate(cmd);
+                } else {
+                    msg = "Primary to Primary doesn't match";
+                    LOGGER.debug(msg);
+                }
+            } else if ((srcData.getObjectType() == DataObjectType.SNAPSHOT)
+                    && (destData.getObjectType() == DataObjectType.SNAPSHOT)) {
+                return backupSnapshot(cmd);
+            } else if ((srcData.getObjectType() == DataObjectType.SNAPSHOT)
+                    && (destData.getObjectType() == DataObjectType.TEMPLATE)) {
+                return createTemplateFromSnapshot(cmd);
+            } else {
+                msg = "Unable to do stuff for " + srcStore.getClass() + ":"
+                        + srcData.getObjectType() + " to "
+                        + destStore.getClass() + ":" + destData.getObjectType();
+                LOGGER.debug(msg);
+            }
+        } catch (Exception e) {
+            msg = "Catch Exception " + e.getClass().getName()
+                    + " for template due to " + e.toString();
+            LOGGER.warn(msg, e);
+            return new CopyCmdAnswer(msg);
+        }
+        LOGGER.warn(msg + " " + cmd.getClass());
+        return new CopyCmdAnswer(msg);
+    }
+
+    public Answer execute(DeleteCommand cmd) {
+        DataTO data = cmd.getData();
+        String msg;
+        LOGGER.debug("Deleting object: " + data.getObjectType());
+        if (data.getObjectType() == DataObjectType.VOLUME) {
+            return deleteVolume(cmd);
+        } else if (data.getObjectType() == DataObjectType.SNAPSHOT) {
+            return deleteSnapshot(cmd);
+        } else if (data.getObjectType() == DataObjectType.TEMPLATE) {
+            msg = "Template deletion is not implemented yet.";
+            LOGGER.info(msg);
+        } else {
+            msg = data.getObjectType() + " deletion is not implemented yet.";
+            LOGGER.info(msg);
+        }
+        return new Answer(cmd, false, msg);
+    }
+
+    public CreateAnswer execute(CreateCommand cmd) {
+        LOGGER.debug("execute: "+ cmd.getClass());
+        StorageFilerTO primaryStorage = cmd.getPool();
+        DiskProfile disk = cmd.getDiskCharacteristics();
+        /* disk should have a uuid */
+        // should also be replaced with getVirtualDiskPath ?
+        String fileName = UUID.randomUUID().toString() + ".raw";
+        String dst = primaryStorage.getPath() + File.separator
+                + primaryStorage.getUuid() + File.separator + fileName;
+        try {
+            StoragePlugin store = new StoragePlugin(c);
+            if (cmd.getTemplateUrl() != null) {
+                LOGGER.debug("CreateCommand " + cmd.getTemplateUrl() + " "
+                        + dst);
+                Linux host = new Linux(c);
+                host.copyFile(cmd.getTemplateUrl(), dst);
+            } else {
+                /* this is a dup with the createVolume ? */
+                LOGGER.debug("CreateCommand " + dst);
+                store.storagePluginCreate(primaryStorage.getUuid(),
+                        primaryStorage.getHost(), dst, disk.getSize(), false);
+            }
+            FileProperties fp = store.storagePluginGetFileInfo(
+                    primaryStorage.getUuid(), primaryStorage.getHost(), dst);
+            VolumeTO volume = new VolumeTO(cmd.getVolumeId(), disk.getType(),
+                    primaryStorage.getType(), primaryStorage.getUuid(),
+                    primaryStorage.getPath(), fileName, fp.getName(),
+                    fp.getSize(), null);
+            return new CreateAnswer(cmd, volume);
+        } catch (Exception e) {
+            LOGGER.debug("CreateCommand failed", e);
+            return new CreateAnswer(cmd, e.getMessage());
+        }
+    }
+
+    /**
+     * src is Nfs and Template from secondary storage to primary
+     */
+    @Override
+    public CopyCmdAnswer copyTemplateToPrimaryStorage(CopyCommand cmd) {
+        LOGGER.debug("execute copyTemplateToPrimaryStorage: "+ cmd.getClass());
+        DataTO srcData = cmd.getSrcTO();
+        DataStoreTO srcStore = srcData.getDataStore();
+        DataTO destData = cmd.getDestTO();
+        NfsTO srcImageStore = (NfsTO) srcStore;
+        TemplateObjectTO destTemplate = (TemplateObjectTO) destData;
+        try {
+            String secPoolUuid = pool.setupSecondaryStorage(srcImageStore.getUrl());
+            String primaryPoolUuid = destData.getDataStore().getUuid();
+            String destPath = config.getAgentOvmRepoPath() + File.separator
+                    + ovmObject.deDash(primaryPoolUuid) + File.separator
+                    + config.getTemplateDir();
+            String sourcePath = config.getAgentSecStoragePath()
+                    + File.separator + secPoolUuid;
+            Linux host = new Linux(c);
+            String destUuid = destTemplate.getUuid();
+            /*
+             * Would love to add dynamic formats (tolower), to also support
+             * VHD and QCOW2, although Ovm3.2 does not have tapdisk2 anymore
+             * so we can forget about that.
+             */
+            /* TODO: add checksumming */
+            String srcFile = sourcePath + File.separator
+                    + srcData.getPath();
+            if (srcData.getPath().endsWith(File.separator)) {
+                srcFile = sourcePath + File.separator + srcData.getPath()
+                        + File.separator + destUuid + ".raw";
+            }
+            String destFile = destPath + File.separator + destUuid + ".raw";
+            LOGGER.debug("CopyFrom: " + srcData.getObjectType() + ","
+                    + srcFile + " to " + destData.getObjectType() + ","
+                    + destFile);
+            host.copyFile(srcFile, destFile);
+            TemplateObjectTO newVol = new TemplateObjectTO();
+            newVol.setUuid(destUuid);
+            // was destfile
+            newVol.setPath(destUuid);
+            newVol.setFormat(ImageFormat.RAW);
+            return new CopyCmdAnswer(newVol);
+        } catch (Ovm3ResourceException e) {
+            String msg = "Error while copying template to primary storage: " + e.getMessage();
+            LOGGER.info(msg);
+            return new CopyCmdAnswer(msg);
+        }
+    }
+    /**
+     * Only copies in case of dest is NfsTO, xenserver also unmounts secstorage
+     */
+    @Override
+    public Answer copyVolumeFromPrimaryToSecondary(CopyCommand cmd) {
+        LOGGER.debug("execute copyVolumeFromPrimaryToSecondary: "+ cmd.getClass());
+        return new Answer(cmd);
+    }
+    /**
+     * dest is VolumeObject, src is a template
+     */
+    @Override
+    public CopyCmdAnswer cloneVolumeFromBaseTemplate(CopyCommand cmd) {
+        LOGGER.debug("execute cloneVolumeFromBaseTemplate: "+ cmd.getClass());
+        try {
+            // src
+            DataTO srcData = cmd.getSrcTO();
+            TemplateObjectTO src = (TemplateObjectTO) srcData;
+            String srcFile = getVirtualDiskPath(src.getUuid(), src.getDataStore().getUuid());
+            srcFile = srcFile.replace(config.getVirtualDiskDir(), config.getTemplateDir());
+
+            DataTO destData = cmd.getDestTO();
+            VolumeObjectTO dest = (VolumeObjectTO) destData;
+            String destFile = getVirtualDiskPath(dest.getUuid(), dest.getDataStore().getUuid());
+            Linux host = new Linux(c);
+            LOGGER.debug("CopyFrom: " + srcData.getObjectType() + ","
+                    + srcFile + " to " + destData.getObjectType() + ","
+                    + destFile);
+            host.copyFile(srcFile, destFile);
+            VolumeObjectTO newVol = new VolumeObjectTO();
+            newVol.setUuid(dest.getUuid());
+            // was destfile
+            newVol.setPath(dest.getUuid());
+            newVol.setFormat(ImageFormat.RAW);
+            return new CopyCmdAnswer(newVol);
+        } catch (Ovm3ResourceException e) {
+            String msg = "Error cloneVolumeFromBaseTemplate: " + e.getMessage();
+            LOGGER.info(msg);
+            return new CopyCmdAnswer(msg);
+        }
+    }
+    /**
+     * createprivatetemplate, also needs template.properties
+     */
+    @Override
+    public Answer createTemplateFromVolume(CopyCommand cmd) {
+        LOGGER.debug("execute createTemplateFromVolume: "+ cmd.getClass());
+        return new Answer(cmd);
+    }
+    /**
+     * Volume to Volume from NfsTO
+     */
+    @Override
+    public Answer copyVolumeFromImageCacheToPrimary(CopyCommand cmd) {
+        LOGGER.debug("execute copyVolumeFromImageCacheToPrimary: "+ cmd.getClass());
+        return new Answer(cmd);
+    }
+    /**
+     * Copies from secondary to secondary
+     */
+    @Override
+    public Answer createTemplateFromSnapshot(CopyCommand cmd) {
+        LOGGER.debug("execute createTemplateFromSnapshot: "+ cmd.getClass());
+        try {
+            // src.getPath contains the uuid of the snapshot.
+            DataTO srcData = cmd.getSrcTO();
+            SnapshotObjectTO srcSnap = (SnapshotObjectTO) srcData;
+            String secPoolUuid = pool.setupSecondaryStorage(srcData.getDataStore().getUrl());
+            String srcFile = config.getAgentSecStoragePath()
+                    + File.separator + secPoolUuid + File.separator
+                    + srcSnap.getPath();
+            // dest
+            DataTO destData = cmd.getDestTO();
+            TemplateObjectTO destTemplate = (TemplateObjectTO) destData;
+            String secPoolUuidTemplate = pool.setupSecondaryStorage(destData.getDataStore().getUrl());
+            String destDir = config.getAgentSecStoragePath()
+                    + File.separator + secPoolUuidTemplate + File.separator
+                    + destTemplate.getPath();
+            String destFile = destDir + File.separator
+                    + destTemplate.getUuid() + ".raw";
+            CloudstackPlugin csp = new CloudstackPlugin(c);
+            csp.ovsMkdirs(destDir);
+
+            Linux host = new Linux(c);
+            host.copyFile(srcFile, destFile);
+            TemplateObjectTO newVol = new TemplateObjectTO();
+            newVol.setUuid(destTemplate.getUuid());
+            newVol.setPath(destTemplate.getUuid());
+            newVol.setFormat(ImageFormat.RAW);
+            return new CopyCmdAnswer(newVol);
+        } catch (Ovm3ResourceException e) {
+            String msg = "Error backupSnapshot: " + e.getMessage();
+            LOGGER.info(msg);
+            return new CopyCmdAnswer(msg);
+        }
+    }
+
+    /**
+     * use the cache, or the normal nfs, also delete the leftovers for us
+     * also contains object store storage in xenserver.
+     */
+    @Override
+    public CopyCmdAnswer backupSnapshot(CopyCommand cmd) {
+        LOGGER.debug("execute backupSnapshot: "+ cmd.getClass());
+        try {
+            DataTO srcData = cmd.getSrcTO();
+            DataTO destData = cmd.getDestTO();
+            SnapshotObjectTO src = (SnapshotObjectTO) srcData;
+            SnapshotObjectTO dest = (SnapshotObjectTO) destData;
+
+            // src.getPath contains the uuid of the snapshot.
+            String srcFile = getVirtualDiskPath(src.getPath(), src.getDataStore().getUuid());
+
+            // destination
+            String storeUrl = dest.getDataStore().getUrl();
+            String secPoolUuid = pool.setupSecondaryStorage(storeUrl);
+            String destDir = config.getAgentSecStoragePath()
+                    + File.separator + secPoolUuid + File.separator
+                    + dest.getPath();
+            String destFile =  destDir + File.separator + src.getPath();
+            destFile = destFile.concat(".raw");
+            // copy
+            Linux host = new Linux(c);
+            CloudstackPlugin csp = new CloudstackPlugin(c);
+            csp.ovsMkdirs(destDir);
+            LOGGER.debug("CopyFrom: " + srcData.getObjectType() + ","
+                    + srcFile + " to " + destData.getObjectType() + ","
+                    + destFile);
+            host.copyFile(srcFile, destFile);
+            StoragePlugin sp = new StoragePlugin(c);
+            sp.storagePluginDestroy(secPoolUuid, srcFile);
+
+            SnapshotObjectTO newSnap = new SnapshotObjectTO();
+            // newSnap.setPath(destFile);
+            // damnit frickin crap, no reference whatsoever... could use parent ?
+            newSnap.setPath(dest.getPath() + File.separator + src.getPath() + ".raw");
+            newSnap.setParentSnapshotPath(null);
+            return new CopyCmdAnswer(newSnap);
+        } catch (Ovm3ResourceException e) {
+            String msg = "Error backupSnapshot: " + e.getMessage();
+            LOGGER.info(msg);
+            return new CopyCmdAnswer(msg);
+        }
+    }
+
+    public Answer execute(CreateObjectCommand cmd) {
+        LOGGER.debug("execute: "+ cmd.getClass());
+        DataTO data = cmd.getData();
+        if (data.getObjectType() == DataObjectType.VOLUME) {
+            return createVolume(cmd);
+        } else if (data.getObjectType() == DataObjectType.SNAPSHOT) {
+            return createSnapshot(cmd);
+        } else if (data.getObjectType() == DataObjectType.TEMPLATE) {
+            LOGGER.debug("Template object creation not supported.");
+        }
+        return new CreateObjectAnswer(data.getObjectType()
+                + " object creation not supported");
+    }
+    /**
+     * Attach an iso
+     */
+    @Override
+    public AttachAnswer attachIso(AttachCommand cmd) {
+        LOGGER.debug("execute attachIso: "+ cmd.getClass());
+        String vmName = cmd.getVmName();
+        DiskTO disk = cmd.getDisk();
+        return attachDetach(cmd, vmName, disk, true);
+    }
+    /**
+     * Detach an iso
+     */
+    @Override
+    public AttachAnswer dettachIso(DettachCommand cmd) {
+        LOGGER.debug("execute dettachIso: "+ cmd.getClass());
+        String vmName = cmd.getVmName();
+        DiskTO disk = cmd.getDisk();
+        return attachDetach(cmd, vmName, disk, false);
+    }
+
+    /**
+     * Iso specific path return.
+     * @param disk
+     * @return
+     * @throws Ovm3ResourceException
+     */
+    private String getIsoPath(DiskTO disk) throws Ovm3ResourceException {
+        TemplateObjectTO isoTO = (TemplateObjectTO) disk.getData();
+        DataStoreTO store = isoTO.getDataStore();
+        NfsTO nfsStore = (NfsTO) store;
+        String secPoolUuid = pool.setupSecondaryStorage(nfsStore.getUrl());
+        return config.getAgentSecStoragePath() + File.separator
+                + secPoolUuid + File.separator + isoTO.getPath();
+    }
+
+    /**
+     * Returns the disk path
+     * @param diskUuid
+     * @return
+     * @throws Ovm3ResourceException
+     */
+    public String getVirtualDiskPath(String diskUuid, String storeUuid) throws Ovm3ResourceException {
+        String d = config.getAgentOvmRepoPath() +
+                File.separator +
+                ovmObject.deDash(storeUuid) +
+                File.separator +
+                config.getVirtualDiskDir() +
+                File.separator +
+                diskUuid;
+        if (!d.endsWith(".raw")) {
+            d = d.concat(".raw");
+        }
+        return d;
+    }
+    public String getVirtualDiskPath(DiskTO disk, String storeUuid) throws Ovm3ResourceException {
+        return getVirtualDiskPath(disk.getPath(), storeUuid);
+    }
+
+    /**
+     * Generic disk attach/detach.
+     * @param cmd
+     * @param vmName
+     * @param disk
+     * @param isAttach
+     * @return
+     */
+    private AttachAnswer attachDetach(Command cmd, String vmName, DiskTO disk,
+            boolean isAttach) {
+        Xen xen = new Xen(c);
+        String doThis = (isAttach) ? "Attach" : "Dettach";
+        LOGGER.debug(doThis + " volume type " + disk.getType() + "  " + vmName);
+        String msg = "";
+        String path = "";
+        try {
+            Xen.Vm vm = xen.getVmConfig(vmName);
+            /* check running */
+            if (vm == null) {
+                msg = doThis + " can't find VM " + vmName;
+                LOGGER.debug(msg);
+                return new AttachAnswer(msg);
+            }
+            if (disk.getType() == Volume.Type.ISO) {
+                path = getIsoPath(disk);
+            } else if (disk.getType() == Volume.Type.DATADISK) {
+                path = getVirtualDiskPath(disk, vm.getPrimaryPoolUuid());
+            }
+            if ("".equals(path)) {
+                msg = doThis + " can't do anything with an empty path.";
+                LOGGER.debug(msg);
+                return new AttachAnswer(msg);
+            }
+            if (isAttach) {
+                if (disk.getType() == Volume.Type.ISO) {
+                    vm.addIso(path);
+                } else {
+                    vm.addDataDisk(path);
+                }
+            } else {
+                if (!vm.removeDisk(path)) {
+                    msg = doThis + " failed for " + vmName + disk.getType()
+                            + "  was not attached " + path;
+                    LOGGER.debug(msg);
+                    return new AttachAnswer(msg);
+                }
+            }
+            xen.configureVm(ovmObject.deDash(vm.getPrimaryPoolUuid()),
+                    vm.getVmUuid());
+            return new AttachAnswer(disk);
+        } catch (Ovm3ResourceException e) {
+            msg = doThis + " failed for " + vmName + " " + e.getMessage();
+            LOGGER.warn(msg, e);
+            return new AttachAnswer(msg);
+        }
+    }
+    /**
+     * Attach a volume
+     */
+    @Override
+    public AttachAnswer attachVolume(AttachCommand cmd) {
+        LOGGER.debug("execute attachVolume: "+ cmd.getClass());
+        String vmName = cmd.getVmName();
+        DiskTO disk = cmd.getDisk();
+        return attachDetach(cmd, vmName, disk, true);
+    }
+    /**
+     * Detach a volume
+     */
+    @Override
+    public AttachAnswer dettachVolume(DettachCommand cmd) {
+        LOGGER.debug("execute dettachVolume: "+ cmd.getClass());
+        String vmName = cmd.getVmName();
+        DiskTO disk = cmd.getDisk();
+        return attachDetach(cmd, vmName, disk, false);
+    }
+
+    /**
+     * Creates a volume, just a normal empty volume.
+     */
+    @Override
+    public Answer createVolume(CreateObjectCommand cmd) {
+        LOGGER.debug("execute createVolume: "+ cmd.getClass());
+        DataTO data = cmd.getData();
+        VolumeObjectTO volume = (VolumeObjectTO) data;
+        try {
+            /*
+             * public Boolean storagePluginCreate(String uuid, String ssuuid,
+             * String host, String file, Integer size)
+             */
+            String poolUuid = data.getDataStore().getUuid();
+            String storeUrl = data.getDataStore().getUrl();
+            URI uri = new URI(storeUrl);
+            String host = uri.getHost();
+            String file = getVirtualDiskPath(volume.getUuid(), poolUuid);
+            Long size = volume.getSize();
+            StoragePlugin sp = new StoragePlugin(c);
+            FileProperties fp = sp.storagePluginCreate(poolUuid, host, file,
+                    size, false);
+            if (!fp.getName().equals(file)) {
+                return new CreateObjectAnswer("Filename mismatch: "
+                        + fp.getName() + " != " + file);
+            }
+            VolumeObjectTO newVol = new VolumeObjectTO();
+            newVol.setName(volume.getName());
+            newVol.setSize(fp.getSize());
+            newVol.setPath(volume.getUuid());
+            return new CreateObjectAnswer(newVol);
+        } catch (Ovm3ResourceException | URISyntaxException e) {
+            LOGGER.info("Volume creation failed: " + e.toString(), e);
+            return new CreateObjectAnswer(e.toString());
+        }
+    }
+
+    /**
+     * Creates a snapshot from a volume, but only if the VM is stopped.
+     * This due qemu not being able to snap raw volumes.
+     *
+     * if stopped yes, if running ... no, unless we have ocfs2 when
+     * using raw partitions (file:) if using tap:aio we cloud...
+     * The "ancient" way:
+     * We do however follow the "two stage" approach, of "snap"
+     * on primary first, with the create object... and then
+     * backup the snapshot with the copycmd....
+     * (should transfer to createSnapshot, backupSnapshot)
+     */
+    @Override
+    public Answer createSnapshot(CreateObjectCommand cmd) {
+        LOGGER.debug("execute createSnapshot: "+ cmd.getClass());
+        DataTO data = cmd.getData();
+        Xen xen = new Xen(c);
+        SnapshotObjectTO snap = (SnapshotObjectTO) data;
+        VolumeObjectTO vol = snap.getVolume();
+        try {
+            Xen.Vm vm = xen.getVmConfig(snap.getVmName());
+            if (vm != null) {
+                return new CreateObjectAnswer(
+                        "Snapshot object creation not supported for running VMs."
+                                + snap.getVmName());
+            }
+            Linux host = new Linux(c);
+            String uuid = host.newUuid();
+            /* for root volumes this works... */
+            String src = vol.getPath() + File.separator + vol.getUuid()
+                    + ".raw";
+            String dest = vol.getPath() + File.separator + uuid + ".raw";
+            /* seems that sometimes the path is already contains a file
+             * in case, we just replace it.... (Seems to happen if not ROOT)
+             */
+            if (vol.getPath().contains(vol.getUuid())) {
+                src = getVirtualDiskPath(vol.getUuid(),data.getDataStore().getUuid());
+                dest = src.replace(vol.getUuid(), uuid);
+            }
+            LOGGER.debug("Snapshot " + src + " to " + dest);
+            host.copyFile(src, dest);
+            SnapshotObjectTO nsnap = new SnapshotObjectTO();
+            // nsnap.setPath(dest);
+            // move to something that looks the same as xenserver.
+            nsnap.setPath(uuid);
+            return new CreateObjectAnswer(nsnap);
+        } catch (Ovm3ResourceException e) {
+            return new CreateObjectAnswer(
+                    "Snapshot object creation failed. " + e.getMessage());
+        }
+    }
+
+    @Override
+    public Answer deleteVolume(DeleteCommand cmd) {
+        LOGGER.debug("execute deleteVolume: "+ cmd.getClass());
+        DataTO data = cmd.getData();
+        VolumeObjectTO volume = (VolumeObjectTO) data;
+        try {
+            String poolUuid = data.getDataStore().getUuid();
+            String uuid = volume.getUuid();
+            String path = getVirtualDiskPath(uuid, poolUuid);
+            StoragePlugin sp = new StoragePlugin(c);
+            sp.storagePluginDestroy(poolUuid, path);
+            LOGGER.debug("Volume deletion success: " + path);
+        } catch (Ovm3ResourceException e) {
+            LOGGER.info("Volume deletion failed: " + e.toString(), e);
+            return new CreateObjectAnswer(e.toString());
+        }
+        return new Answer(cmd);
+    }
+
+    /*
+     * CopyVolumeCommand gets the storage_pool should use that for
+     * bumper bowling.
+     */
+    public CopyVolumeAnswer execute(CopyVolumeCommand cmd) {
+        LOGGER.debug("execute: "+ cmd.getClass());
+        String volumePath = cmd.getVolumePath();
+        /* is a repository */
+        String secondaryStorageURL = cmd.getSecondaryStorageURL();
+        int wait = cmd.getWait();
+        if (wait == 0) {
+            wait = 7200;
+        }
+
+        try {
+            Linux host = new Linux(c);
+
+            /* to secondary storage */
+            if (cmd.toSecondaryStorage()) {
+                LOGGER.debug("Copy to  secondary storage " + volumePath
+                        + " to " + secondaryStorageURL);
+                host.copyFile(volumePath, secondaryStorageURL);
+                /* from secondary storage */
+            } else {
+                LOGGER.debug("Copy from secondary storage "
+                        + secondaryStorageURL + " to " + volumePath);
+                host.copyFile(secondaryStorageURL, volumePath);
+            }
+            /* check the truth of this */
+            return new CopyVolumeAnswer(cmd, true, null, null, null);
+        } catch (Ovm3ResourceException e) {
+            LOGGER.debug("Copy volume failed", e);
+            return new CopyVolumeAnswer(cmd, false, e.getMessage(), null, null);
+        }
+    }
+
+    /* Destroy a volume (image) */
+    public Answer execute(DestroyCommand cmd) {
+        LOGGER.debug("execute: "+ cmd.getClass());
+        VolumeTO vol = cmd.getVolume();
+        String vmName = cmd.getVmName();
+        try {
+            StoragePlugin store = new StoragePlugin(c);
+            store.storagePluginDestroy(vol.getPoolUuid(), vol.getPath());
+            return new Answer(cmd, true, "Success");
+        } catch (Ovm3ResourceException e) {
+            LOGGER.debug("Destroy volume " + vol.getName() + " failed for "
+                    + vmName + " ", e);
+            return new Answer(cmd, false, e.getMessage());
+        }
+    }
+
+    /* check if a VM is running should be added */
+    public CreatePrivateTemplateAnswer execute(
+            final CreatePrivateTemplateFromVolumeCommand cmd) {
+        LOGGER.debug("execute: "+ cmd.getClass());
+        String volumePath = cmd.getVolumePath();
+        Long accountId = cmd.getAccountId();
+        Long templateId = cmd.getTemplateId();
+        int wait = cmd.getWait();
+        if (wait == 0) {
+            /* Defaut timeout 2 hours */
+            wait = 7200;
+        }
+
+        try {
+            /* missing uuid */
+            String installPath = config.getAgentOvmRepoPath() + File.separator
+                    + config.getTemplateDir() + File.separator
+                    + accountId + File.separator + templateId;
+            Linux host = new Linux(c);
+            host.copyFile(volumePath, installPath);
+            return new CreatePrivateTemplateAnswer(cmd, true, installPath);
+        } catch (Exception e) {
+            LOGGER.debug("Create template failed", e);
+            return new CreatePrivateTemplateAnswer(cmd, false, e.getMessage());
+        }
+    }
+
+    /**
+     * SnapshotObjectTO secondary to VolumeObjectTO primary in xenserver,
+     */
+    @Override
+    public Answer createVolumeFromSnapshot(CopyCommand cmd) {
+        LOGGER.debug("execute createVolumeFromSnapshot: "+ cmd.getClass());
+        try {
+            DataTO srcData = cmd.getSrcTO();
+            DataStoreTO srcStore = srcData.getDataStore();
+            NfsTO srcImageStore = (NfsTO) srcStore;
+
+            // source, should contain snap dir/filename
+            SnapshotObjectTO srcSnap = (SnapshotObjectTO) srcData;
+            String secPoolUuid = pool.setupSecondaryStorage(srcImageStore.getUrl());
+            String srcFile = config.getAgentSecStoragePath()
+                    + File.separator + secPoolUuid + File.separator
+                    + srcSnap.getPath();
+
+            // dest
+            DataTO destData = cmd.getDestTO();
+            VolumeObjectTO destVol = (VolumeObjectTO) destData;
+            String primaryPoolUuid = destData.getDataStore().getUuid();
+            String destFile = getVirtualDiskPath(destVol.getUuid(), ovmObject.deDash(primaryPoolUuid));
+
+            Linux host = new Linux(c);
+            host.copyFile(srcFile, destFile);
+
+            VolumeObjectTO newVol = new VolumeObjectTO();
+            newVol.setUuid(destVol.getUuid());
+            // newVol.setPath(destFile);
+            newVol.setPath(destVol.getUuid());
+            newVol.setFormat(ImageFormat.RAW);
+            return new CopyCmdAnswer(newVol);
+            /* we assume the cache for templates is local */
+        } catch (Ovm3ResourceException e) {
+            LOGGER.debug("Failed to createVolumeFromSnapshot: ", e);
+            return new CopyCmdAnswer(e.toString());
+        }
+    }
+
+    /**
+     * Is not used in normal operation, the SSVM takes care of this.
+     */
+    @Override
+    public Answer deleteSnapshot(DeleteCommand cmd) {
+        LOGGER.debug("execute deleteSnapshot: "+ cmd.getClass());
+        DataTO data = cmd.getData();
+        SnapshotObjectTO snap = (SnapshotObjectTO) data;
+        String storeUrl = data.getDataStore().getUrl();
+        String snapUuid = snap.getPath();
+        try {
+            // snapshots/accountid/volumeid
+            String secPoolUuid = pool.setupSecondaryStorage(storeUrl);
+            String filePath = config.getAgentSecStoragePath()
+                    + File.separator + secPoolUuid + File.separator
+                    + snapUuid + ".raw";
+            StoragePlugin sp = new StoragePlugin(c);
+            sp.storagePluginDestroy(secPoolUuid, filePath);
+            LOGGER.debug("Snapshot deletion success: " + filePath);
+            return new Answer(cmd, true, "Deleted Snapshot " + filePath);
+        } catch (Ovm3ResourceException e) {
+            LOGGER.info("Snapshot deletion failed: " + e.toString(), e);
+            return new CreateObjectAnswer(e.toString());
+        }
+    }
+    /**
+     * SR scan in xenserver
+     */
+    @Override
+    public Answer introduceObject(IntroduceObjectCmd cmd) {
+        LOGGER.debug("execute introduceObject: "+ cmd.getClass());
+        return new Answer(cmd, false, "not implemented yet");
+    }
+    /**
+     * used as unmount for VDIs in xenserver
+     */
+    @Override
+    public Answer forgetObject(ForgetObjectCmd cmd) {
+        LOGGER.debug("execute forgetObject: "+ cmd.getClass());
+        return new Answer(cmd, false, "not implemented yet");
+    }
+
+    /**
+     * make sure both mounts are there, snapshot source image
+     * copy snap to dest image, remove source snap and unmount
+     * iSCSI?
+     */
+    @Override
+    public Answer snapshotAndCopy(SnapshotAndCopyCommand cmd) {
+        LOGGER.debug("execute snapshotAndCopy: "+ cmd.getClass());
+        return new SnapshotAndCopyAnswer("not implemented yet");
+    }
+
+    /**
+     * Attach disks
+     * @param cmd
+     * @return
+     */
+    public Answer execute(AttachCommand cmd) {
+        LOGGER.debug("execute: "+ cmd.getClass());
+        String vmName = cmd.getVmName();
+        DiskTO disk = cmd.getDisk();
+        return attachDetach(cmd, vmName, disk, true);
+    }
+
+    /**
+     * Detach disks, calls a middle man which calls attachDetach for volumes.
+     * @param cmd
+     * @return
+     */
+    public Answer execute(DettachCommand cmd) {
+        LOGGER.debug("execute: "+ cmd.getClass());
+        String vmName = cmd.getVmName();
+        DiskTO disk = cmd.getDisk();
+        return attachDetach(cmd, vmName, disk, false);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/c27c6943/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3VirtualRoutingResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3VirtualRoutingResource.java b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3VirtualRoutingResource.java
new file mode 100644
index 0000000..52409b1
--- /dev/null
+++ b/plugins/hypervisors/ovm3/src/main/java/com/cloud/hypervisor/ovm3/resources/Ovm3VirtualRoutingResource.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * 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 com.cloud.hypervisor.ovm3.resources;
+
+import javax.ejb.Local;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.api.SetupGuestNetworkCommand;
+import com.cloud.agent.api.routing.IpAssocCommand;
+import com.cloud.agent.api.routing.IpAssocVpcCommand;
+import com.cloud.agent.api.routing.NetworkElementCommand;
+import com.cloud.agent.api.routing.SetSourceNatCommand;
+import com.cloud.agent.api.to.IpAddressTO;
+import com.cloud.agent.resource.virtualnetwork.VirtualRouterDeployer;
+import com.cloud.hypervisor.ovm3.objects.CloudstackPlugin;
+import com.cloud.hypervisor.ovm3.objects.Connection;
+import com.cloud.hypervisor.ovm3.objects.Xen;
+import com.cloud.utils.ExecutionResult;
+
+@Local(value = VirtualRouterDeployer.class)
+public class Ovm3VirtualRoutingResource implements VirtualRouterDeployer {
+    private final Logger logger = Logger
+            .getLogger(Ovm3VirtualRoutingResource.class);
+    private String domRCloudPath = "/opt/cloud/bin/";
+    private int vrTimeout = 600;
+    private Connection c;
+    private String agentName;
+    public Ovm3VirtualRoutingResource() {
+    }
+    public Ovm3VirtualRoutingResource(Connection conn) {
+        c = conn;
+        agentName=c.getIp();
+    }
+    public void setConnection(Connection conn) {
+        c = conn;
+    }
+    @Override
+    public ExecutionResult executeInVR(String routerIp, String script,
+            String args) {
+        return executeInVR(routerIp, script, args, vrTimeout);
+    }
+
+    @Override
+    public ExecutionResult executeInVR(String routerIp, String script,
+            String args, int timeout) {
+        if (!script.contains(domRCloudPath)) {
+            script = domRCloudPath + "/" + script;
+        }
+        String cmd = script + " " + args;
+        logger.debug("executeInVR via " + agentName + " on " + routerIp + ": "
+                + cmd);
+        try {
+            CloudstackPlugin cSp = new CloudstackPlugin(c);
+            CloudstackPlugin.ReturnCode result;
+            result = cSp.domrExec(routerIp, cmd);
+            return new ExecutionResult(result.getRc(), result.getStdOut());
+        } catch (Exception e) {
+            logger.error("executeInVR FAILED via " + agentName + " on "
+                    + routerIp + ":" + cmd + ", " + e.getMessage(), e);
+        }
+        return new ExecutionResult(false, "");
+    }
+
+    @Override
+    public ExecutionResult createFileInVR(String routerIp, String path,
+            String filename, String content) {
+        String error = null;
+        logger.debug("createFileInVR via " + agentName + " on " + routerIp
+                + ": " + path + "/" + filename + ", content: " + content);
+        try {
+            CloudstackPlugin cSp = new CloudstackPlugin(c);
+            boolean result = cSp.ovsDomrUploadFile(routerIp, path, filename,
+                    content);
+            return new ExecutionResult(result, "");
+        } catch (Exception e) {
+            error = e.getMessage();
+            logger.warn(
+                    "createFileInVR failed for " + path + "/" + filename
+                            + " in VR " + routerIp + " via " + agentName + ": "
+                            + error, e);
+        }
+        return new ExecutionResult(error == null, error);
+    }
+
+    @Override
+    public ExecutionResult prepareCommand(NetworkElementCommand cmd) {
+        // Update IP used to access router
+        cmd.setRouterAccessIp(cmd
+                .getAccessDetail(NetworkElementCommand.ROUTER_IP));
+        assert cmd.getRouterAccessIp() != null;
+
+        if (cmd instanceof IpAssocVpcCommand) {
+            return prepareNetworkElementCommand((IpAssocVpcCommand) cmd);
+        } else if (cmd instanceof IpAssocCommand) {
+            return prepareNetworkElementCommand((IpAssocCommand) cmd);
+        } else if (cmd instanceof SetupGuestNetworkCommand) {
+            return prepareNetworkElementCommand((SetupGuestNetworkCommand) cmd);
+        } else if (cmd instanceof SetSourceNatCommand) {
+            return prepareNetworkElementCommand((SetSourceNatCommand) cmd);
+        }
+        return new ExecutionResult(true, null);
+    }
+
+    @Override
+    public ExecutionResult cleanupCommand(NetworkElementCommand cmd) {
+        if (cmd instanceof IpAssocCommand
+                && !(cmd instanceof IpAssocVpcCommand)) {
+            return cleanupNetworkElementCommand((IpAssocCommand) cmd);
+        }
+        return new ExecutionResult(true, null);
+    }
+
+    private ExecutionResult cleanupNetworkElementCommand(IpAssocCommand cmd) {
+        return new ExecutionResult(true, null);
+    }
+
+    private ExecutionResult prepareNetworkElementCommand(
+            SetupGuestNetworkCommand cmd) {
+        return new ExecutionResult(true, null);
+    }
+
+    private ExecutionResult prepareNetworkElementCommand(IpAssocVpcCommand cmd) {
+        return prepNetBoth(cmd
+                .getAccessDetail(NetworkElementCommand.ROUTER_NAME),
+                cmd.getIpAddresses(), "IpAssocVpcCommand");
+    }
+
+    private ExecutionResult prepareNetworkElementCommand(SetSourceNatCommand cmd) {
+        return new ExecutionResult(true, null);
+    }
+
+    private ExecutionResult prepareNetworkElementCommand(IpAssocCommand cmd) {
+        return prepNetBoth(cmd
+                .getAccessDetail(NetworkElementCommand.ROUTER_NAME),
+                cmd.getIpAddresses(), "IpAssocCommand");
+    }
+
+    private ExecutionResult prepNetBoth(String routerName, IpAddressTO[] ips, String type) {
+        Xen xen = new Xen(c);
+        try {
+            Xen.Vm vm = xen.getVmConfig(routerName);
+            for (IpAddressTO ip : ips) {
+                Integer devId = vm.getVifIdByMac(ip.getVifMacAddress());
+                if (devId < 0 && "IpAssocVpcCommand".equals(type)) {
+                    String msg = "No valid Nic devId found for " + vm.getVmName()
+                            + " with " + ip.getVifMacAddress();
+                    logger.error(msg);
+                    return new ExecutionResult(false, msg);
+                } else if (devId < 0 && "IpAssocCommand".equals(type)) {
+                    // vm.get
+                    String msg = "No valid Nic devId found for " + vm.getVmName()
+                            + " with " + ip.getVifMacAddress() + " "
+                            + " Ignoring for now (routervm)";
+                    logger.debug(msg);
+                    devId=2;
+                }
+                ip.setNicDevId(devId);
+            }
+        } catch (Exception e) {
+            String msg = type + " failure on applying one ip due to exception:  " + e;
+            logger.error(msg);
+            return new ExecutionResult(false, msg);
+        }
+        return new ExecutionResult(true, null);
+    }
+}