Repository: cloudstack
Updated Branches:
  refs/heads/master c10f8a10e -> 1de0cb709

restore barematel work after merge


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/1de0cb70
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/1de0cb70
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/1de0cb70

Branch: refs/heads/master
Commit: 1de0cb709483090926cbef48d1d677f618f9c17f
Parents: c10f8a1
Author: Daan Hoogland <d...@onecht.net>
Authored: Fri Oct 17 10:24:01 2014 +0200
Committer: Daan Hoogland <d...@onecht.net>
Committed: Fri Oct 17 10:24:01 2014 +0200

----------------------------------------------------------------------
 api/src/com/cloud/event/EventTypes.java         |   1 +
 .../PrepareKickstartPxeServerCommand.java       |  84 ------
 .../core/spring-baremetal-core-context.xml      |   8 +-
 .../baremetal/manager/BaremetalManager.java     |   3 +
 .../baremetal/manager/BaremetalManagerImpl.java |   3 +
 .../baremetal/manager/BaremetalVlanManager.java |   1 +
 .../manager/BaremetalVlanManagerImpl.java       |   7 +-
 .../networkservice/BareMetalResourceBase.java   |  47 ++-
 .../BaremetalKickStartPxeResource.java          |   1 -
 .../BaremetalKickStartServiceImpl.java          |  12 +-
 .../networkservice/BaremetalPxeElement.java     |   5 +-
 .../Force10BaremetalSwitchBackend.java          | 120 ++++++--
 .../PrepareKickstartPxeServerCommand.java       |  83 ++++++
 .../BaremetalProvisionDoneNotificationCmd.java  |  87 ++++++
 server/src/com/cloud/configuration/Config.java  |  36 ++-
 .../deploy/DeploymentPlanningManagerImpl.java   |  11 +-
 .../VirtualNetworkApplianceManagerImpl.java     |   2 +
 .../com/cloud/resource/ResourceManagerImpl.java |  15 -
 .../com/cloud/storage/VolumeApiServiceImpl.java |  12 +-
 .../cloud/storage/VolumeApiServiceImplTest.java |  24 +-
 .../patches/debian/config/etc/dnsmasq.conf.tmpl |   6 +-
 .../config/opt/cloud/bin/baremetal_snat.sh      |  21 +-
 .../debian/config/opt/cloud/bin/prepare_pxe.sh  |  28 +-
 .../component/test_deploy_vgpu_vm.py            | 291 +------------------
 .../com/cloud/utils/xmlobject/XmlObject.java    |  15 +-
 .../cloud/utils/xmlobject/XmlObjectParser.java  |  22 +-
 .../cloud/utils/xmlobject/TestXmlObject.java    |   5 +
 27 files changed, 462 insertions(+), 488 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/api/src/com/cloud/event/EventTypes.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/event/EventTypes.java 
b/api/src/com/cloud/event/EventTypes.java
index 7477152..3a1d58a 100755
--- a/api/src/com/cloud/event/EventTypes.java
+++ b/api/src/com/cloud/event/EventTypes.java
@@ -454,6 +454,7 @@ public class EventTypes {
     public static final String EVENT_BAREMETAL_PXE_SERVER_ADD = 
"PHYSICAL.PXE.ADD";
     public static final String EVENT_BAREMETAL_PXE_SERVER_DELETE = 
"PHYSICAL.PXE.DELETE";
     public static final String EVENT_BAREMETAL_RCT_ADD = "BAREMETAL.RCT.ADD";
+    public static final String EVENT_BAREMETAL_PROVISION_DONE = 
"BAREMETAL.PROVISION.DONE";
 
     public static final String EVENT_AFFINITY_GROUP_CREATE = "AG.CREATE";
     public static final String EVENT_AFFINITY_GROUP_DELETE = "AG.DELETE";

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/core/src/com/cloud/agent/api/baremetal/PrepareKickstartPxeServerCommand.java
----------------------------------------------------------------------
diff --git 
a/core/src/com/cloud/agent/api/baremetal/PrepareKickstartPxeServerCommand.java 
b/core/src/com/cloud/agent/api/baremetal/PrepareKickstartPxeServerCommand.java
deleted file mode 100755
index b8fb5d0..0000000
--- 
a/core/src/com/cloud/agent/api/baremetal/PrepareKickstartPxeServerCommand.java
+++ /dev/null
@@ -1,84 +0,0 @@
-//
-// 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.agent.api.baremetal;
-
-import com.cloud.agent.api.Command;
-
-public class PrepareKickstartPxeServerCommand extends Command {
-    private String ksFile;
-    private String templateUuid;
-    private String mac;
-    private String ksDevice;
-    private String kernel;
-    private String initrd;
-
-    @Override
-    public boolean executeInSequence() {
-        return true;
-    }
-
-    public String getKsFile() {
-        return ksFile;
-    }
-
-    public void setKsFile(String ksFile) {
-        this.ksFile = ksFile;
-    }
-
-    public String getKernel() {
-        return kernel;
-    }
-
-    public void setKernel(String kernel) {
-        this.kernel = kernel;
-    }
-
-    public String getInitrd() {
-        return initrd;
-    }
-
-    public void setInitrd(String initrd) {
-        this.initrd = initrd;
-    }
-
-    public String getTemplateUuid() {
-        return templateUuid;
-    }
-
-    public void setTemplateUuid(String templateUuid) {
-        this.templateUuid = templateUuid;
-    }
-
-    public String getMac() {
-        return mac;
-    }
-
-    public void setMac(String mac) {
-        this.mac = mac;
-    }
-
-    public String getKsDevice() {
-        return ksDevice;
-    }
-
-    public void setKsDevice(String ksDevice) {
-        this.ksDevice = ksDevice;
-    }
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml
 
b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml
index ae28efa..a153e7f 100755
--- 
a/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml
+++ 
b/plugins/hypervisors/baremetal/resources/META-INF/cloudstack/core/spring-baremetal-core-context.xml
@@ -28,7 +28,13 @@
                       >
 
     <bean id="BaremetalManager" 
class="com.cloud.baremetal.manager.BaremetalManagerImpl" />
-    <bean id="BaremetalVlanManager" 
class="com.cloud.baremetal.manager.BaremetalVlanManagerImpl" />
+    <bean id="BaremetalVlanManager" 
class="com.cloud.baremetal.manager.BaremetalVlanManagerImpl" >
+       <property name="backends">
+           <map>
+               <entry key="Force10" value-ref="Force10BaremetalSwitchBackend"/>
+           </map>
+       </property>
+    </bean>
     <bean id="Force10BaremetalSwitchBackend" 
class="com.cloud.baremetal.networkservice.Force10BaremetalSwitchBackend" />
 
     <bean id="BaremetalKickStartPxeService"

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManager.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManager.java
 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManager.java
index 5db29d2..629153a 100755
--- 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManager.java
+++ 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManager.java
@@ -20,9 +20,12 @@ package com.cloud.baremetal.manager;
 
 import com.cloud.utils.component.Manager;
 import com.cloud.utils.component.PluggableService;
+import org.apache.cloudstack.api.BaremetalProvisionDoneNotificationCmd;
 
 public interface BaremetalManager extends Manager, PluggableService {
     public static final String EchoSecurityGroupAgent = 
"EchoSecurityGroupAgent";
     public static final String ExternalBaremetalSystemUrl = 
"ExternalBaremetalSystemUrl";
     public static final String DO_PXE = "doPxe";
+
+    void notifyProvisionDone(BaremetalProvisionDoneNotificationCmd cmd);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManagerImpl.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManagerImpl.java
 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManagerImpl.java
index 076a1bc..f826ae9 100755
--- 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManagerImpl.java
+++ 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalManagerImpl.java
@@ -52,6 +52,8 @@ public class BaremetalManagerImpl extends ManagerBase 
implements BaremetalManage
 
     @Inject
     protected HostDao _hostDao;
+    @Inject
+    protected VMInstanceDao vmDao;
 
     @Override
     public boolean configure(String name, Map<String, Object> params) throws 
ConfigurationException {
@@ -116,6 +118,7 @@ public class BaremetalManagerImpl extends ManagerBase 
implements BaremetalManage
     public List<Class<?>> getCommands() {
         List<Class<?>> cmds = new ArrayList<Class<?>>();
         cmds.add(AddBaremetalHostCmd.class);
+        cmds.add(BaremetalProvisionDoneNotificationCmd.class);
         return cmds;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManager.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManager.java
 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManager.java
index 09215ea..b2a1be9 100755
--- 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManager.java
+++ 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManager.java
@@ -18,6 +18,7 @@
 package com.cloud.baremetal.manager;
 
 import com.cloud.baremetal.networkservice.BaremetalRctResponse;
+import com.cloud.baremetal.networkservice.BaremetalSwitchBackend;
 import com.cloud.deploy.DeployDestination;
 import com.cloud.network.Network;
 import com.cloud.utils.component.Manager;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManagerImpl.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManagerImpl.java
 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManagerImpl.java
index 3728a31..c8473b6 100755
--- 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManagerImpl.java
+++ 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/manager/BaremetalVlanManagerImpl.java
@@ -48,7 +48,6 @@ import javax.inject.Inject;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
@@ -70,13 +69,17 @@ public class BaremetalVlanManagerImpl extends ManagerBase 
implements BaremetalVl
     @Inject
     private AccountManager acntMgr;
 
-    private Map<String, BaremetalSwitchBackend> backends = new HashMap<>();
+    private Map<String, BaremetalSwitchBackend> backends;
 
     private class RackPair {
         BaremetalRct.Rack rack;
         BaremetalRct.HostEntry host;
     }
 
+    public void setBackends(Map<String, BaremetalSwitchBackend> backends) {
+        this.backends = backends;
+    }
+
     @Override
     public BaremetalRctResponse addRct(AddBaremetalRctCmd cmd) {
         try {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java
 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java
index 8ed50ef..ab863dc 100755
--- 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java
+++ 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalResourceBase.java
@@ -59,12 +59,15 @@ import com.cloud.host.Host.Type;
 import com.cloud.hypervisor.Hypervisor;
 import com.cloud.resource.ServerResource;
 import com.cloud.utils.component.ManagerBase;
+import com.cloud.utils.db.QueryBuilder;
+import com.cloud.utils.db.SearchCriteria;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.script.OutputInterpreter;
 import com.cloud.utils.script.Script;
 import com.cloud.utils.script.Script2;
 import com.cloud.utils.script.Script2.ParamType;
 import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VirtualMachine.PowerState;
 import com.cloud.vm.dao.VMInstanceDao;
 import org.apache.cloudstack.api.ApiConstants;
@@ -107,6 +110,8 @@ public class BareMetalResourceBase extends ManagerBase 
implements ServerResource
     protected Script2 _bootOrRebootCommand;
     protected String _vmName;
     protected int ipmiRetryTimes = 5;
+    protected boolean provisionDoneNotificationOn = false;
+    protected int isProvisionDoneNotificationTimeout = 1800;
 
     protected ConfigurationDao configDao;
     protected VMInstanceDao vmDao;
@@ -181,6 +186,13 @@ public class BareMetalResourceBase extends ManagerBase 
implements ServerResource
             s_logger.debug(e.getMessage(), e);
         }
 
+        try {
+            provisionDoneNotificationOn = 
Boolean.valueOf(configDao.getValue(Config.BaremetalProvisionDoneNotificationEnabled.key()));
+            isProvisionDoneNotificationTimeout = 
Integer.valueOf(configDao.getValue(Config.BaremetalProvisionDoneNotificationTimeout.key()));
+        } catch (Exception e) {
+            s_logger.debug(e.getMessage(), e);
+        }
+
         String injectScript = "scripts/util/ipmi.py";
         String scriptPath = Script.findScript("", injectScript);
         if (scriptPath == null) {
@@ -392,7 +404,7 @@ public class BareMetalResourceBase extends ManagerBase 
implements ServerResource
                 VMInstanceVO vm = vms.get(0);
                 SecurityGroupHttpClient client = new SecurityGroupHttpClient();
                 HashMap<String, Pair<Long, Long>> nwGrpStates = 
client.sync(vm.getInstanceName(), vm.getId(), vm.getPrivateIpAddress());
-                return new PingRoutingWithNwGroupsCommand(getType(), id, 
getHostVmStateReport(), nwGrpStates);
+                return new PingRoutingWithNwGroupsCommand(getType(), id, null, 
nwGrpStates);
             }
         } else {
             return new PingRoutingCommand(getType(), id, null);
@@ -581,6 +593,39 @@ public class BareMetalResourceBase extends ManagerBase 
implements ServerResource
             }
         }
 
+        if (provisionDoneNotificationOn) {
+            QueryBuilder<VMInstanceVO> q = 
QueryBuilder.create(VMInstanceVO.class);
+            q.and(q.entity().getInstanceName(), SearchCriteria.Op.EQ, 
vm.getName());
+            VMInstanceVO vmvo = q.find();
+
+            if (vmvo.getLastHostId() == null) {
+                // this is new created vm
+                long timeout = System.currentTimeMillis() + 
TimeUnit.SECONDS.toMillis(isProvisionDoneNotificationTimeout);
+                while (timeout > System.currentTimeMillis()) {
+                    try {
+                        TimeUnit.SECONDS.sleep(5);
+                    } catch (InterruptedException e) {
+                        s_logger.warn(e.getMessage(), e);
+                    }
+
+                    q = QueryBuilder.create(VMInstanceVO.class);
+                    q.and(q.entity().getInstanceName(), SearchCriteria.Op.EQ, 
vm.getName());
+                    vmvo = q.find();
+                    if (vmvo == null) {
+                        return new StartAnswer(cmd, String.format("cannot find 
vm[name:%s] while waiting for baremtal provision done notification", 
vm.getName()));
+                    }
+
+                    if (VirtualMachine.State.Running == vmvo.getState()) {
+                        return new StartAnswer(cmd);
+                    }
+
+                    s_logger.debug(String.format("still wait for baremetal 
provision done notification for vm[name:%s], current vm state is %s", 
vmvo.getInstanceName(), vmvo.getState()));
+                }
+
+                return new StartAnswer(cmd, String.format("timeout after %s 
seconds, no baremetal provision done notification received. vm[name:%s] failed 
to start", isProvisionDoneNotificationTimeout, vm.getName()));
+            }
+        }
+
         s_logger.debug("Start bare metal vm " + vm.getName() + "successfully");
         _vmName = vm.getName();
         return new StartAnswer(cmd);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartPxeResource.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartPxeResource.java
 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartPxeResource.java
index 75be597..260f4f1 100755
--- 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartPxeResource.java
+++ 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartPxeResource.java
@@ -34,7 +34,6 @@ import com.cloud.agent.api.Command;
 import com.cloud.agent.api.HostVmStateReportEntry;
 import com.cloud.agent.api.PingCommand;
 import com.cloud.agent.api.PingRoutingCommand;
-import com.cloud.agent.api.baremetal.PrepareKickstartPxeServerCommand;
 import com.cloud.agent.api.routing.VmDataCommand;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.script.Script;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java
 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java
index f668155..7f6b0bf 100755
--- 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java
+++ 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java
@@ -30,16 +30,17 @@ import java.util.Map;
 import javax.ejb.Local;
 import javax.inject.Inject;
 
+import com.cloud.configuration.Config;
+import org.apache.log4j.Logger;
+
 import org.apache.cloudstack.api.AddBaremetalKickStartPxeCmd;
 import org.apache.cloudstack.api.AddBaremetalPxeCmd;
 import org.apache.cloudstack.api.ListBaremetalPxeServersCmd;
 import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
-import org.apache.log4j.Logger;
 
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.baremetal.IpmISetBootDevCommand;
 import com.cloud.agent.api.baremetal.IpmISetBootDevCommand.BootDev;
-import com.cloud.agent.api.baremetal.PrepareKickstartPxeServerCommand;
 import com.cloud.baremetal.database.BaremetalPxeDao;
 import com.cloud.baremetal.database.BaremetalPxeVO;
 import com.cloud.baremetal.networkservice.BaremetalPxeManager.BaremetalPxeType;
@@ -223,6 +224,11 @@ public class BaremetalKickStartServiceImpl extends 
BareMetalPxeServiceBase imple
             throw new CloudRuntimeException(String.format("cannot find 
management nic on virtual router[id:%s]", vr.getId()));
         }
 
+        String internalServerIp = 
_configDao.getValue(Config.BaremetalInternalStorageServer.key());
+        if (internalServerIp == null) {
+            throw new CloudRuntimeException(String.format("please specify 
'baremetal.internal.storage.server.ip', which is the http server/nfs server 
storing kickstart files and ISO files, in global setting"));
+        }
+
         List<String> tuple =  parseKickstartUrl(profile);
         String cmd =  String.format("/opt/cloud/bin/prepare_pxe.sh %s %s %s %s 
%s %s", tuple.get(1), tuple.get(2), profile.getTemplate().getUuid(),
                 String.format("01-%s", nic.getMacAddress().replaceAll(":", 
"-")).toLowerCase(), tuple.get(0), nic.getMacAddress().toLowerCase());
@@ -232,7 +238,7 @@ public class BaremetalKickStartServiceImpl extends 
BareMetalPxeServiceBase imple
             throw new CloudRuntimeException(String.format("failed preparing 
PXE in virtual router[id:%s], because %s", vr.getId(), ret.second()));
         }
 
-        String internalServerIp = "10.223.110.231";
+        //String internalServerIp = "10.223.110.231";
         cmd = String.format("/opt/cloud/bin/baremetal_snat.sh %s %s %s", 
mgmtNic.getIp4Address(), internalServerIp, mgmtNic.getGateway());
         s_logger.debug(String.format("prepare SNAT on virtual router[ip:%s], 
cmd: %s", mgmtNic.getIp4Address(), cmd));
         ret = SshHelper.sshExecute(mgmtNic.getIp4Address(), 3922, "root", 
getSystemVMKeyFile(), null, cmd);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java
 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java
index 5d20d31..10b81c2 100755
--- 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java
+++ 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java
@@ -21,6 +21,7 @@ package com.cloud.baremetal.networkservice;
 import com.cloud.baremetal.database.BaremetalPxeVO;
 import com.cloud.baremetal.manager.BaremetalVlanManager;
 import com.cloud.dc.DataCenter;
+import com.cloud.dc.DataCenterVO;
 import com.cloud.dc.Pod;
 import com.cloud.dc.dao.DataCenterDao;
 import com.cloud.deploy.DeployDestination;
@@ -139,11 +140,9 @@ public class BaremetalPxeElement extends AdapterBase 
implements NetworkElement {
             }
         }
 
-        /*
         if (dest.getDataCenter().getNetworkType() == 
DataCenter.NetworkType.Advanced){
             prepareVlan(network, dest);
         }
-        */
 
         return true;
     }
@@ -159,12 +158,10 @@ public class BaremetalPxeElement extends AdapterBase 
implements NetworkElement {
             return false;
         }
 
-        /*
         DataCenterVO dc = 
zoneDao.findById(vm.getVirtualMachine().getDataCenterId());
         if (dc.getNetworkType() == DataCenter.NetworkType.Advanced) {
             releaseVlan(network, vm);
         }
-        */
         return true;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/Force10BaremetalSwitchBackend.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/Force10BaremetalSwitchBackend.java
 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/Force10BaremetalSwitchBackend.java
old mode 100644
new mode 100755
index 9009b02..c34a6cd
--- 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/Force10BaremetalSwitchBackend.java
+++ 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/Force10BaremetalSwitchBackend.java
@@ -32,11 +32,16 @@ import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.web.client.ResponseErrorHandler;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.web.util.UriComponentsBuilder;
 
+import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -46,17 +51,38 @@ public class Force10BaremetalSwitchBackend implements 
BaremetalSwitchBackend {
     private Logger logger = 
Logger.getLogger(Force10BaremetalSwitchBackend.class);
     public static final String TYPE = "Force10";
 
+    private static List<HttpStatus> successHttpStatusCode = new ArrayList<>();
+    {
+        successHttpStatusCode.add(HttpStatus.OK);
+        successHttpStatusCode.add(HttpStatus.ACCEPTED);
+        successHttpStatusCode.add(HttpStatus.CREATED);
+        successHttpStatusCode.add(HttpStatus.NO_CONTENT);
+        successHttpStatusCode.add(HttpStatus.PARTIAL_CONTENT);
+        successHttpStatusCode.add(HttpStatus.RESET_CONTENT);
+        successHttpStatusCode.add(HttpStatus.ALREADY_REPORTED);
+    }
+
     RestTemplate rest = new RestTemplate();
-
-    private String buildLink(String switchIp, Integer vlan) {
+    {
+        // fake error handler, we handle error in business logic code
+        rest.setErrorHandler(new ResponseErrorHandler() {
+            @Override
+            public boolean hasError(ClientHttpResponse clientHttpResponse) 
throws IOException {
+                return false;
+            }
+
+            @Override
+            public void handleError(ClientHttpResponse clientHttpResponse) 
throws IOException {
+            }
+        });
+    }
+
+    private String buildLink(String switchIp, String path) {
         UriComponentsBuilder builder = UriComponentsBuilder.newInstance();
         builder.scheme("http");
         builder.host(switchIp);
         builder.port(8008);
-        builder.path("/api/running/ftos/interface/vlan");
-        if (vlan != null) {
-            builder.path(vlan.toString());
-        }
+        builder.path(path);
         return builder.build().toUriString();
     }
 
@@ -67,29 +93,36 @@ public class Force10BaremetalSwitchBackend implements 
BaremetalSwitchBackend {
 
     @Override
     public void prepareVlan(BaremetalVlanStruct struct) {
-        String link = buildLink(struct.getSwitchIp(), struct.getVlan());
+        String link = buildLink(struct.getSwitchIp(), 
String.format("/api/running/ftos/interface/vlan/%s", struct.getVlan()));
         HttpHeaders headers = createBasicAuthenticationHeader(struct);
         HttpEntity<String> request = new HttpEntity<>(headers);
         ResponseEntity rsp = rest.exchange(link, HttpMethod.GET, request, 
String.class);
+        logger.debug(String.format("http get: %s", link));
 
         if (rsp.getStatusCode() == HttpStatus.NOT_FOUND) {
             PortInfo port = new PortInfo(struct);
-            XmlObject xml = new XmlObject("vlan").putElement("vlan-id", 
String.valueOf(struct.getVlan())).putElement("tagged",
-                    new XmlObject(port.interfaceType).putElement("name", 
port.port)
-            ).putElement("shutdown", "false");
-            request = new HttpEntity<>(xml.toString(), headers);
-            link = buildLink(struct.getSwitchIp(), null);
-            rsp = rest.exchange(link, HttpMethod.GET, request, String.class);
-            if (rsp.getStatusCode() != HttpStatus.OK) {
+            XmlObject xml = new XmlObject("vlan").putElement("vlan-id",
+                    new 
XmlObject("vlan-id").setText(String.valueOf(struct.getVlan()))).putElement("untagged",
+                    new XmlObject("untagged").putElement(port.interfaceType, 
new XmlObject(port.interfaceType)
+                            .putElement("name", new 
XmlObject("name").setText(port.port)))
+            ).putElement("shutdown", new 
XmlObject("shutdown").setText("false"));
+            request = new HttpEntity<>(xml.dump(), headers);
+            link = buildLink(struct.getSwitchIp(), 
String.format("/api/running/ftos/interface/"));
+            logger.debug(String.format("http get: %s, body: %s", link, 
request));
+            rsp = rest.exchange(link, HttpMethod.POST, request, String.class);
+            if (!successHttpStatusCode.contains(rsp.getStatusCode())) {
                 throw new CloudRuntimeException(String.format("unable to 
create vlan[%s] on force10 switch[ip:%s]. HTTP status code:%s, body dump:%s",
-                        struct.getVlan(), rsp.getStatusCode(), 
struct.getSwitchIp(), rsp.getBody()));
+                        struct.getVlan(), 
struct.getSwitchIp(),rsp.getStatusCode(), rsp.getBody()));
+            } else {
+                logger.debug(String.format("successfully programmed vlan[%s] 
on Force10[ip:%s, port:%s]. http response[status code:%s, body:%s]",
+                        struct.getVlan(), struct.getSwitchIp(), 
struct.getPort(), rsp.getStatusCode(), rsp.getBody()));
             }
-        } else if (rsp.getStatusCode() == HttpStatus.OK) {
+        } else if (successHttpStatusCode.contains(rsp.getStatusCode())) {
             PortInfo port = new PortInfo(struct);
             XmlObject xml = 
XmlObjectParser.parseFromString((String)rsp.getBody());
-            List<XmlObject> ports = xml.getAsList("tagged.tengigabitethernet");
-            ports.addAll(xml.<XmlObject>getAsList("tagged.gigabitethernet"));
-            ports.addAll(xml.<XmlObject>getAsList("tagged.fortyGigE"));
+            List<XmlObject> ports = 
xml.getAsList("untagged.tengigabitethernet");
+            ports.addAll(xml.<XmlObject>getAsList("untagged.gigabitethernet"));
+            ports.addAll(xml.<XmlObject>getAsList("untagged.fortyGigE"));
             for (XmlObject pxml : ports) {
                 XmlObject name = pxml.get("name");
                 if (port.port.equals(name.getText())) {
@@ -98,14 +131,26 @@ public class Force10BaremetalSwitchBackend implements 
BaremetalSwitchBackend {
                 }
             }
 
-            XmlObject tag = xml.get("tagged");
-            tag.putElement(port.interfaceType, new 
XmlObject("name").setText(port.port));
-            request = new HttpEntity<>(xml.toString(), headers);
-            link = buildLink(struct.getSwitchIp(), struct.getVlan());
+            xml.removeElement("mtu");
+            xml.setText(null);
+            XmlObject tag = xml.get("untagged");
+            if (tag == null) {
+                tag = new XmlObject("untagged");
+                xml.putElement("untagged", tag);
+            }
+
+            tag.putElement(port.interfaceType, new 
XmlObject(port.interfaceType)
+                    .putElement("name", new 
XmlObject("name").setText(port.port)));
+            request = new HttpEntity<>(xml.dump(), headers);
+            link = buildLink(struct.getSwitchIp(), 
String.format("/api/running/ftos/interface/vlan/%s", struct.getVlan()));
+            logger.debug(String.format("http get: %s, body: %s", link, 
request));
             rsp = rest.exchange(link, HttpMethod.PUT, request, String.class);
-            if (rsp.getStatusCode() != HttpStatus.NO_CONTENT) {
+            if (!successHttpStatusCode.contains(rsp.getStatusCode())) {
                 throw new CloudRuntimeException(String.format("failed to 
program vlan[%s] for port[%s] on force10[ip:%s]. http status:%s, body dump:%s",
                         struct.getVlan(), struct.getPort(), 
struct.getSwitchIp(), rsp.getStatusCode(), rsp.getBody()));
+            } else {
+                logger.debug(String.format("successfully join port[%s] into 
vlan[%s] on Force10[ip:%s]. http response[status code:%s, body:%s]",
+                        struct.getPort(), struct.getVlan(), 
struct.getSwitchIp(), rsp.getStatusCode(), rsp.getBody()));
             }
         } else {
             throw new CloudRuntimeException(String.format("force10[ip:%s] 
returns unexpected error[%s] when http getting %s, body dump:%s",
@@ -115,18 +160,19 @@ public class Force10BaremetalSwitchBackend implements 
BaremetalSwitchBackend {
 
     @Override
     public void removePortFromVlan(BaremetalVlanStruct struct) {
-        String link = buildLink(struct.getSwitchIp(), struct.getVlan());
+        String link = buildLink(struct.getSwitchIp(), 
String.format("/api/running/ftos/interface/vlan/%s", struct.getVlan()));
         HttpHeaders headers = createBasicAuthenticationHeader(struct);
         HttpEntity<String> request = new HttpEntity<>(headers);
+        logger.debug(String.format("http get: %s, body: %s", link, request));
         ResponseEntity rsp = rest.exchange(link, HttpMethod.GET, request, 
String.class);
         if (rsp.getStatusCode() == HttpStatus.NOT_FOUND) {
             logger.debug(String.format("vlan[%s] has been deleted on 
force10[ip:%s], no need to remove the port[%s] anymore", struct.getVlan(), 
struct.getSwitchIp(), struct.getPort()));
         } else if (rsp.getStatusCode() == HttpStatus.OK) {
             PortInfo port = new PortInfo(struct);
             XmlObject xml = 
XmlObjectParser.parseFromString((String)rsp.getBody());
-            List<XmlObject> ports = xml.getAsList("tagged.tengigabitethernet");
-            ports.addAll(xml.<XmlObject>getAsList("tagged.gigabitethernet"));
-            ports.addAll(xml.<XmlObject>getAsList("tagged.fortyGigE"));
+            List<XmlObject> ports = 
xml.getAsList("untagged.tengigabitethernet");
+            ports.addAll(xml.<XmlObject>getAsList("untagged.gigabitethernet"));
+            ports.addAll(xml.<XmlObject>getAsList("untagged.fortyGigE"));
             List<XmlObject> newPorts = new ArrayList<>();
             boolean needRemove = false;
             for (XmlObject pxml : ports) {
@@ -143,11 +189,19 @@ public class Force10BaremetalSwitchBackend implements 
BaremetalSwitchBackend {
                 return;
             }
 
-            xml.putElement("tagged", newPorts);
-
-            request = new HttpEntity<>(xml.toString(), headers);
+            xml.setText(null);
+            xml.removeElement("mtu");
+            XmlObject tagged = xml.get("untagged");
+            tagged.removeAllChildren();
+            for (XmlObject p : newPorts) {
+                tagged.putElement(p.getTag(), p);
+            }
+
+
+            request = new HttpEntity<>(xml.dump(), headers);
+            logger.debug(String.format("http get: %s, body: %s", link, 
request));
             rsp = rest.exchange(link, HttpMethod.PUT, request, String.class);
-            if (rsp.getStatusCode() != HttpStatus.NO_CONTENT) {
+            if (!successHttpStatusCode.contains(rsp.getStatusCode())) {
                 throw new CloudRuntimeException(String.format("failed to 
program vlan[%s] for port[%s] on force10[ip:%s]. http status:%s, body dump:%s",
                         struct.getVlan(), struct.getPort(), 
struct.getSwitchIp(), rsp.getStatusCode(), rsp.getBody()));
             } else {
@@ -166,6 +220,8 @@ public class Force10BaremetalSwitchBackend implements 
BaremetalSwitchBackend {
         String base64Creds = new String(base64CredsBytes);
         HttpHeaders headers = new HttpHeaders();
         headers.add("Authorization", "Basic " + base64Creds);
+        headers.setAccept(Arrays.asList(MediaType.ALL));
+        
headers.setContentType(MediaType.valueOf("application/vnd.yang.data+xml"));
         return  headers;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/PrepareKickstartPxeServerCommand.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/PrepareKickstartPxeServerCommand.java
 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/PrepareKickstartPxeServerCommand.java
new file mode 100755
index 0000000..4f59a83
--- /dev/null
+++ 
b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/PrepareKickstartPxeServerCommand.java
@@ -0,0 +1,83 @@
+// 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.
+//
+// Automatically generated by addcopyright.py at 01/29/2013
+package com.cloud.baremetal.networkservice;
+
+import com.cloud.agent.api.Command;
+
+public class PrepareKickstartPxeServerCommand extends Command {
+    private String ksFile;
+    private String templateUuid;
+    private String mac;
+    private String ksDevice;
+    private String kernel;
+    private String initrd;
+
+    @Override
+    public boolean executeInSequence() {
+        return true;
+    }
+
+    public String getKsFile() {
+        return ksFile;
+    }
+
+    public void setKsFile(String ksFile) {
+        this.ksFile = ksFile;
+    }
+
+    public String getKernel() {
+        return kernel;
+    }
+
+    public void setKernel(String kernel) {
+        this.kernel = kernel;
+    }
+
+    public String getInitrd() {
+        return initrd;
+    }
+
+    public void setInitrd(String initrd) {
+        this.initrd = initrd;
+    }
+
+    public String getTemplateUuid() {
+        return templateUuid;
+    }
+
+    public void setTemplateUuid(String templateUuid) {
+        this.templateUuid = templateUuid;
+    }
+
+    public String getMac() {
+        return mac;
+    }
+
+    public void setMac(String mac) {
+        this.mac = mac;
+    }
+
+    public String getKsDevice() {
+        return ksDevice;
+    }
+
+    public void setKsDevice(String ksDevice) {
+        this.ksDevice = ksDevice;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/plugins/hypervisors/baremetal/src/org/apache/cloudstack/api/BaremetalProvisionDoneNotificationCmd.java
----------------------------------------------------------------------
diff --git 
a/plugins/hypervisors/baremetal/src/org/apache/cloudstack/api/BaremetalProvisionDoneNotificationCmd.java
 
b/plugins/hypervisors/baremetal/src/org/apache/cloudstack/api/BaremetalProvisionDoneNotificationCmd.java
new file mode 100755
index 0000000..a5248aa
--- /dev/null
+++ 
b/plugins/hypervisors/baremetal/src/org/apache/cloudstack/api/BaremetalProvisionDoneNotificationCmd.java
@@ -0,0 +1,87 @@
+// 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.api;
+
+import com.cloud.baremetal.manager.BaremetalManager;
+import com.cloud.event.EventTypes;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.NetworkRuleConflictException;
+import com.cloud.exception.ResourceAllocationException;
+import com.cloud.exception.ResourceUnavailableException;
+import org.apache.cloudstack.acl.RoleType;
+import org.apache.cloudstack.api.response.SuccessResponse;
+import org.apache.cloudstack.context.CallContext;
+
+import javax.inject.Inject;
+import org.apache.log4j.Logger;
+
+/**
+ * Created by frank on 9/17/14.
+ */
+@APICommand(name = "notifyBaremetalProvisionDone", description = "Notify 
provision has been done on a host. This api is for baremetal virtual router 
service, not for end user", responseObject = SuccessResponse.class,
+        requestHasSensitiveInfo = false, responseHasSensitiveInfo = false, 
authorized = {RoleType.User})
+public class BaremetalProvisionDoneNotificationCmd extends BaseAsyncCmd {
+    public static final Logger s_logger = 
Logger.getLogger(BaremetalProvisionDoneNotificationCmd.class);
+    private static final String s_name = "baremetalprovisiondone";
+
+    @Inject
+    private BaremetalManager bmMgr;
+
+    @Parameter(name="mac", required = true, description = "mac of the nic used 
for provision")
+    private String mac;
+
+    @Override
+    public String getEventType() {
+        return EventTypes.EVENT_BAREMETAL_PROVISION_DONE;
+    }
+
+    @Override
+    public String getEventDescription() {
+        return "notify management server that baremetal provision has been 
done on a host";
+    }
+
+    @Override
+    public void execute() throws ResourceUnavailableException, 
InsufficientCapacityException, ServerApiException, 
ConcurrentOperationException, ResourceAllocationException, 
NetworkRuleConflictException {
+        try {
+            bmMgr.notifyProvisionDone(this);
+            this.setResponseObject(new SuccessResponse(getCommandName()));
+        } catch (Exception e) {
+            s_logger.warn(String.format("unable to notify baremetal provision 
done[mac:%s]", mac), e);
+            throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, 
e.getMessage());
+        }
+    }
+
+    public String getMac() {
+        return mac;
+    }
+
+    public void setMac(String mac) {
+        this.mac = mac;
+    }
+
+    @Override
+    public String getCommandName() {
+        return s_name;
+    }
+
+    @Override
+    public long getEntityOwnerId() {
+        return CallContext.current().getCallingAccount().getId();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/server/src/com/cloud/configuration/Config.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/configuration/Config.java 
b/server/src/com/cloud/configuration/Config.java
index 71f5c5b..3710e0a 100755
--- a/server/src/com/cloud/configuration/Config.java
+++ b/server/src/com/cloud/configuration/Config.java
@@ -1848,29 +1848,37 @@ public enum Config {
             "The maximum number of retrying times to search for an available 
IPv6 address in the table",
             null),
 
-    BaremetalEnableCompleteNotification(
+    BaremetalInternalStorageServer(
+            "Advanced",
+            ManagementServer.class,
+            String.class,
+            "baremetal.internal.storage.server.ip",
+            null,
+            "the ip address of server that stores kickstart file, kernel, 
initrd, ISO for advanced networking baremetal provisioning",
+            null),
+    BaremetalProvisionDoneNotificationEnabled(
             "Advanced",
             ManagementServer.class,
             Boolean.class,
-            "baremetal.provision.done.notification",
-            "false",
-            "Enable provision done notification through virtual router",
+            "baremetal.provision.done.notification.enabled",
+            "true",
+            "whether to enable baremetal provison done notification",
             null),
-    BaremetalPeerHypervisorType(
+    BaremetalProvisionDoneNotificationTimeout(
             "Advanced",
             ManagementServer.class,
-            String.class,
-            "baremetal.peer.hypervisor.type",
-            "Vmware",
-            "Hypervisor[Xenserver/KVM/VMWare] used to spring up virtual router 
for baremetal instances. The cluster having this hypervisor type must be in the 
same zone with baremetal cluster",
+            Integer.class,
+            "baremetal.provision.done.notification.timeout",
+            "1800",
+            "the max time to wait before treating a baremetal provision as 
failure if no provision done notification is not received, in secs",
             null),
-    BaremetalInternalStorageServer(
+    BaremetalProvisionDoneNotificationPort(
             "Advanced",
             ManagementServer.class,
-            String.class,
-            "baremetal.internal.storage.server.ip",
-            null,
-            "the ip address of server that stores kickstart file, kernel, 
initrd, ISO for advanced networking baremetal provisioning",
+            Integer.class,
+            "baremetal.provision.done.notification.port",
+            "8080",
+            "the port that listens baremetal provision done notification. 
Should be the same to port management server listening on for now. Please 
change it to management server port if it's not default 8080",
             null),
     ExternalBaremetalSystemUrl(
             "Advanced",

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java 
b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java
index 3329ff2..bfb33b0 100755
--- a/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java
+++ b/server/src/com/cloud/deploy/DeploymentPlanningManagerImpl.java
@@ -404,6 +404,15 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> 
{
                             s_logger.debug("The last host of this VM is UP and 
has enough capacity");
                             s_logger.debug("Now checking for suitable pools 
under zone: " + host.getDataCenterId()
                                     + ", pod: " + host.getPodId() + ", 
cluster: " + host.getClusterId());
+
+                            Pod pod = _podDao.findById(host.getPodId());
+                            Cluster cluster = 
_clusterDao.findById(host.getClusterId());
+                            if (vm.getHypervisorType() == 
HypervisorType.BareMetal) {
+                                DeployDestination dest = new 
DeployDestination(dc, pod, cluster, host, new HashMap<Volume, StoragePool>());
+                                s_logger.debug("Returning Deployment 
Destination: " + dest);
+                                return dest;
+                            }
+
                             // search for storage under the zone, pod, cluster
                             // of
                             // the last host.
@@ -423,8 +432,6 @@ StateListener<State, VirtualMachine.Event, VirtualMachine> {
                                         suitableHosts, 
suitableVolumeStoragePools, avoids,
                                         getPlannerUsage(planner, vmProfile, 
plan, avoids), readyAndReusedVolumes);
                                 if (potentialResources != null) {
-                                    Pod pod = 
_podDao.findById(host.getPodId());
-                                    Cluster cluster = 
_clusterDao.findById(host.getClusterId());
                                     Map<Volume, StoragePool> storageVolMap = 
potentialResources.second();
                                     // remove the reused vol<->pool from
                                     // destination, since we don't have to

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
----------------------------------------------------------------------
diff --git 
a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java 
b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
index be7cb37..315bdde 100644
--- 
a/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
+++ 
b/server/src/com/cloud/network/router/VirtualNetworkApplianceManagerImpl.java
@@ -1506,6 +1506,8 @@ Configurable, StateListener<State, VirtualMachine.Event, 
VirtualMachine> {
             } else {
                 buf.append(String.format(" 
baremetalnotificationsecuritykey=%s", user.getSecretKey()));
                 buf.append(String.format(" baremetalnotificationapikey=%s", 
user.getApiKey()));
+                buf.append(" 
host=").append(ApiServiceConfiguration.ManagementHostIPAdr.value());
+                buf.append(" 
port=").append(_configDao.getValue(Config.BaremetalProvisionDoneNotificationPort.key()));
             }
         }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/server/src/com/cloud/resource/ResourceManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/resource/ResourceManagerImpl.java 
b/server/src/com/cloud/resource/ResourceManagerImpl.java
index cdad91e..c7ba80a 100755
--- a/server/src/com/cloud/resource/ResourceManagerImpl.java
+++ b/server/src/com/cloud/resource/ResourceManagerImpl.java
@@ -1631,21 +1631,6 @@ public class ResourceManagerImpl extends ManagerBase 
implements ResourceManager,
                 clusterId = c.getId();
             }
         }
-        if (startup instanceof StartupRoutingCommand) {
-            StartupRoutingCommand ssCmd = ((StartupRoutingCommand)startup);
-            List<String> implicitHostTags = ssCmd.getHostTags();
-            if (!implicitHostTags.isEmpty()) {
-                if (hostTags == null) {
-                    hostTags = _hostTagsDao.gethostTags(host.getId());
-                }
-                if (hostTags != null) {
-                    implicitHostTags.removeAll(hostTags);
-                    hostTags.addAll(implicitHostTags);
-                } else {
-                    hostTags = implicitHostTags;
-                }
-            }
-        }
 
         if (startup instanceof StartupRoutingCommand) {
             StartupRoutingCommand ssCmd = ((StartupRoutingCommand)startup);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/server/src/com/cloud/storage/VolumeApiServiceImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/VolumeApiServiceImpl.java 
b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
index 9f132c3..e089b77 100644
--- a/server/src/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/com/cloud/storage/VolumeApiServiceImpl.java
@@ -1230,10 +1230,9 @@ public class VolumeApiServiceImpl extends ManagerBase 
implements VolumeApiServic
 
         // Check that the volume ID is valid
         VolumeInfo volumeToAttach = volFactory.getVolume(volumeId);
-
         // Check that the volume is a data volume
-        if (volumeToAttach == null || !(volumeToAttach.getVolumeType() == 
Volume.Type.DATADISK)) {
-            throw new InvalidParameterValueException("Please specify a volume 
with the valid type: " + Volume.Type.DATADISK.toString());
+        if (volumeToAttach == null || !(volumeToAttach.getVolumeType() == 
Volume.Type.DATADISK || volumeToAttach.getVolumeType() == Volume.Type.ROOT)) {
+            throw new InvalidParameterValueException("Please specify a volume 
with the valid type: " + Volume.Type.ROOT.toString() + " or " + 
Volume.Type.DATADISK.toString());
         }
 
         // Check that the volume is not currently attached to any VM
@@ -1516,10 +1515,9 @@ public class VolumeApiServiceImpl extends ManagerBase 
implements VolumeApiServic
             throw new InvalidParameterValueException("Please specify a VM that 
is either running or stopped.");
         }
 
-        // Check that the volume is a data volume.
-        // TODO - Disabling root volume detach for now, enable it back in 4.6
-        if (volume.getVolumeType() != Volume.Type.DATADISK) {
-            throw new InvalidParameterValueException("Please specify volume of 
type " + Volume.Type.DATADISK.toString());
+        // Check that the volume is a data/root volume
+        if (!(volume.getVolumeType() == Volume.Type.ROOT || 
volume.getVolumeType() == Volume.Type.DATADISK)) {
+            throw new InvalidParameterValueException("Please specify volume of 
type " + Volume.Type.DATADISK.toString() + " or " + 
Volume.Type.ROOT.toString());
         }
 
         // Root volume detach is allowed for following hypervisors: 
Xen/KVM/VmWare

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/server/test/com/cloud/storage/VolumeApiServiceImplTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/storage/VolumeApiServiceImplTest.java 
b/server/test/com/cloud/storage/VolumeApiServiceImplTest.java
index 3d2de4e..c60aa50 100644
--- a/server/test/com/cloud/storage/VolumeApiServiceImplTest.java
+++ b/server/test/com/cloud/storage/VolumeApiServiceImplTest.java
@@ -30,6 +30,7 @@ import javax.inject.Inject;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
+import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.mockito.Mock;
 import org.mockito.Mockito;
@@ -48,6 +49,7 @@ import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
 
+import com.cloud.exception.InvalidParameterValueException;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.storage.dao.VolumeDao;
 import com.cloud.user.Account;
@@ -241,7 +243,7 @@ public class VolumeApiServiceImplTest {
      * @throws Exception
      */
 
-    //@Test(expected = InvalidParameterValueException.class)
+    @Test(expected = InvalidParameterValueException.class)
     public void testDetachVolumeFromRunningVm() throws NoSuchFieldException, 
IllegalAccessException {
         Field dedicateIdField = _detachCmdClass.getDeclaredField("id");
         dedicateIdField.setAccessible(true);
@@ -249,7 +251,7 @@ public class VolumeApiServiceImplTest {
         _svc.detachVolumeFromVM(detachCmd);
     }
 
-    //@Test(expected = InvalidParameterValueException.class)
+    @Test(expected = InvalidParameterValueException.class)
     public void testDetachVolumeFromStoppedHyperVVm() throws 
NoSuchFieldException, IllegalAccessException {
         Field dedicateIdField = _detachCmdClass.getDeclaredField("id");
         dedicateIdField.setAccessible(true);
@@ -257,7 +259,7 @@ public class VolumeApiServiceImplTest {
         _svc.detachVolumeFromVM(detachCmd);
     }
 
-    //@Test(expected = InvalidParameterValueException.class)
+    @Test(expected = InvalidParameterValueException.class)
     public void testDetachVolumeOfManagedDataStore() throws 
NoSuchFieldException, IllegalAccessException {
         Field dedicateIdField = _detachCmdClass.getDeclaredField("id");
         dedicateIdField.setAccessible(true);
@@ -268,7 +270,7 @@ public class VolumeApiServiceImplTest {
     @Rule
     public ExpectedException thrown = ExpectedException.none();
 
-    //@Test
+    @Test
     public void testDetachVolumeFromStoppedXenVm() throws 
NoSuchFieldException, IllegalAccessException {
         thrown.expect(NullPointerException.class);
         Field dedicateIdField = _detachCmdClass.getDeclaredField("id");
@@ -282,43 +284,43 @@ public class VolumeApiServiceImplTest {
      */
 
     // Negative test - try to attach non-root non-datadisk volume
-    //@Test(expected = InvalidParameterValueException.class)
+    @Test(expected = InvalidParameterValueException.class)
     public void attachIncorrectDiskType() throws NoSuchFieldException, 
IllegalAccessException {
         _svc.attachVolumeToVM(1L, 5L, 0L);
     }
 
     // Negative test - attach root volume to running vm
-    //@Test(expected = InvalidParameterValueException.class)
+    @Test(expected = InvalidParameterValueException.class)
     public void attachRootDiskToRunningVm() throws NoSuchFieldException, 
IllegalAccessException {
         _svc.attachVolumeToVM(1L, 6L, 0L);
     }
 
     // Negative test - attach root volume to non-xen vm
-    //@Test(expected = InvalidParameterValueException.class)
+    @Test(expected = InvalidParameterValueException.class)
     public void attachRootDiskToHyperVm() throws NoSuchFieldException, 
IllegalAccessException {
         _svc.attachVolumeToVM(3L, 6L, 0L);
     }
 
     // Negative test - attach root volume from the managed data store
-    //@Test(expected = InvalidParameterValueException.class)
+    @Test(expected = InvalidParameterValueException.class)
     public void attachRootDiskOfManagedDataStore() throws 
NoSuchFieldException, IllegalAccessException {
         _svc.attachVolumeToVM(2L, 7L, 0L);
     }
 
     // Negative test - root volume can't be attached to the vm already having 
a root volume attached
-    //@Test(expected = InvalidParameterValueException.class)
+    @Test(expected = InvalidParameterValueException.class)
     public void attachRootDiskToVmHavingRootDisk() throws 
NoSuchFieldException, IllegalAccessException {
         _svc.attachVolumeToVM(4L, 6L, 0L);
     }
 
     // Negative test - root volume in uploaded state can't be attached
-    //@Test(expected = InvalidParameterValueException.class)
+    @Test(expected = InvalidParameterValueException.class)
     public void attachRootInUploadedState() throws NoSuchFieldException, 
IllegalAccessException {
         _svc.attachVolumeToVM(2L, 8L, 0L);
     }
 
     // Positive test - attach ROOT volume in correct state, to the vm not 
having root volume attached
-    //@Test
+    @Test
     public void attachRootVolumePositive() throws NoSuchFieldException, 
IllegalAccessException {
         thrown.expect(NullPointerException.class);
         _svc.attachVolumeToVM(2L, 6L, 0L);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/systemvm/patches/debian/config/etc/dnsmasq.conf.tmpl
----------------------------------------------------------------------
diff --git a/systemvm/patches/debian/config/etc/dnsmasq.conf.tmpl 
b/systemvm/patches/debian/config/etc/dnsmasq.conf.tmpl
index 447e748..28b598c 100644
--- a/systemvm/patches/debian/config/etc/dnsmasq.conf.tmpl
+++ b/systemvm/patches/debian/config/etc/dnsmasq.conf.tmpl
@@ -415,7 +415,7 @@ dhcp-option=vendor:MSFT,2,1i
 # this is you want to boot machines over the network and you will need
 # a TFTP server; either dnsmasq's built in TFTP server or an
 # external one. (See below for how to enable the TFTP server.)
-#dhcp-boot=pxelinux.0
+dhcp-boot=pxelinux.0
 
 # The same as above, but use custom tftp-server instead machine running dnsmasq
 #dhcp-boot=pxelinux,server.name,192.168.1.100
@@ -472,10 +472,10 @@ dhcp-option=vendor:MSFT,2,1i
 
 
 # Enable dnsmasq's built-in TFTP server
-#enable-tftp
+enable-tftp
 
 # Set the root directory for files available via FTP.
-#tftp-root=/var/ftpd
+tftp-root=/opt/tftpboot
 
 # Make the TFTP server more secure: with this set, only files owned by
 # the user dnsmasq is running as will be send over the net.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/systemvm/patches/debian/config/opt/cloud/bin/baremetal_snat.sh
----------------------------------------------------------------------
diff --git a/systemvm/patches/debian/config/opt/cloud/bin/baremetal_snat.sh 
b/systemvm/patches/debian/config/opt/cloud/bin/baremetal_snat.sh
index f35a16f..22e5669 100755
--- a/systemvm/patches/debian/config/opt/cloud/bin/baremetal_snat.sh
+++ b/systemvm/patches/debian/config/opt/cloud/bin/baremetal_snat.sh
@@ -21,11 +21,12 @@ set +u
 
 mgmt_nic_ip=$1
 internal_server_ip=$2
+gateway_ip=$3
 
 ip route | grep "$internal_server_ip" > /dev/null
 
 if [ $? -ne 0 ]; then
-    ip route add $internal_server_ip via $mgmt_nic_ip
+    ip route add $internal_server_ip via $gateway_ip
 fi
 
 iptables-save | grep -- "-A POSTROUTING -d $internal_server_ip" > /dev/null
@@ -33,3 +34,21 @@ iptables-save | grep -- "-A POSTROUTING -d 
$internal_server_ip" > /dev/null
 if [ $? -ne 0 ]; then
     iptables -t nat -A POSTROUTING -d $internal_server_ip -j SNAT --to-source 
$mgmt_nic_ip
 fi
+
+
+iptables-save | grep -- "-A INPUT -i eth0 -p udp -m udp --dport 69 -j ACCEPT" 
> /dev/null
+if [ $? -ne 0 ]; then
+    iptables -I INPUT -i eth0 -p udp -m udp --dport 69 -j ACCEPT
+fi
+
+iptables-save | grep -- "-A FORWARD -i eth1 -o eth0 -j ACCEPT" > /dev/null
+if [ $? -ne 0 ]; then
+    iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
+fi
+
+rule="-A FORWARD -d $internal_server_ip/32 -i eth0 -o eth1 -j ACCEPT"
+iptables-save | grep -- "$rule" > /dev/null
+if [ $? -ne 0 ]; then 
+    iptables -I FORWARD -d $internal_server_ip/32 -i eth0 -o eth1 -j ACCEPT
+fi
+

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/systemvm/patches/debian/config/opt/cloud/bin/prepare_pxe.sh
----------------------------------------------------------------------
diff --git a/systemvm/patches/debian/config/opt/cloud/bin/prepare_pxe.sh 
b/systemvm/patches/debian/config/opt/cloud/bin/prepare_pxe.sh
index bd9ece6..5bc1a93 100755
--- a/systemvm/patches/debian/config/opt/cloud/bin/prepare_pxe.sh
+++ b/systemvm/patches/debian/config/opt/cloud/bin/prepare_pxe.sh
@@ -40,6 +40,20 @@ tmpt_uuid=$3
 pxe_cfg_filename=$4
 ks_file=$5
 
+kernel_path=$tmpt_uuid/$kernel_file_name
+initrd_path=$tmpt_uuid/$initrd_file_name
+
+cat > $PXELINUX_CFG_DIR/$pxe_cfg_filename <<EOF
+DEFAULT default
+PROMPT 1
+TIMEOUT 26
+DISPLAY boot.msg
+LABEL default
+KERNEL $kernel_path
+APPEND ramdisk_size=66000 initrd=$initrd_path ks=$ks_file
+
+EOF
+
 tmpt_dir=$TFTP_ROOT/$tmpt_uuid
 if [ -d $tmpt_dir ]; then
     success
@@ -47,9 +61,6 @@ fi
 
 mkdir -p $tmpt_dir
 
-kernel_path=$tmpt_uuid/$kernel_file_name
-initrd_path=$tmpt_uuid/$initrd_file_name
-
 mnt_path=/tmp/$(uuid)
 
 mkdir -p $mnt_path
@@ -61,17 +72,6 @@ mount `dirname $initrd_nfs_path` $mnt_path
 cp -f $mnt_path/$initrd_file_name $tmpt_dir/$initrd_file_name
 umount $mnt_path
 
-cat > $PXELINUX_CFG_DIR/$pxe_cfg_filename <<EOF
-DEFAULT default
-PROMPT 1
-TIMEOUT 26
-DISPLAY boot.msg
-LABEL default
-KERNEL $kernel_path
-APPEND ramdisk_size=66000 initrd=$initrd_path ks=$ks_file
-
-EOF
-
 success
 
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/test/integration/component/test_deploy_vgpu_vm.py
----------------------------------------------------------------------
diff --git a/test/integration/component/test_deploy_vgpu_vm.py 
b/test/integration/component/test_deploy_vgpu_vm.py
index 6cd6c2c..0284eab 100644
--- a/test/integration/component/test_deploy_vgpu_vm.py
+++ b/test/integration/component/test_deploy_vgpu_vm.py
@@ -1186,282 +1186,6 @@ class TestvGPUWindowsVm(cloudstackTestCase):
 
 
 
-    def new_template_register(self,guestostype):
-
-        template1 = get_windows_template(self.apiclient, self.zone.id 
,ostype_desc=guestostype)
-
-        if  template1 == FAILED:
-            if "http://pleaseupdateURL/dummy.vhd"; in cls.testdata["vgpu"] 
[guestostype]["url"]:
-                raise unittest.SkipTest("Check Test Data file if it has the 
valid template URL")
-            template1 = Template.register(
-                   self.apiclient,
-                   self.testdata["vgpu"] [guestostype],
-                   hypervisor = "XenServer",
-                   zoneid=cls.zone.id,
-                   domainid=cls.account.domainid,
-                   account=cls.account.name
-                   )
-            timeout = self.testdata["vgpu"]["timeout"]
-
-            while True:
-                  time.sleep(self.testdata["vgpu"]["sleep"])
-                  list_template_response = Template.list(
-                       self.apiclient,
-                       templatefilter=\
-                       self.testdata["templatefilter"],
-                       id=template1.id
-                        )
-                  if (isinstance(list_template_response, list)) is not True:
-                      raise unittest.SkipTest("Check list template api 
response returns a valid list")
-
-                  if len(list_template_response) is None :
-                      raise unittest.SkipTest("Check template registered is in 
List Templates")
-
-                  template_response = list_template_response[0]
-                  if template_response.isready == True:
-                      break
-                  if timeout == 0:
-                      raise unittest.SkipTest("Failed to download template(ID: 
%s)" % template_response.id)
-
-                  timeout = timeout - 1
-        return(template1.id)
-
-    def deploy_vm_lifecycle(self):
-        """
-        Create Service Offerings for Both K1 and K2 cards to be used for VM 
life cycle tests
-        """
-
-        if(self.k1hosts != 0):
-            if(self.k140qgpuhosts != 0):
-                gtype = "GRID K140Q"
-            elif(self.k120qgpuhosts != 0):
-                gtype = "GRID K120Q"
-            elif(self.k100gpuhosts !=0):
-                gtype = "GRID K100"
-            else:
-                gtype = "passthrough"
-
-            
self.testdata["vgpu"]["service_offerings"][gtype]["serviceofferingdetails"] = 
[{'pciDevice':'Group of NVIDIA Corporation GK107GL [GRID K1] GPUs'},
-                                                                               
        {'vgpuType':gtype}]
-            try:
-               self.__class__.k100_vgpu_service_offering = 
ServiceOffering.create(
-                                                                    
self.apiclient,
-                                                                    
self.testdata["vgpu"]["service_offerings"][gtype]
-                                                                    )
-            except Exception as e:
-               self.fail("Failed to create the service offering, %s" % e)
-
-        if(self.k2hosts != 0):
-            if(self.k240qgpuhosts != 0):
-                gtype = "GRID K240Q"
-            elif(cls.k220qgpuhosts != 0):
-                gtype = "GRID K220Q"
-            elif(self.k200gpuhosts !=0):
-                gtype = "GRID K200"
-            else:
-                gtype = "passthrough"
-
-            
self.testdata["vgpu"]["service_offerings"][gtype]["serviceofferingdetails"] = 
[{'pciDevice': 'Group of NVIDIA Corporation GK104GL [GRID K2] GPUs'},
-                                                                               
        {'vgpuType':gtype}]
-            try:
-               self.__class__.k200_vgpu_service_offering = 
ServiceOffering.create(
-                                                                    
self.apiclient,
-                                                                    
self.testdata["vgpu"]["service_offerings"][gtype]
-                                                                    )
-            except Exception as e:
-              self.fail("Failed to create the service offering, %s" % e)
-
-        win8templateid=self.new_template_register("Windows 8 (64-bit)")
-        win2012templateid=self.new_template_register("Windows Server 2012 
(64-bit)")
-        win7templateid=self.new_template_register("Windows 7 (64-bit)")
-
-        """
-        Create Virtual Machines for Both K1 and K2 cards to be used for VM 
life cycle tests
-        """
-
-        if(self.k1hosts != 0):
-            self.__class__.vm_k1_card = VirtualMachine.create(
-            self.apiclient,
-            self.testdata["virtual_machine"],
-            accountid=self.account.name,
-            zoneid=self.zone.id,
-            domainid=self.account.domainid,
-            serviceofferingid=self.k100_vgpu_service_offering.id,
-            templateid=win8templateid
-            )
-        if(self.k2hosts !=0):
-            self.__class__.vm_k2_card = VirtualMachine.create(
-            self.apiclient,
-            self.testdata["virtual_machine"],
-            accountid=self.account.name,
-            zoneid=self.zone.id,
-            domainid=self.account.domainid,
-            serviceofferingid=self.k200_vgpu_service_offering.id,
-            templateid=win2012templateid
-            )
-        if(self.k2hosts !=0):
-            self.__class__.vm2_k2_card = VirtualMachine.create(
-            self.apiclient,
-            self.testdata["virtual_machine"],
-            accountid=self.account.name,
-            zoneid=self.zone.id,
-            domainid=self.account.domainid,
-            serviceofferingid=self.k200_vgpu_service_offering.id,
-            templateid=win7templateid
-            )
-        return
-
-
-    def check_gpu_resources_released_vm(self,gpuhostid,vm_vgpu_type,rcapacity):
-        hhosts = list_hosts(
-               self.apiclient,
-               hypervisor="XenServer",
-               id=gpuhostid
-               )
-        self.assertEqual(
-                            isinstance(hhosts, list),
-                            True,
-                            "Check list hosts response returns a valid list"
-                        )
-
-        self.assertNotEqual(
-                            len(hhosts),
-                            0,
-                            "Check Host details are available in List Hosts"
-                        )
-        for ggroup in hhosts:
-               if ggroup.ipaddress not in self.nongpuhosts:
-                  for gp in ggroup.gpugroup:
-                      #if gp.gpugroupname == "Group of NVIDIA Corporation 
GK104GL [GRID K2] GPUs":
-                         for gptype in gp.vgpu:
-                             if gptype.vgputype==vm_vgpu_type:
-                                self.debug("Latest remainingcapacity is %s and 
before remainingcapacity is %s"%(gptype.remainingcapacity,rcapacity))
-                                if gptype.remainingcapacity != rcapacity+1:
-                                   self.fail("Host capacity is not updated 
.GPU resources should be released when VM is stopped/Destroyed ")
-        return
-
-    def check_vm_state(self,vmid):
-        list_vm_response = list_virtual_machines(
-                                                     self.apiclient,
-                                                     id=vmid
-                                                     )
-
-        if list_vm_response is None:
-            return("Expunge")
-        return(list_vm_response[0].state)
-
-    def check_host_vgpu_remaining_capacity(self,gpuhostid,gtype):
-        gputhosts = list_hosts(
-               self.apiclient,
-               hypervisor="XenServer",
-               id=gpuhostid
-               )
-        vgpucapacity=0
-        for ghost in gputhosts:
-            if ghost.gpugroup is not None:
-                        for gp in ghost.gpugroup:
-                            #if gp.gpugroupname == gpucard:
-                               for gptype in gp.vgpu:
-                                   if gptype.vgputype == gtype:
-                                      
vgpucapacity=vgpucapacity+gptype.remainingcapacity
-
-        return(vgpucapacity)
-
-    def verify_vm(self,vm_gpu_card):
-        if(vm_gpu_card):
-          vm_gpu_card.getState(
-                                   self.apiclient,
-                                   "Running")
-
-          
self.check_for_vGPU_resource(vm_gpu_card.hostid,vm_gpu_card.instancename,vm_gpu_card.serviceofferingid,vm_gpu_card.vgpu)
-
-    def stop_life_cycle_vm (self,vm_gpu_card):
-
-        if(vm_gpu_card):
-          vm_gpu_card.stop(self.apiclient)
-          time.sleep(self.testdata["vgpu"]["sleep"])
-          vm_gpu_card.getState(
-                                   self.apiclient,
-                                   "Stopped")
-
-    def start_life_cycle_vm(self,vm_gpu_card):
-
-        if(vm_gpu_card):
-          vm_gpu_card.start(self.apiclient)
-          time.sleep(self.testdata["vgpu"]["sleep"])
-
-    def restore_life_cycle_vm(self,vm_gpu_card):
-        if(vm_gpu_card):
-          vm_gpu_card.restore(self.apiclient)
-          time.sleep(self.testdata["vgpu"]["sleep"])
-
-    def reboot_life_cycle_vm(self,vm_gpu_card):
-
-        if(vm_gpu_card):
-          vm_gpu_card.reboot(self.apiclient)
-          time.sleep(self.testdata["vgpu"]["sleep"])
-
-    def delete_vm_life_cycle_vm(self,vm_gpu_card):
-        if(vm_gpu_card):
-          vm_gpu_card.delete(self.apiclient)
-          time.sleep(self.testdata["vgpu"]["sleep"])
-          vm_gpu_card.getState(
-                                   self.apiclient,
-                                   "Destroyed")
-
-    def recover_vm_life_cycle_vm(self,vm_gpu_card):
-        if(vm_gpu_card):
-          vm_gpu_card.recover(self.apiclient)
-          vm_gpu_card.getState(
-                                   self.apiclient,
-                                   "Stopped")
-
-
-    def recovervm(self,vm_gpu_card):
-        if self.check_vm_state(vm_gpu_card.id)=="Expunge":
-            raise unittest.SkipTest("VM is already deleted hence skipping")
-        self.recover_vm_life_cycle_vm(vm_gpu_card)
-        self.start_life_cycle_vm(vm_gpu_card)
-        self.verify_vm(vm_gpu_card)
-        return
-
-
-    def startvm(self,vm_gpu_card):
-
-        self.start_life_cycle_vm(vm_gpu_card)
-        self.verify_vm(vm_gpu_card)
-        return
-
-    def stopvm(self,vm_gpu_card):
-
-        
rcapacity=self.check_host_vgpu_remaining_capacity(vm_gpu_card.hostid,vm_gpu_card.vgpu)
-        self.stop_life_cycle_vm(vm_gpu_card)
-        
self.check_gpu_resources_released_vm(vm_gpu_card.hostid,vm_gpu_card.vgpu,rcapacity)
-        return
-
-    def deletevm(self,vm_gpu_card):
-
-        
rcapacity=self.check_host_vgpu_remaining_capacity(vm_gpu_card.hostid,vm_gpu_card.vgpu)
-        hostid=vm_gpu_card.hostid
-        vgputype=vm_gpu_card.vgpu
-        self.delete_vm_life_cycle_vm(vm_gpu_card)
-        self.check_gpu_resources_released_vm(hostid,vgputype,rcapacity)
-        return
-
-    def restorevm(self,vm_gpu_card):
-
-        self.restore_life_cycle_vm(vm_gpu_card)
-        self.verify_vm(vm_gpu_card)
-        return
-
-
-    def rebootvm(self,vm_vgpu_card):
-
-        self.reboot_life_cycle_vm(vm_vgpu_card)
-        self.verify_vm(vm_vgpu_card)
-        return
-
-
     def test_01_list_vgpu_host_details(self):
         """   list vGPU host details  """
         hhosts = list_hosts(
@@ -1770,6 +1494,7 @@ class TestvGPUWindowsVm(cloudstackTestCase):
 
         self.debug("Check if deployed VMs are in running state?")
 
+
         if self.__class__.vm_k1_card is not None:
             self.verify_vm(self.__class__.vm_k1_card)
 
@@ -1779,6 +1504,7 @@ class TestvGPUWindowsVm(cloudstackTestCase):
         if self.__class__.vm2_k2_card is not None:
             self.verify_vm(self.__class__.vm2_k2_card)
 
+
         self.__class__.vmlifecycletest=1
         return
 
@@ -1789,6 +1515,7 @@ class TestvGPUWindowsVm(cloudstackTestCase):
         if self.__class__.vmlifecycletest==0:
             raise unittest.SkipTest("VM Life Cycle Deploy VM test failed hence 
skipping")
 
+
         if self.__class__.vm_k1_card:
             self.stopvm(self.__class__.vm_k1_card)
 
@@ -1798,6 +1525,7 @@ class TestvGPUWindowsVm(cloudstackTestCase):
         if self.__class__.vm2_k2_card:
             self.stopvm(self.__class__.vm2_k2_card)
 
+
         return
 
     @attr(tags = ['advanced', 'basic' , 'vgpu'], required_hardware="true")
@@ -1807,6 +1535,7 @@ class TestvGPUWindowsVm(cloudstackTestCase):
         if self.__class__.vmlifecycletest==0:
             raise unittest.SkipTest("VM Life Cycle Deploy VM test failed hence 
skipping")
 
+
         if self.__class__.vm_k1_card:
             self.startvm(self.__class__.vm_k1_card)
 
@@ -1826,6 +1555,7 @@ class TestvGPUWindowsVm(cloudstackTestCase):
         if self.__class__.vmlifecycletest==0:
             raise unittest.SkipTest("VM Life Cycle Deploy VM test failed hence 
skipping")
 
+
         if self.__class__.vm_k1_card:
             self.restorevm(self.__class__.vm_k1_card)
         if self.__class__.vm_k2_card:
@@ -1833,6 +1563,7 @@ class TestvGPUWindowsVm(cloudstackTestCase):
         if self.__class__.vm2_k2_card:
             self.restorevm(self.__class__.vm2_k2_card)
 
+
         return
 
     @attr(tags = ['advanced', 'basic' , 'vgpu'], required_hardware="true")
@@ -2052,11 +1783,6 @@ class TestvGPUWindowsVm(cloudstackTestCase):
             self.deletevm(self.__class__.nonvgpu)
 
         self.cleanup.append(self.__class__.nonvgpu_service_offerin)
-
-        self.deletevm(self.__class__.vm_k1_card)
-        self.deletevm(self.__class__.vm_k2_card)
-        self.deletevm(self.__class__.vm2_k2_card)
-
         self.cleanup.append(self.__class__.k100_vgpu_service_offering)
         self.cleanup.append(self.__class__.k200_vgpu_service_offering)
 
@@ -2233,3 +1959,6 @@ class TestvGPUWindowsVm(cloudstackTestCase):
         except Exception as e:
             self.debug("Warning! Exception in tearDown: %s" % e)
 
+
+
+

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/utils/src/com/cloud/utils/xmlobject/XmlObject.java
----------------------------------------------------------------------
diff --git a/utils/src/com/cloud/utils/xmlobject/XmlObject.java 
b/utils/src/com/cloud/utils/xmlobject/XmlObject.java
index e4e4363..42af945 100755
--- a/utils/src/com/cloud/utils/xmlobject/XmlObject.java
+++ b/utils/src/com/cloud/utils/xmlobject/XmlObject.java
@@ -27,10 +27,12 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.logging.Logger;
 
 import com.cloud.utils.exception.CloudRuntimeException;
 
 public class XmlObject {
+    private final Logger logger = Logger.getLogger(XmlObject.class.getName());
     private final Map<String, Object> elements = new HashMap<String, Object>();
     private String text;
     private String tag;
@@ -38,6 +40,10 @@ public class XmlObject {
     XmlObject() {
     }
 
+    public void removeAllChildren() {
+        elements.clear();
+    }
+
     public XmlObject(String tag) {
         this.tag = tag;
     }
@@ -99,8 +105,12 @@ public class XmlObject {
         if (e instanceof List) {
             return (List<T>)e;
         }
+
         List lst = new ArrayList(1);
-        lst.add(e);
+        if (e != null) {
+            lst.add(e);
+        }
+
         return lst;
     }
 
@@ -142,7 +152,8 @@ public class XmlObject {
         }
 
         if (!children.isEmpty() && text != null) {
-            throw new CloudRuntimeException(String.format("element %s cannot 
have both text[%s] and child elements", tag, text));
+            logger.info(String.format("element %s cannot have both text[%s] 
and child elements, set text to null", tag, text));
+            text = null;
         }
 
         if (!children.isEmpty()) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/utils/src/com/cloud/utils/xmlobject/XmlObjectParser.java
----------------------------------------------------------------------
diff --git a/utils/src/com/cloud/utils/xmlobject/XmlObjectParser.java 
b/utils/src/com/cloud/utils/xmlobject/XmlObjectParser.java
old mode 100644
new mode 100755
index 321af0c..f0e8ce3
--- a/utils/src/com/cloud/utils/xmlobject/XmlObjectParser.java
+++ b/utils/src/com/cloud/utils/xmlobject/XmlObjectParser.java
@@ -19,6 +19,13 @@
 
 package com.cloud.utils.xmlobject;
 
+import com.cloud.utils.exception.CloudRuntimeException;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
 import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -26,15 +33,6 @@ import java.io.FileNotFoundException;
 import java.io.InputStream;
 import java.util.Stack;
 
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-import com.cloud.utils.exception.CloudRuntimeException;
-
 public class XmlObjectParser {
     final private InputStream is;
 
@@ -109,7 +107,11 @@ public class XmlObjectParser {
     public static XmlObject parseFromString(String xmlString) {
         InputStream stream = new ByteArrayInputStream(xmlString.getBytes());
         XmlObjectParser p = new XmlObjectParser(stream);
-        return p.parse();
+        XmlObject obj = p.parse();
+        if (obj.getText() != null && obj.getText().replaceAll("\\n", 
"").replaceAll("\\r", "").replaceAll(" ", "").isEmpty()) {
+            obj.setText(null);
+        }
+        return obj;
     }
 
     private XmlObject parse() {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/1de0cb70/utils/test/com/cloud/utils/xmlobject/TestXmlObject.java
----------------------------------------------------------------------
diff --git a/utils/test/com/cloud/utils/xmlobject/TestXmlObject.java 
b/utils/test/com/cloud/utils/xmlobject/TestXmlObject.java
old mode 100644
new mode 100755
index cbd24b0..faaf980
--- a/utils/test/com/cloud/utils/xmlobject/TestXmlObject.java
+++ b/utils/test/com/cloud/utils/xmlobject/TestXmlObject.java
@@ -43,6 +43,11 @@ public class TestXmlObject {
                 }
             }
             */
+
+        XmlObject xml = new XmlObject("vlan").putElement("vlan-id", 
String.valueOf(19)).putElement("tagged",
+                new XmlObject("teng").putElement("name", "0/0")
+        ).putElement("shutdown", "false");
+        System.out.println(xml.toString());
     }
 
 }

Reply via email to