You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ki...@apache.org on 2013/01/31 18:07:19 UTC

[12/43] CloudStack CLOUDSTACK-774 Supporting kickstart in CloudStack baremetal

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1f7eaf3d/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpManagerImpl.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpManagerImpl.java
new file mode 100755
index 0000000..ae8482c
--- /dev/null
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpManagerImpl.java
@@ -0,0 +1,323 @@
+// 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
+// Apache License, Version 2.0 (the "License"); you may not use this
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// 
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.baremetal.networkservice;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.Local;
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StartupExternalDhcpCommand;
+import com.cloud.agent.api.routing.DhcpEntryCommand;
+import com.cloud.baremetal.database.BaremetalDhcpDao;
+import com.cloud.baremetal.database.BaremetalDhcpVO;
+import com.cloud.dc.DataCenter;
+import com.cloud.dc.DataCenterVO;
+import com.cloud.dc.HostPodVO;
+import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.dc.dao.HostPodDao;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.host.Host;
+import com.cloud.host.Host.Type;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.network.Network;
+import com.cloud.network.PhysicalNetworkServiceProvider;
+import com.cloud.network.PhysicalNetworkVO;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
+import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
+import com.cloud.resource.ResourceManager;
+import com.cloud.resource.ResourceStateAdapter;
+import com.cloud.resource.ServerResource;
+import com.cloud.resource.UnableDeleteHostException;
+import com.cloud.utils.component.Inject;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.SearchCriteria.Op;
+import com.cloud.utils.db.SearchCriteria2;
+import com.cloud.utils.db.SearchCriteriaService;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachineProfile;
+import com.cloud.vm.dao.NicDao;
+import com.cloud.vm.dao.UserVmDao;
+
+@Local(value = { BaremetalDhcpManager.class })
+public class BaremetalDhcpManagerImpl implements BaremetalDhcpManager, ResourceStateAdapter {
+    private static final org.apache.log4j.Logger s_logger = Logger.getLogger(BaremetalDhcpManagerImpl.class);
+    protected String _name;
+    @Inject
+    DataCenterDao _dcDao;
+    @Inject
+    HostDao _hostDao;
+    @Inject
+    AgentManager _agentMgr;
+    @Inject
+    HostPodDao _podDao;
+    @Inject
+    UserVmDao _userVmDao;
+    @Inject
+    ResourceManager _resourceMgr;
+    @Inject
+    NicDao _nicDao;
+    @Inject
+    PhysicalNetworkDao _physicalNetworkDao;
+    @Inject
+    PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
+    @Inject
+    BaremetalDhcpDao _extDhcpDao;
+
+    @Override
+    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+        _resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
+        return true;
+    }
+
+    @Override
+    public boolean start() {
+        return true;
+    }
+
+    @Override
+    public boolean stop() {
+        _resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName());
+        return true;
+    }
+
+    @Override
+    public String getName() {
+        return _name;
+    }
+
+    protected String getDhcpServerGuid(String zoneId, String name, String ip) {
+        return zoneId + "-" + name + "-" + ip;
+    }
+
+    @Override
+    public boolean addVirtualMachineIntoNetwork(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> profile,
+            DeployDestination dest, ReservationContext context) throws ResourceUnavailableException {
+        Long zoneId = profile.getVirtualMachine().getDataCenterIdToDeployIn();
+        Long podId = profile.getVirtualMachine().getPodIdToDeployIn();
+        List<HostVO> hosts = _resourceMgr.listAllUpAndEnabledHosts(Type.BaremetalDhcp, null, podId, zoneId);
+        if (hosts.size() == 0) {
+            throw new CloudRuntimeException("No external Dhcp found in zone " + zoneId + " pod " + podId);
+        }
+
+        if (hosts.size() > 1) {
+            throw new CloudRuntimeException("Something wrong, more than 1 external Dhcp found in zone " + zoneId + " pod " + podId);
+        }
+
+        HostVO h = hosts.get(0);
+        String dns = nic.getDns1();
+        if (dns == null) {
+            dns = nic.getDns2();
+        }
+        DhcpEntryCommand dhcpCommand = new DhcpEntryCommand(nic.getMacAddress(), nic.getIp4Address(), profile.getVirtualMachine().getHostName(), dns,
+                nic.getGateway());
+        String errMsg = String.format("Set dhcp entry on external DHCP %1$s failed(ip=%2$s, mac=%3$s, vmname=%4$s)", h.getPrivateIpAddress(),
+                nic.getIp4Address(), nic.getMacAddress(), profile.getVirtualMachine().getHostName());
+        // prepareBareMetalDhcpEntry(nic, dhcpCommand);
+        try {
+            Answer ans = _agentMgr.send(h.getId(), dhcpCommand);
+            if (ans.getResult()) {
+                s_logger.debug(String.format("Set dhcp entry on external DHCP %1$s successfully(ip=%2$s, mac=%3$s, vmname=%4$s)", h.getPrivateIpAddress(),
+                        nic.getIp4Address(), nic.getMacAddress(), profile.getVirtualMachine().getHostName()));
+                return true;
+            } else {
+                s_logger.debug(errMsg + " " + ans.getDetails());
+                throw new ResourceUnavailableException(errMsg, DataCenter.class, zoneId);
+            }
+        } catch (Exception e) {
+            s_logger.debug(errMsg, e);
+            throw new ResourceUnavailableException(errMsg + e.getMessage(), DataCenter.class, zoneId);
+        }
+    }
+
+    @Override
+    public HostVO createHostVOForConnectedAgent(HostVO host, StartupCommand[] cmd) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public HostVO createHostVOForDirectConnectAgent(HostVO host, StartupCommand[] startup, ServerResource resource, Map<String, String> details,
+            List<String> hostTags) {
+        if (!(startup[0] instanceof StartupExternalDhcpCommand)) {
+            return null;
+        }
+
+        host.setType(Host.Type.BaremetalDhcp);
+        return host;
+    }
+
+    @Override
+    public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+
+    @Override
+    @DB
+    public BaremetalDhcpVO addDchpServer(AddBaremetalDhcpCmd cmd) {
+        PhysicalNetworkVO pNetwork = null;
+        long zoneId;
+
+        if (cmd.getPhysicalNetworkId() == null || cmd.getUrl() == null || cmd.getUsername() == null || cmd.getPassword() == null) {
+            throw new IllegalArgumentException("At least one of the required parameters(physical network id, url, username, password) is null");
+        }
+
+        pNetwork = _physicalNetworkDao.findById(cmd.getPhysicalNetworkId());
+        if (pNetwork == null) {
+            throw new IllegalArgumentException("Could not find phyical network with ID: " + cmd.getPhysicalNetworkId());
+        }
+        zoneId = pNetwork.getDataCenterId();
+        DataCenterVO zone = _dcDao.findById(zoneId);
+
+        PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(),
+        		BaremetalDhcpManager.BAREMETAL_DHCP_SERVICE_PROVIDER.getName());
+        if (ntwkSvcProvider == null) {
+            throw new CloudRuntimeException("Network Service Provider: " + BaremetalDhcpManager.BAREMETAL_DHCP_SERVICE_PROVIDER.getName() + " is not enabled in the physical network: "
+                    + cmd.getPhysicalNetworkId() + "to add this device");
+        } else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
+            throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName()
+                    + " is in shutdown state in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
+        }
+
+        HostPodVO pod = _podDao.findById(cmd.getPodId());
+        if (pod == null) {
+            throw new IllegalArgumentException("Could not find pod with ID: " + cmd.getPodId());
+        }
+
+        List<HostVO> dhcps = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.BaremetalDhcp, null, cmd.getPodId(), zoneId);
+        if (dhcps.size() != 0) {
+            throw new IllegalArgumentException("Already had a DHCP server in Pod: " + cmd.getPodId() + " zone: " + zoneId);
+        }
+
+        URI uri;
+        try {
+            uri = new URI(cmd.getUrl());
+        } catch (Exception e) {
+            s_logger.debug(e);
+            throw new IllegalArgumentException(e.getMessage());
+        }
+
+        String ipAddress = uri.getHost();
+        String guid = getDhcpServerGuid(Long.toString(zoneId) + "-" + Long.toString(cmd.getPodId()), "ExternalDhcp", ipAddress);
+        Map params = new HashMap<String, String>();
+        params.put("type", cmd.getDhcpType());
+        params.put("zone", Long.toString(zoneId));
+        params.put("pod", cmd.getPodId().toString());
+        params.put("ip", ipAddress);
+        params.put("username", cmd.getUsername());
+        params.put("password", cmd.getPassword());
+        params.put("guid", guid);
+        params.put("gateway", pod.getGateway());
+        String dns = zone.getDns1();
+        if (dns == null) {
+            dns = zone.getDns2();
+        }
+        params.put("dns", dns);
+
+        ServerResource resource = null;
+        try {
+            if (cmd.getDhcpType().equalsIgnoreCase(BaremetalDhcpType.DNSMASQ.toString())) {
+                resource = new BaremetalDnsmasqResource();
+                resource.configure("Dnsmasq resource", params);
+            } else if (cmd.getDhcpType().equalsIgnoreCase(BaremetalDhcpType.DHCPD.toString())) {
+                resource = new BaremetalDhcpdResource();
+                resource.configure("Dhcpd resource", params);
+            } else {
+                throw new CloudRuntimeException("Unsupport DHCP server type: " + cmd.getDhcpType());
+            }
+        } catch (Exception e) {
+            s_logger.debug(e);
+            throw new CloudRuntimeException(e.getMessage());
+        }
+
+        Host dhcpServer = _resourceMgr.addHost(zoneId, resource, Host.Type.BaremetalDhcp, params);
+        if (dhcpServer == null) {
+            throw new CloudRuntimeException("Cannot add external Dhcp server as a host");
+        }
+
+        BaremetalDhcpVO vo = new BaremetalDhcpVO();
+        vo.setDeviceType(cmd.getDhcpType());
+        vo.setHostId(dhcpServer.getId());
+        vo.setNetworkServiceProviderId(ntwkSvcProvider.getId());
+        vo.setPhysicalNetworkId(cmd.getPhysicalNetworkId());
+        vo.setPodId(cmd.getPodId());
+        Transaction txn = Transaction.currentTxn();
+        txn.start();
+        _extDhcpDao.persist(vo);
+        txn.commit();
+        return vo;
+    }
+
+    @Override
+    public BaremetalDhcpResponse generateApiResponse(BaremetalDhcpVO vo) {
+        BaremetalDhcpResponse response = new BaremetalDhcpResponse();
+        response.setDeviceType(vo.getDeviceType());
+        response.setId(String.valueOf(vo.getId()));
+        response.setPhysicalNetworkId(String.valueOf(vo.getPhysicalNetworkId()));
+        response.setProviderId(String.valueOf(vo.getNetworkServiceProviderId()));
+        return response;
+    }
+
+    @Override
+    public List<BaremetalDhcpResponse> listBaremetalDhcps(ListBaremetalDhcpCmd cmd) {
+        SearchCriteriaService<BaremetalDhcpVO, BaremetalDhcpVO> sc = SearchCriteria2.create(BaremetalDhcpVO.class);
+        if (cmd.getDeviceType() != null) {
+        	sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, cmd.getDeviceType());
+        }
+        if (cmd.getPodId() != null) {
+            sc.addAnd(sc.getEntity().getPodId(), Op.EQ, cmd.getPodId());
+            if (cmd.getId() != null) {
+                sc.addAnd(sc.getEntity().getId(), Op.EQ, cmd.getId());
+            }
+        }
+        List<BaremetalDhcpVO> vos = sc.list();
+        List<BaremetalDhcpResponse> responses = new ArrayList<BaremetalDhcpResponse>(vos.size());
+        for (BaremetalDhcpVO vo : vos) {
+            responses.add(generateApiResponse(vo));
+        }
+        return responses;
+    }
+
+	@Override
+	public List<Class<?>> getCommands() {
+		return null;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1f7eaf3d/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpResourceBase.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpResourceBase.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpResourceBase.java
new file mode 100644
index 0000000..0541415
--- /dev/null
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpResourceBase.java
@@ -0,0 +1,174 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+// 
+//   http://www.apache.org/licenses/LICENSE-2.0
+// 
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+// 
+// Automatically generated by addcopyright.py at 01/29/2013
+// Apache License, Version 2.0 (the "License"); you may not use this
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// 
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.baremetal.networkservice;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.IAgentControl;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.PingCommand;
+import com.cloud.agent.api.PingRoutingCommand;
+import com.cloud.agent.api.ReadyAnswer;
+import com.cloud.agent.api.ReadyCommand;
+import com.cloud.agent.api.StartupCommand;
+import com.cloud.agent.api.StartupExternalDhcpCommand;
+import com.cloud.agent.api.StartupPxeServerCommand;
+import com.cloud.host.Host.Type;
+import com.cloud.resource.ServerResource;
+import com.cloud.utils.script.Script;
+import com.cloud.utils.ssh.SSHCmdHelper;
+import com.cloud.vm.VirtualMachine.State;
+import com.trilead.ssh2.SCPClient;
+
+public class BaremetalDhcpResourceBase implements ServerResource {
+	private static final Logger s_logger = Logger.getLogger(BaremetalDhcpResourceBase.class);
+	String _name;
+	String _guid;
+	String _username;
+	String _password;
+	String _ip;
+	String _zoneId;
+	String _podId;
+	String _gateway;
+	String _dns;
+	
+	@Override
+	public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+		_name = name;
+		_guid = (String)params.get("guid");
+		_ip = (String)params.get("ip");
+		_username = (String)params.get("username");
+		_password = (String)params.get("password");
+		_zoneId = (String)params.get("zone");
+		_podId = (String)params.get("pod");
+		_gateway = (String)params.get("gateway");
+		_dns = (String)params.get("dns");
+		
+		if (_guid == null) {
+			throw new ConfigurationException("No Guid specified");
+		}
+		
+		if (_zoneId == null) {
+			throw new ConfigurationException("No Zone specified");
+		}
+		
+		if (_podId == null) {
+			throw new ConfigurationException("No Pod specified");
+		}
+		
+		if (_ip == null) {
+			throw new ConfigurationException("No IP specified");
+		}
+		
+		if (_username == null) {
+			throw new ConfigurationException("No username specified");
+		}
+		
+		if (_password == null) {
+			throw new ConfigurationException("No password specified");
+		}
+		
+		if (_gateway == null) {
+			throw new ConfigurationException("No gateway specified");
+		}
+		
+		if (_dns == null) {
+			throw new ConfigurationException("No dns specified");
+		}
+		
+		return true;
+	}
+
+	@Override
+	public boolean start() {
+		return true;
+	}
+
+	@Override
+	public boolean stop() {
+		return true;
+	}
+
+	@Override
+	public String getName() {
+		return _name;
+	}
+
+	@Override
+	public Type getType() {
+		return Type.BaremetalDhcp;
+	}
+
+	@Override
+	public StartupCommand[] initialize() {
+		StartupExternalDhcpCommand cmd = new StartupExternalDhcpCommand();
+		cmd.setName(_name);
+		cmd.setDataCenter(_zoneId);
+		cmd.setPod(_podId);
+		cmd.setPrivateIpAddress(_ip);
+		cmd.setStorageIpAddress("");
+		cmd.setVersion("");
+		cmd.setGuid(_guid);
+		return new StartupCommand[]{cmd};
+	}
+
+	@Override
+	public PingCommand getCurrentStatus(long id) {
+		//TODO: check server
+		return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
+	}
+
+	protected ReadyAnswer execute(ReadyCommand cmd) {
+		s_logger.debug("External DHCP resource " + _name + " is ready");
+		return new ReadyAnswer(cmd);
+	}
+	
+	@Override
+	public Answer executeRequest(Command cmd) {
+		if (cmd instanceof ReadyCommand) {
+			return execute((ReadyCommand) cmd);
+		} else {
+			return Answer.createUnsupportedCommandAnswer(cmd);
+		}
+	}
+
+	@Override
+	public void disconnected() {
+	}
+
+	@Override
+	public IAgentControl getAgentControl() {
+		return null;
+	}
+
+	@Override
+	public void setAgentControl(IAgentControl agentControl) {
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1f7eaf3d/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpResponse.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpResponse.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpResponse.java
new file mode 100755
index 0000000..952ac41
--- /dev/null
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpResponse.java
@@ -0,0 +1,71 @@
+// 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 org.apache.cloudstack.api.ApiConstants;
+import org.apache.cloudstack.api.BaseResponse;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+public class BaremetalDhcpResponse extends BaseResponse {
+    @SerializedName(ApiConstants.ID) @Param(description="device id of ")
+    private String id;
+    
+    @SerializedName(ApiConstants.PHYSICAL_NETWORK_ID) @Param(description="the physical network to which this external dhcp device belongs to")
+    private String physicalNetworkId;
+    
+    @SerializedName(ApiConstants.PROVIDER) @Param(description="name of the provider")
+    private String providerId;
+    
+    @SerializedName(ApiConstants.DHCP_SERVER_TYPE) @Param(description="name of the provider")
+    private String deviceType;
+
+    public String getId() {
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	public String getPhysicalNetworkId() {
+		return physicalNetworkId;
+	}
+
+	public void setPhysicalNetworkId(String physicalNetworkId) {
+		this.physicalNetworkId = physicalNetworkId;
+	}
+
+	public String getProviderId() {
+		return providerId;
+	}
+
+	public void setProviderId(String providerId) {
+		this.providerId = providerId;
+	}
+
+	public String getDeviceType() {
+        return deviceType;
+    }
+
+    public void setDeviceType(String deviceType) {
+        this.deviceType = deviceType;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1f7eaf3d/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpdResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpdResource.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpdResource.java
new file mode 100755
index 0000000..a27a6f2
--- /dev/null
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDhcpdResource.java
@@ -0,0 +1,139 @@
+// 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
+// Apache License, Version 2.0 (the "License"); you may not use this
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// 
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.baremetal.networkservice;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.PingCommand;
+import com.cloud.agent.api.PingRoutingCommand;
+import com.cloud.agent.api.routing.DhcpEntryCommand;
+import com.cloud.utils.script.Script;
+import com.cloud.utils.ssh.SSHCmdHelper;
+import com.cloud.vm.VirtualMachine.State;
+import com.trilead.ssh2.SCPClient;
+
+public class BaremetalDhcpdResource extends BaremetalDhcpResourceBase {
+	private static final Logger s_logger = Logger.getLogger(BaremetalDhcpdResource.class);
+	
+	public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+		com.trilead.ssh2.Connection sshConnection = null;
+		try {
+			super.configure(name, params);
+			s_logger.debug(String.format("Trying to connect to DHCP server(IP=%1$s, username=%2$s, password=%3$s)", _ip, _username, "******"));
+			sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
+			if (sshConnection == null) {
+				throw new ConfigurationException(
+						String.format("Cannot connect to DHCP server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username, "******"));
+			}
+
+			if (!SSHCmdHelper.sshExecuteCmd(sshConnection, "[ -f '/usr/sbin/dhcpd' ]")) {
+				throw new ConfigurationException("Cannot find dhcpd.conf /etc/dhcpd.conf at  on " + _ip);
+			}
+
+			SCPClient scp = new SCPClient(sshConnection);
+
+			String editHosts = "scripts/network/exdhcp/dhcpd_edithosts.py";
+			String editHostsPath = Script.findScript("", editHosts);
+			if (editHostsPath == null) {
+				throw new ConfigurationException("Can not find script dnsmasq_edithosts.sh at " + editHosts);
+			}
+			scp.put(editHostsPath, "/usr/bin/", "0755");
+			
+			String prepareDhcpdScript = "scripts/network/exdhcp/prepare_dhcpd.sh";
+			String prepareDhcpdScriptPath = Script.findScript("", prepareDhcpdScript);
+			if (prepareDhcpdScriptPath == null) {
+				throw new ConfigurationException("Can not find prepare_dhcpd.sh at " + prepareDhcpdScriptPath);
+			}
+			scp.put(prepareDhcpdScriptPath, "/usr/bin/", "0755");
+			
+			//TODO: tooooooooooooooo ugly here!!!
+			String[] ips = _ip.split("\\.");
+			ips[3] = "0";
+			StringBuffer buf = new StringBuffer();
+			int i;
+			for (i=0;i<ips.length-1;i++) {
+				buf.append(ips[i]).append(".");
+			}
+			buf.append(ips[i]);
+			String subnet = buf.toString();
+			String cmd = String.format("sh /usr/bin/prepare_dhcpd.sh %1$s", subnet);
+			if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) {
+				throw new ConfigurationException("prepare Dhcpd at " + _ip + " failed, command:" + cmd);
+			}	
+			
+			s_logger.debug("Dhcpd resource configure successfully");
+			return true;
+		} catch (Exception e) {
+			s_logger.debug("Dhcpd resorce configure failed", e);
+			throw new ConfigurationException(e.getMessage());
+		} finally {
+			SSHCmdHelper.releaseSshConnection(sshConnection);
+		}
+	}
+	
+	@Override
+	public PingCommand getCurrentStatus(long id) {
+		com.trilead.ssh2.Connection sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
+		if (sshConnection == null) {
+			return null;
+		} else {
+			SSHCmdHelper.releaseSshConnection(sshConnection);
+			return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
+		}
+	}
+	
+	Answer execute(DhcpEntryCommand cmd) {
+		com.trilead.ssh2.Connection sshConnection = null;
+		try {
+			sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
+			if (sshConnection == null) {
+				return new Answer(cmd, false, "ssh authenticate failed");
+			}
+			String addDhcp = String.format("python /usr/bin/dhcpd_edithosts.py %1$s %2$s %3$s %4$s %5$s %6$s",
+					cmd.getVmMac(), cmd.getVmIpAddress(), cmd.getVmName(), cmd.getDns(), cmd.getGateway(), cmd.getNextServer());
+			if (!SSHCmdHelper.sshExecuteCmd(sshConnection, addDhcp)) {
+				return new Answer(cmd, false, "add Dhcp entry failed");
+			} else {
+				return new Answer(cmd);
+			}
+		} finally {
+			SSHCmdHelper.releaseSshConnection(sshConnection);
+		}
+	}
+	
+	@Override
+	public Answer executeRequest(Command cmd) {
+		if (cmd instanceof DhcpEntryCommand) {
+			return execute((DhcpEntryCommand)cmd);
+		} else {
+			return super.executeRequest(cmd);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1f7eaf3d/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDnsmasqResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDnsmasqResource.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDnsmasqResource.java
new file mode 100644
index 0000000..6841c525
--- /dev/null
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalDnsmasqResource.java
@@ -0,0 +1,129 @@
+// 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
+// Apache License, Version 2.0 (the "License"); you may not use this
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// 
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.baremetal.networkservice;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.PingCommand;
+import com.cloud.agent.api.PingRoutingCommand;
+import com.cloud.agent.api.routing.DhcpEntryCommand;
+import com.cloud.utils.script.Script;
+import com.cloud.utils.ssh.SSHCmdHelper;
+import com.cloud.vm.VirtualMachine.State;
+import com.trilead.ssh2.SCPClient;
+
+public class BaremetalDnsmasqResource extends BaremetalDhcpResourceBase {
+	private static final Logger s_logger = Logger.getLogger(BaremetalDnsmasqResource.class);
+
+	public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+		com.trilead.ssh2.Connection sshConnection = null;
+		try {
+			super.configure(name, params);
+			s_logger.debug(String.format("Trying to connect to DHCP server(IP=%1$s, username=%2$s, password=%3$s)", _ip, _username, _password));
+			sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
+			if (sshConnection == null) {
+				throw new ConfigurationException(
+						String.format("Cannot connect to DHCP server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username, _password));
+			}
+
+			if (!SSHCmdHelper.sshExecuteCmd(sshConnection, "[ -f '/usr/sbin/dnsmasq' ]")) {
+				throw new ConfigurationException("Cannot find dnsmasq at /usr/sbin/dnsmasq on " + _ip);
+			}
+
+			SCPClient scp = new SCPClient(sshConnection);
+			
+			String editHosts = "scripts/network/exdhcp/dnsmasq_edithosts.sh";
+			String editHostsPath = Script.findScript("", editHosts);
+			if (editHostsPath == null) {
+				throw new ConfigurationException("Can not find script dnsmasq_edithosts.sh at " + editHosts);
+			}
+			scp.put(editHostsPath, "/usr/bin/", "0755");
+			
+			String prepareDnsmasq = "scripts/network/exdhcp/prepare_dnsmasq.sh";
+			String prepareDnsmasqPath = Script.findScript("", prepareDnsmasq);
+			if (prepareDnsmasqPath == null) {
+				throw new ConfigurationException("Can not find script prepare_dnsmasq.sh at " + prepareDnsmasq);
+			}
+			scp.put(prepareDnsmasqPath, "/usr/bin/", "0755");
+			
+			String prepareCmd = String.format("sh /usr/bin/prepare_dnsmasq.sh %1$s %2$s %3$s", _gateway, _dns, _ip);
+			if (!SSHCmdHelper.sshExecuteCmd(sshConnection, prepareCmd)) {
+				throw new ConfigurationException("prepare dnsmasq at " + _ip + " failed");
+			}
+			
+			s_logger.debug("Dnsmasq resource configure successfully");
+			return true;
+		} catch (Exception e) {
+			s_logger.debug("Dnsmasq resorce configure failed", e);
+			throw new ConfigurationException(e.getMessage());
+		} finally {
+			SSHCmdHelper.releaseSshConnection(sshConnection);
+		}
+	}
+	
+	@Override
+	public PingCommand getCurrentStatus(long id) {
+		com.trilead.ssh2.Connection sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
+		if (sshConnection == null) {
+			return null;
+		} else {
+			SSHCmdHelper.releaseSshConnection(sshConnection);
+			return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
+		}
+	}
+
+	Answer execute(DhcpEntryCommand cmd) {
+		com.trilead.ssh2.Connection sshConnection = null;
+		try {
+			sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
+			if (sshConnection == null) {
+				return new Answer(cmd, false, "ssh authenticate failed");
+			}
+			String addDhcp = String.format("/usr/bin/dnsmasq_edithosts.sh %1$s %2$s %3$s", cmd.getVmMac(), cmd.getVmIpAddress(), cmd.getVmName());
+			if (!SSHCmdHelper.sshExecuteCmd(sshConnection, addDhcp)) {
+				return new Answer(cmd, false, "add Dhcp entry failed");
+			} else {
+				return new Answer(cmd);
+			}
+		} finally {
+			SSHCmdHelper.releaseSshConnection(sshConnection);
+		}
+	}
+	
+	@Override
+	public Answer executeRequest(Command cmd) {
+		if (cmd instanceof DhcpEntryCommand) {
+			return execute((DhcpEntryCommand)cmd);
+		} else {
+			return super.executeRequest(cmd);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1f7eaf3d/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
new file mode 100755
index 0000000..938b3ac
--- /dev/null
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartPxeResource.java
@@ -0,0 +1,201 @@
+// 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 java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.PingCommand;
+import com.cloud.agent.api.PingRoutingCommand;
+import com.cloud.agent.api.routing.VmDataCommand;
+import com.cloud.utils.script.Script;
+import com.cloud.utils.ssh.SSHCmdHelper;
+import com.cloud.vm.VirtualMachine.State;
+import com.trilead.ssh2.SCPClient;
+
+public class BaremetalKickStartPxeResource extends BaremetalPxeResourceBase {
+    private static final Logger s_logger = Logger.getLogger(BaremetalKickStartPxeResource.class);
+    private static final String _name = "BaremetalKickStartPxeResource";
+    String _tftpDir;
+
+    @Override
+    public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+        super.configure(name, params);
+        _tftpDir = (String) params.get(BaremetalPxeService.PXE_PARAM_TFTP_DIR);
+        if (_tftpDir == null) {
+            throw new ConfigurationException("No tftp directory specified");
+        }
+
+        com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
+
+        s_logger.debug(String.format("Trying to connect to kickstart PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username, "******"));
+        try {
+            sshConnection.connect(null, 60000, 60000);
+            if (!sshConnection.authenticateWithPassword(_username, _password)) {
+                s_logger.debug("SSH Failed to authenticate");
+                throw new ConfigurationException(String.format("Cannot connect to kickstart PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
+                        "******"));
+            }
+
+            String cmd = String.format("[ -f /%1$s/pxelinux.0 ]", _tftpDir);
+            if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) {
+                throw new ConfigurationException("Miss files in TFTP directory at " + _tftpDir + " check if pxelinux.0 are here");
+            }
+
+            SCPClient scp = new SCPClient(sshConnection);
+            String prepareScript = "scripts/network/ping/prepare_kickstart_bootfile.py";
+            String prepareScriptPath = Script.findScript("", prepareScript);
+            if (prepareScriptPath == null) {
+                throw new ConfigurationException("Can not find prepare_kickstart_bootfile.py at " + prepareScriptPath);
+            }
+            scp.put(prepareScriptPath, "/usr/bin/", "0755");
+
+            String cpScript = "scripts/network/ping/prepare_kickstart_kernel_initrd.py";
+            String cpScriptPath = Script.findScript("", cpScript);
+            if (cpScriptPath == null) {
+                throw new ConfigurationException("Can not find prepare_kickstart_kernel_initrd.py at " + cpScriptPath);
+            }
+            scp.put(cpScriptPath, "/usr/bin/", "0755");
+            
+            String userDataScript = "scripts/network/ping/baremetal_user_data.py";
+            String userDataScriptPath = Script.findScript("", userDataScript);
+            if (userDataScriptPath == null) {
+                throw new ConfigurationException("Can not find baremetal_user_data.py at " + userDataScriptPath);
+            }
+            scp.put(userDataScriptPath, "/usr/bin/", "0755");
+
+            return true;
+        } catch (Exception e) {
+            throw new ConfigurationException(e.getMessage());
+        } finally {
+            if (sshConnection != null) {
+                sshConnection.close();
+            }
+        }
+    }
+    
+    @Override
+    public PingCommand getCurrentStatus(long id) {
+        com.trilead.ssh2.Connection sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
+        if (sshConnection == null) {
+            return null;
+        } else {
+            SSHCmdHelper.releaseSshConnection(sshConnection);
+            return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
+        }
+    }
+    
+    private Answer execute(VmDataCommand cmd) {
+        com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
+        try {
+            List<String[]> vmData = cmd.getVmData();
+            StringBuilder sb = new StringBuilder();
+            for (String[] data : vmData) {
+                String folder = data[0];
+                String file = data[1];
+                String contents = (data[2] == null) ? "none" : data[2];
+                sb.append(cmd.getVmIpAddress());
+                sb.append(",");
+                sb.append(folder);
+                sb.append(",");
+                sb.append(file);
+                sb.append(",");
+                sb.append(contents);
+                sb.append(";");
+            }
+            String arg = StringUtils.stripEnd(sb.toString(), ";");
+            
+            sshConnection.connect(null, 60000, 60000);
+            if (!sshConnection.authenticateWithPassword(_username, _password)) {
+                s_logger.debug("SSH Failed to authenticate");
+                throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
+                        _password));
+            }
+            
+            String script = String.format("python /usr/bin/baremetal_user_data.py '%s'", arg);
+            if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
+                return new Answer(cmd, false, "Failed to add user data, command:" + script);
+            }
+            
+            return new Answer(cmd, true, "Success");
+        }  catch (Exception e){
+            s_logger.debug("Prepare for creating baremetal template failed", e);
+            return new Answer(cmd, false, e.getMessage());
+        } finally {
+            if (sshConnection != null) {
+                sshConnection.close();
+            }
+        }
+    }
+    
+    @Override
+    public Answer executeRequest(Command cmd) {
+        if (cmd instanceof PrepareKickstartPxeServerCommand) {
+            return execute((PrepareKickstartPxeServerCommand) cmd);
+        } else if (cmd instanceof VmDataCommand) {
+            return execute((VmDataCommand)cmd);
+        } else {
+            return super.executeRequest(cmd);
+        }
+    }
+
+    private Answer execute(PrepareKickstartPxeServerCommand cmd) {
+        com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
+        try {
+            sshConnection.connect(null, 60000, 60000);
+            if (!sshConnection.authenticateWithPassword(_username, _password)) {
+                s_logger.debug("SSH Failed to authenticate");
+                throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
+                        _password));
+            }
+            
+            String copyTo = String.format("%s/%s", _tftpDir, cmd.getTemplateUuid());
+            String script = String.format("python /usr/bin/prepare_kickstart_kernel_initrd.py %s %s", cmd.getRepo(), copyTo);
+            
+            if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
+                return new Answer(cmd, false, "prepare kickstart at pxe server " + _ip + " failed, command:" + script);
+            }   
+            
+            String kernelPath = String.format("%s/vmlinuz", cmd.getTemplateUuid());
+            String initrdPath = String.format("%s/initrd.img", cmd.getTemplateUuid());
+            script = String.format("python /usr/bin/prepare_kickstart_bootfile.py %s %s %s %s %s %s", _tftpDir, cmd.getMac(), kernelPath, initrdPath, cmd.getKsFile(), cmd.getMac());
+            if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
+                return new Answer(cmd, false, "prepare kickstart at pxe server " + _ip + " failed, command:" + script);
+            }   
+            
+            s_logger.debug("Prepare kickstart PXE server successfully");
+            return new Answer(cmd, true, "Success");
+        }  catch (Exception e){
+            s_logger.debug("Prepare for kickstart server failed", e);
+            return new Answer(cmd, false, e.getMessage());
+        } finally {
+            if (sshConnection != null) {
+                sshConnection.close();
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1f7eaf3d/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
new file mode 100755
index 0000000..4a2369b
--- /dev/null
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java
@@ -0,0 +1,238 @@
+// 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 java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.ejb.Local;
+
+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.baremetal.database.BaremetalPxeDao;
+import com.cloud.baremetal.database.BaremetalPxeVO;
+import com.cloud.baremetal.networkservice.BaremetalPxeManager.BaremetalPxeType;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.host.Host;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDetailsDao;
+import com.cloud.network.NetworkVO;
+import com.cloud.network.PhysicalNetworkServiceProvider;
+import com.cloud.network.PhysicalNetworkVO;
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.PhysicalNetworkDao;
+import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
+import com.cloud.network.dao.PhysicalNetworkServiceProviderVO;
+import com.cloud.resource.ResourceManager;
+import com.cloud.resource.ServerResource;
+import com.cloud.storage.VMTemplateVO;
+import com.cloud.storage.dao.VMTemplateDao;
+import com.cloud.uservm.UserVm;
+import com.cloud.utils.component.Inject;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.SearchCriteria.Op;
+import com.cloud.utils.db.SearchCriteria2;
+import com.cloud.utils.db.SearchCriteriaService;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.UserVmVO;
+import com.cloud.vm.VirtualMachineProfile;
+
+@Local(value = BaremetalPxeService.class)
+public class BaremetalKickStartServiceImpl extends BareMetalPxeServiceBase implements BaremetalPxeService {
+    private static final Logger s_logger = Logger.getLogger(BaremetalKickStartServiceImpl.class);
+    @Inject
+    ResourceManager _resourceMgr;
+    @Inject
+    PhysicalNetworkDao _physicalNetworkDao;
+    @Inject
+    PhysicalNetworkServiceProviderDao _physicalNetworkServiceProviderDao;
+    @Inject
+    HostDetailsDao _hostDetailsDao;
+    @Inject
+    BaremetalPxeDao _pxeDao;
+    @Inject
+    NetworkDao _nwDao;
+    @Inject
+    VMTemplateDao _tmpDao;
+
+    @Override
+    public boolean prepare(VirtualMachineProfile<UserVmVO> profile, NicProfile nic, DeployDestination dest, ReservationContext context) {
+        NetworkVO nwVO = _nwDao.findById(nic.getNetworkId());
+        SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
+        sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, BaremetalPxeType.KICK_START.toString());
+        sc.addAnd(sc.getEntity().getPhysicalNetworkId(), Op.EQ, nwVO.getPhysicalNetworkId());
+        BaremetalPxeVO pxeVo = sc.find();
+        if (pxeVo == null) {
+            throw new CloudRuntimeException("No kickstart PXE server found in pod: " + dest.getPod().getId() + ", you need to add it before starting VM");
+        }
+        VMTemplateVO template = _tmpDao.findById(profile.getTemplateId());
+
+        try {
+            String tpl = profile.getTemplate().getUrl();
+            assert tpl != null : "How can a null template get here!!!";
+            String[] tpls = tpl.split(";");
+            assert tpls.length == 2 : "Template is not correctly encoded. " + tpl;
+            PrepareKickstartPxeServerCommand cmd = new PrepareKickstartPxeServerCommand();
+            cmd.setKsFile(tpls[0]);
+            cmd.setRepo(tpls[1]);
+            cmd.setMac(nic.getMacAddress());
+            cmd.setTemplateUuid(template.getUuid());
+            Answer aws = _agentMgr.send(pxeVo.getHostId(), cmd);
+            if (!aws.getResult()) {
+                s_logger.warn("Unable to set host: " + dest.getHost().getId() + " to PXE boot because " + aws.getDetails());
+                return aws.getResult();
+            }
+            
+            IpmISetBootDevCommand bootCmd = new IpmISetBootDevCommand(BootDev.pxe);
+            aws = _agentMgr.send(dest.getHost().getId(), bootCmd);
+            if (!aws.getResult()) {
+                s_logger.warn("Unable to set host: " + dest.getHost().getId() + " to PXE boot because " + aws.getDetails());
+            }
+            
+            return aws.getResult();
+        } catch (Exception e) {
+            s_logger.warn("Cannot prepare PXE server", e);
+            return false;
+        }
+    }
+
+    @Override
+    public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    @DB
+    public BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd) {
+        AddBaremetalKickStartPxeCmd kcmd = (AddBaremetalKickStartPxeCmd)cmd;
+        PhysicalNetworkVO pNetwork = null;
+        long zoneId;
+        
+        if (cmd.getPhysicalNetworkId() == null || cmd.getUrl() == null || cmd.getUsername() == null || cmd.getPassword() == null) {
+            throw new IllegalArgumentException("At least one of the required parameters(physical network id, url, username, password) is null");
+        } 
+        
+        pNetwork = _physicalNetworkDao.findById(cmd.getPhysicalNetworkId());
+        if (pNetwork == null) {
+            throw new IllegalArgumentException("Could not find phyical network with ID: " + cmd.getPhysicalNetworkId());
+        }
+        zoneId = pNetwork.getDataCenterId();
+        
+        PhysicalNetworkServiceProviderVO ntwkSvcProvider = _physicalNetworkServiceProviderDao.findByServiceProvider(pNetwork.getId(), BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName());
+        if (ntwkSvcProvider == null) {
+            throw new CloudRuntimeException("Network Service Provider: " + BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER.getName() +
+                    " is not enabled in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
+        } else if (ntwkSvcProvider.getState() == PhysicalNetworkServiceProvider.State.Shutdown) {
+            throw new CloudRuntimeException("Network Service Provider: " + ntwkSvcProvider.getProviderName() +
+                    " is in shutdown state in the physical network: " + cmd.getPhysicalNetworkId() + "to add this device");
+        }
+        
+        List<HostVO> pxes = _resourceMgr.listAllHostsInOneZoneByType(Host.Type.BaremetalPxe, zoneId);
+        if (!pxes.isEmpty()) {
+            throw new IllegalArgumentException("Already had a PXE server zone: " + zoneId);
+        }
+        
+        String tftpDir = kcmd.getTftpDir();
+        if (tftpDir == null) {
+            throw new IllegalArgumentException("No TFTP directory specified");
+        }
+        
+        URI uri;
+        try {
+            uri = new URI(cmd.getUrl());
+        } catch (Exception e) {
+            s_logger.debug(e);
+            throw new IllegalArgumentException(e.getMessage());
+        }
+        String ipAddress = uri.getHost();
+        
+        String guid = getPxeServerGuid(Long.toString(zoneId), BaremetalPxeType.KICK_START.toString(), ipAddress);
+        
+        ServerResource resource = null;
+        Map params = new HashMap<String, String>();
+        params.put(BaremetalPxeService.PXE_PARAM_ZONE, Long.toString(zoneId));
+        params.put(BaremetalPxeService.PXE_PARAM_IP, ipAddress);
+        params.put(BaremetalPxeService.PXE_PARAM_USERNAME, cmd.getUsername());
+        params.put(BaremetalPxeService.PXE_PARAM_PASSWORD, cmd.getPassword());
+        params.put(BaremetalPxeService.PXE_PARAM_TFTP_DIR, tftpDir);
+        params.put(BaremetalPxeService.PXE_PARAM_GUID, guid);
+        resource = new BaremetalKickStartPxeResource();
+        try {
+            resource.configure("KickStart PXE resource", params);
+        } catch (Exception e) {
+            throw new CloudRuntimeException(e.getMessage(), e);
+        }
+        
+        Host pxeServer = _resourceMgr.addHost(zoneId, resource, Host.Type.BaremetalPxe, params);
+        if (pxeServer == null) {
+            throw new CloudRuntimeException("Cannot add PXE server as a host");
+        }
+        
+        BaremetalPxeVO vo = new BaremetalPxeVO();
+        Transaction txn = Transaction.currentTxn();
+        vo.setHostId(pxeServer.getId());
+        vo.setNetworkServiceProviderId(ntwkSvcProvider.getId());
+        vo.setPhysicalNetworkId(kcmd.getPhysicalNetworkId());
+        vo.setDeviceType(BaremetalPxeType.KICK_START.toString());
+        txn.start();
+        _pxeDao.persist(vo);
+        txn.commit();
+        return vo;
+    }
+
+    @Override
+    public BaremetalPxeResponse getApiResponse(BaremetalPxeVO vo) {
+        BaremetalPxeKickStartResponse response = new BaremetalPxeKickStartResponse();
+        response.setId(String.valueOf(vo.getId()));
+        response.setPhysicalNetworkId(String.valueOf(vo.getPhysicalNetworkId()));
+        response.setPodId(String.valueOf(vo.getPodId()));
+        Map<String, String> details = _hostDetailsDao.findDetails(vo.getHostId());
+        response.setTftpDir(details.get(BaremetalPxeService.PXE_PARAM_TFTP_DIR));
+        return response;
+    }
+
+    @Override
+    public List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd) {
+        SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
+        sc.addAnd(sc.getEntity().getDeviceType(), Op.EQ, BaremetalPxeType.KICK_START.toString());
+        if (cmd.getPodId() != null) {
+            sc.addAnd(sc.getEntity().getPodId(), Op.EQ, cmd.getPodId());
+            if (cmd.getId() != null) {
+                sc.addAnd(sc.getEntity().getId(), Op.EQ, cmd.getId());
+            }
+        }
+        List<BaremetalPxeVO> vos = sc.list();
+        List<BaremetalPxeResponse> responses = new ArrayList<BaremetalPxeResponse>(vos.size());
+        for (BaremetalPxeVO vo : vos) {
+            responses.add(getApiResponse(vo));
+        }
+        return responses;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1f7eaf3d/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPingPxeResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPingPxeResource.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPingPxeResource.java
new file mode 100755
index 0000000..2fb5415
--- /dev/null
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPingPxeResource.java
@@ -0,0 +1,260 @@
+// 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
+// Apache License, Version 2.0 (the "License"); you may not use this
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// 
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.baremetal.networkservice;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.naming.ConfigurationException;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+import com.cloud.agent.api.PingCommand;
+import com.cloud.agent.api.PingRoutingCommand;
+import com.cloud.agent.api.baremetal.PreparePxeServerAnswer;
+import com.cloud.agent.api.baremetal.PreparePxeServerCommand;
+import com.cloud.agent.api.baremetal.prepareCreateTemplateCommand;
+import com.cloud.agent.api.routing.VmDataCommand;
+import com.cloud.utils.script.Script;
+import com.cloud.utils.ssh.SSHCmdHelper;
+import com.cloud.vm.VirtualMachine.State;
+import com.trilead.ssh2.SCPClient;
+
+public class BaremetalPingPxeResource extends BaremetalPxeResourceBase {
+	private static final Logger s_logger = Logger.getLogger(BaremetalPingPxeResource.class);
+	private static final String _name = "BaremetalPingPxeResource";
+	String _storageServer;
+	String _pingDir;
+	String _share;
+	String _dir;
+	String _tftpDir;
+	String _cifsUserName;
+	String _cifsPassword;
+	
+	@Override
+	public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
+		super.configure(name, params);
+		_storageServer = (String)params.get(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_IP);
+		_pingDir = (String)params.get(BaremetalPxeService.PXE_PARAM_PING_ROOT_DIR);
+		_tftpDir = (String)params.get(BaremetalPxeService.PXE_PARAM_TFTP_DIR);
+		_cifsUserName = (String)params.get(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_USERNAME);
+		_cifsPassword = (String)params.get(BaremetalPxeService.PXE_PARAM_PING_STORAGE_SERVER_PASSWORD);
+		
+		if (_podId == null) {
+		    throw new ConfigurationException("No Pod specified");
+		}
+		
+		if (_storageServer == null) {
+			throw new ConfigurationException("No stroage server specified");
+		}
+		
+		if (_tftpDir == null) {
+			throw new ConfigurationException("No tftp directory specified");
+		}
+		
+		if (_pingDir == null) {
+			throw new ConfigurationException("No PING directory specified");
+		}
+		
+		if (_cifsUserName == null || _cifsUserName.equalsIgnoreCase("")) {
+			_cifsUserName = "xxx";
+		}
+		
+		if (_cifsPassword == null || _cifsPassword.equalsIgnoreCase("")) {
+			_cifsPassword = "xxx";
+		}
+		
+		String pingDirs[]= _pingDir.split("/");
+		if (pingDirs.length != 2) {
+			throw new ConfigurationException("PING dir should have format like myshare/direcotry, eg: windows/64bit");
+		}
+		_share = pingDirs[0];
+		_dir = pingDirs[1];
+		
+		com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
+		
+		s_logger.debug(String.format("Trying to connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username, "******"));
+		try {
+			sshConnection.connect(null, 60000, 60000);
+			if (!sshConnection.authenticateWithPassword(_username, _password)) {
+				s_logger.debug("SSH Failed to authenticate");
+				throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
+						"******"));
+			}
+			
+			String cmd = String.format("[ -f /%1$s/pxelinux.0 ] && [ -f /%2$s/kernel ] && [ -f /%3$s/initrd.gz ] ", _tftpDir, _tftpDir, _tftpDir);
+			if (!SSHCmdHelper.sshExecuteCmd(sshConnection, cmd)) {
+				throw new ConfigurationException("Miss files in TFTP directory at " + _tftpDir + " check if pxelinux.0, kernel initrd.gz are here");
+			}
+			
+			SCPClient scp = new SCPClient(sshConnection);	
+			String prepareScript = "scripts/network/ping/prepare_tftp_bootfile.py";
+			String prepareScriptPath = Script.findScript("", prepareScript);
+			if (prepareScriptPath == null) {
+				throw new ConfigurationException("Can not find prepare_tftp_bootfile.py at " + prepareScriptPath);
+			}
+			scp.put(prepareScriptPath, "/usr/bin/", "0755");
+			
+			String userDataScript = "scripts/network/ping/baremetal_user_data.py";
+			String userDataScriptPath = Script.findScript("", userDataScript);
+			if (userDataScriptPath == null) {
+				throw new ConfigurationException("Can not find baremetal_user_data.py at " + userDataScriptPath);
+			}
+			scp.put(userDataScriptPath, "/usr/bin/", "0755");
+			
+			return true;
+		} catch (Exception e) {
+			throw new ConfigurationException(e.getMessage());
+		} finally {
+			if (sshConnection != null) {
+				sshConnection.close();
+			}
+		}
+	}
+	
+	@Override
+	public PingCommand getCurrentStatus(long id) {
+		com.trilead.ssh2.Connection sshConnection = SSHCmdHelper.acquireAuthorizedConnection(_ip, _username, _password);
+		if (sshConnection == null) {
+			return null;
+		} else {
+			SSHCmdHelper.releaseSshConnection(sshConnection);
+			return new PingRoutingCommand(getType(), id, new HashMap<String, State>());
+		}
+	}
+	
+	protected PreparePxeServerAnswer execute(PreparePxeServerCommand cmd) {
+		com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
+		try {
+			sshConnection.connect(null, 60000, 60000);
+			if (!sshConnection.authenticateWithPassword(_username, _password)) {
+				s_logger.debug("SSH Failed to authenticate");
+				throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
+						_password));
+			}
+			
+			String script = String.format("python /usr/bin/prepare_tftp_bootfile.py restore %1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s %10$s %11$s",
+					_tftpDir, cmd.getMac(), _storageServer, _share, _dir, cmd.getTemplate(), _cifsUserName, _cifsPassword, cmd.getIp(), cmd.getNetMask(), cmd.getGateWay());
+			if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
+				return new PreparePxeServerAnswer(cmd, "prepare PING at " + _ip + " failed, command:" + script);
+			}	
+			s_logger.debug("Prepare Ping PXE server successfully");
+			
+			return new PreparePxeServerAnswer(cmd);
+		} catch (Exception e){
+			s_logger.debug("Prepare PING pxe server failed", e);
+			return new PreparePxeServerAnswer(cmd, e.getMessage());
+		} finally {
+			if (sshConnection != null) {
+				sshConnection.close();
+			}
+		}
+	}
+	
+	protected Answer execute(prepareCreateTemplateCommand cmd) {
+       com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
+        try {
+            sshConnection.connect(null, 60000, 60000);
+            if (!sshConnection.authenticateWithPassword(_username, _password)) {
+                s_logger.debug("SSH Failed to authenticate");
+                throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
+                        _password));
+            }
+            
+            String script = String.format("python /usr/bin/prepare_tftp_bootfile.py backup %1$s %2$s %3$s %4$s %5$s %6$s %7$s %8$s %9$s %10$s %11$s",
+                    _tftpDir, cmd.getMac(), _storageServer, _share, _dir, cmd.getTemplate(), _cifsUserName, _cifsPassword, cmd.getIp(), cmd.getNetMask(), cmd.getGateWay());
+            if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
+                return new Answer(cmd, false, "prepare for creating template failed, command:" + script);
+            }
+            s_logger.debug("Prepare for creating template successfully");
+            
+            return new Answer(cmd, true, "Success");
+        }  catch (Exception e){
+            s_logger.debug("Prepare for creating baremetal template failed", e);
+            return new Answer(cmd, false, e.getMessage());
+        } finally {
+            if (sshConnection != null) {
+                sshConnection.close();
+            }
+        }
+	}
+	
+	@Override
+	public Answer executeRequest(Command cmd) {
+		if (cmd instanceof PreparePxeServerCommand) {
+			return execute((PreparePxeServerCommand) cmd);
+		} else if (cmd instanceof prepareCreateTemplateCommand) {
+		    return execute((prepareCreateTemplateCommand)cmd);
+		} else if (cmd instanceof VmDataCommand) {
+		    return execute((VmDataCommand)cmd);
+		} else {
+			return super.executeRequest(cmd);
+		}
+	}
+
+    private Answer execute(VmDataCommand cmd) {
+        com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
+        try {
+            List<String[]> vmData = cmd.getVmData();
+            StringBuilder sb = new StringBuilder();
+            for (String[] data : vmData) {
+                String folder = data[0];
+                String file = data[1];
+                String contents = (data[2] == null) ? "none" : data[2];
+                sb.append(cmd.getVmIpAddress());
+                sb.append(",");
+                sb.append(folder);
+                sb.append(",");
+                sb.append(file);
+                sb.append(",");
+                sb.append(contents);
+                sb.append(";");
+            }
+            String arg = org.apache.commons.lang.StringUtils.stripEnd(sb.toString(), ";");
+            
+            sshConnection.connect(null, 60000, 60000);
+            if (!sshConnection.authenticateWithPassword(_username, _password)) {
+                s_logger.debug("SSH Failed to authenticate");
+                throw new ConfigurationException(String.format("Cannot connect to PING PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
+                        _password));
+            }
+            
+            String script = String.format("python /usr/bin/baremetal_user_data.py '%s'", arg);
+            if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
+                return new Answer(cmd, false, "Failed to add user data, command:" + script);
+            }
+            
+            return new Answer(cmd, true, "Success");
+        }  catch (Exception e){
+            s_logger.debug("Prepare for creating baremetal template failed", e);
+            return new Answer(cmd, false, e.getMessage());
+        } finally {
+            if (sshConnection != null) {
+                sshConnection.close();
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1f7eaf3d/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
new file mode 100755
index 0000000..99b9c43
--- /dev/null
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java
@@ -0,0 +1,178 @@
+// 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 java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ejb.Local;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.baremetal.database.BaremetalPxeVO;
+import com.cloud.dc.DataCenter.NetworkType;
+import com.cloud.dc.Pod;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.exception.ConcurrentOperationException;
+import com.cloud.exception.InsufficientCapacityException;
+import com.cloud.exception.ResourceUnavailableException;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
+import com.cloud.network.Network;
+import com.cloud.network.Network.Capability;
+import com.cloud.network.Network.GuestType;
+import com.cloud.network.Network.Provider;
+import com.cloud.network.Network.Service;
+import com.cloud.network.Networks.TrafficType;
+import com.cloud.network.PhysicalNetworkServiceProvider;
+import com.cloud.network.element.NetworkElement;
+import com.cloud.offering.NetworkOffering;
+import com.cloud.utils.component.AdapterBase;
+import com.cloud.utils.component.Inject;
+import com.cloud.utils.db.DB;
+import com.cloud.utils.db.SearchCriteria.Op;
+import com.cloud.utils.db.SearchCriteria2;
+import com.cloud.utils.db.SearchCriteriaService;
+import com.cloud.utils.db.Transaction;
+import com.cloud.utils.exception.CloudRuntimeException;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.NicVO;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VirtualMachine.Type;
+import com.cloud.vm.VirtualMachineProfile;
+import com.cloud.vm.dao.NicDao;
+import com.cloud.vm.dao.VMInstanceDao;
+
+@Local(value = NetworkElement.class)
+public class BaremetalPxeElement extends AdapterBase implements NetworkElement {
+    private static final Logger s_logger = Logger.getLogger(BaremetalPxeElement.class);
+    private static final Map<Service, Map<Capability, String>> capabilities;
+    
+    @Inject BaremetalPxeManager _pxeMgr;;
+    @Inject VMInstanceDao _vmDao;
+    @Inject NicDao _nicDao;
+    
+    static {
+        Capability cap = new Capability(BaremetalPxeManager.BAREMETAL_PXE_CAPABILITY);
+        Map<Capability, String> baremetalCaps = new HashMap<Capability, String>();
+        baremetalCaps.put(cap, null);
+        capabilities = new HashMap<Service, Map<Capability, String>>();
+        capabilities.put(BaremetalPxeManager.BAREMETAL_PXE_SERVICE, baremetalCaps);
+    }
+    
+    @Override
+    public Map<Service, Map<Capability, String>> getCapabilities() {
+        return capabilities;
+    }
+
+    @Override
+    public Provider getProvider() {
+    	return BaremetalPxeManager.BAREMETAL_PXE_SERVICE_PROVIDER;
+    }
+
+    private boolean canHandle(DeployDestination dest, TrafficType trafficType, GuestType networkType) {
+        Pod pod = dest.getPod();
+        if (pod != null && dest.getDataCenter().getNetworkType() == NetworkType.Basic && trafficType == TrafficType.Guest) {
+            SearchCriteriaService<BaremetalPxeVO, BaremetalPxeVO> sc = SearchCriteria2.create(BaremetalPxeVO.class);
+            sc.addAnd(sc.getEntity().getPodId(), Op.EQ, pod.getId());
+            return sc.find() != null;
+        }
+        
+        return false;
+    }
+    
+    @Override
+    public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context)
+            throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
+        if (offering.isSystemOnly() || !canHandle(dest, offering.getTrafficType(), network.getGuestType())) {
+            s_logger.debug("BaremetalPxeElement can not handle network offering: " + offering.getName());
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    @DB
+    public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
+            ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
+        if (vm.getType() != Type.User || vm.getHypervisorType() != HypervisorType.BareMetal) {
+            return false;
+        }
+        
+        VMInstanceVO vo = _vmDao.findById(vm.getId());
+        if (vo.getLastHostId() == null) {
+            Transaction txn = Transaction.currentTxn();
+            txn.start();
+            nic.setMacAddress(dest.getHost().getPrivateMacAddress());
+            NicVO nicVo = _nicDao.findById(nic.getId());
+            assert vo != null : "Where ths nic " + nic.getId() + " going???";
+            nicVo.setMacAddress(nic.getMacAddress());
+            _nicDao.update(nicVo.getId(), nicVo);
+            txn.commit();
+            
+        	/*This vm is just being created */
+        	if (!_pxeMgr.prepare(vm, nic, dest, context)) {
+        	    throw new CloudRuntimeException("Cannot prepare pxe server");
+        	}
+        }
+        
+        return false;
+    }
+
+    @Override
+    public boolean release(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, ReservationContext context)
+            throws ConcurrentOperationException, ResourceUnavailableException {
+        return true;
+    }
+
+    @Override
+    public boolean shutdown(Network network, ReservationContext context, boolean cleanup) throws ConcurrentOperationException, ResourceUnavailableException {
+        return true;
+    }
+
+    @Override
+    public boolean isReady(PhysicalNetworkServiceProvider provider) {
+        return true;
+    }
+
+    @Override
+    public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException,
+            ResourceUnavailableException {
+        return true;
+    }
+
+    @Override
+    public boolean canEnableIndividualServices() {
+        return false;
+    }
+
+    @Override
+    public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public boolean verifyServicesCombination(Set<Service> services) {
+        // TODO Auto-generated method stub
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1f7eaf3d/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeKickStartResponse.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeKickStartResponse.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeKickStartResponse.java
new file mode 100755
index 0000000..09c6cc6
--- /dev/null
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeKickStartResponse.java
@@ -0,0 +1,37 @@
+// 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 org.apache.cloudstack.api.ApiConstants;
+
+import com.cloud.serializer.Param;
+import com.google.gson.annotations.SerializedName;
+
+public class BaremetalPxeKickStartResponse extends BaremetalPxeResponse {
+    @SerializedName(ApiConstants.TFTP_DIR) @Param(description="Tftp root directory of PXE server")
+    private String tftpDir;
+
+    public String getTftpDir() {
+        return tftpDir;
+    }
+
+    public void setTftpDir(String tftpDir) {
+        this.tftpDir = tftpDir;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/1f7eaf3d/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManager.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManager.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManager.java
new file mode 100755
index 0000000..e0a5162
--- /dev/null
+++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManager.java
@@ -0,0 +1,65 @@
+// 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
+// Apache License, Version 2.0 (the "License"); you may not use this
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// 
+// Automatically generated by addcopyright.py at 04/03/2012
+package com.cloud.baremetal.networkservice;
+
+import java.util.List;
+
+import com.cloud.baremetal.database.BaremetalPxeVO;
+import com.cloud.deploy.DeployDestination;
+import com.cloud.host.HostVO;
+import com.cloud.network.Network;
+import com.cloud.network.Network.Provider;
+import com.cloud.uservm.UserVm;
+import com.cloud.utils.component.Manager;
+import com.cloud.utils.component.PluggableService;
+import com.cloud.vm.NicProfile;
+import com.cloud.vm.ReservationContext;
+import com.cloud.vm.UserVmVO;
+import com.cloud.vm.VirtualMachineProfile;
+
+public interface BaremetalPxeManager extends Manager, PluggableService {
+    public enum BaremetalPxeType {
+        PING,
+        KICK_START,
+    }
+    
+	boolean prepare(VirtualMachineProfile profile, NicProfile nic, DeployDestination dest, ReservationContext context);
+
+	boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl);
+	
+	BaremetalPxeType getPxeServerType(HostVO host);
+	
+	BaremetalPxeVO addPxeServer(AddBaremetalPxeCmd cmd);
+	
+	BaremetalPxeResponse getApiResponse(BaremetalPxeVO vo);
+	
+	List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd);
+	
+	boolean addUserData(NicProfile nic, VirtualMachineProfile<UserVm> vm);
+		
+	public static final Network.Service BAREMETAL_PXE_SERVICE = new Network.Service("BaremetalPxeService");
+	public static final String BAREMETAL_PXE_CAPABILITY = "BaremetalPxe";
+	public static final String BAREMETAL_PXE_SERVICE_PROPERTIES = "baremetalpxe_commands.properties";
+	public static final Provider BAREMETAL_PXE_SERVICE_PROVIDER = new Provider("BaremetalPxeProvider", true);;
+	public static final Provider BAREMETAL_USERDATA_PROVIDER = new Provider("BaremetaUserdataProvider", true);
+}