mirror of https://github.com/apache/cloudstack.git
Bug 8208 - bare metal provisioning
Successfully add start entry into LinMin PXE server
This commit is contained in:
parent
5035778b1a
commit
a9728998ff
|
|
@ -0,0 +1,9 @@
|
|||
package com.cloud.agent.api;
|
||||
|
||||
import com.cloud.host.Host;
|
||||
|
||||
public class StartupPxeServerCommand extends StartupCommand {
|
||||
public StartupPxeServerCommand() {
|
||||
super(Host.Type.PxeServer);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
package com.cloud.agent.api.baremetal;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
|
||||
public class PrepareLinMinPxeServerAnswer extends Answer {
|
||||
public PrepareLinMinPxeServerAnswer(PrepareLinMinPxeServerCommand cmd) {
|
||||
super(cmd, true, "SUCCESS");
|
||||
}
|
||||
|
||||
public PrepareLinMinPxeServerAnswer(PrepareLinMinPxeServerCommand cmd, String details) {
|
||||
super(cmd, false, details);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
package com.cloud.agent.api.baremetal;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
|
||||
public class PrepareLinMinPxeServerCommand extends Command {
|
||||
String ip;
|
||||
String mac;
|
||||
String netMask;
|
||||
String gateway;
|
||||
String dns;
|
||||
String template;
|
||||
String vmName;
|
||||
String hostName;
|
||||
|
||||
@Override
|
||||
public boolean executeInSequence() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public PrepareLinMinPxeServerCommand(String ip, String mac, String netMask, String gateway, String dns, String template, String vmName, String hostName) {
|
||||
this.ip = ip;
|
||||
this.mac = mac;
|
||||
this.netMask = netMask;
|
||||
this.gateway = gateway;
|
||||
this.dns = dns;
|
||||
this.template = template;
|
||||
this.vmName = vmName;
|
||||
this.hostName = hostName;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public String getMac() {
|
||||
return mac;
|
||||
}
|
||||
|
||||
public String getNetMask() {
|
||||
return netMask;
|
||||
}
|
||||
|
||||
public String getGateWay() {
|
||||
return gateway;
|
||||
}
|
||||
|
||||
public String getDns() {
|
||||
return dns;
|
||||
}
|
||||
|
||||
public String getTemplate() {
|
||||
return template;
|
||||
}
|
||||
|
||||
public String getVmName() {
|
||||
return vmName;
|
||||
}
|
||||
|
||||
public String getHostName() {
|
||||
return hostName;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -194,5 +194,7 @@ public class ApiConstants {
|
|||
public static final String HOST_CPU_NUM = "hostcpunum";
|
||||
public static final String HOST_MEM_CAPACITY = "hostmemcapacity";
|
||||
public static final String HOST_MAC = "hostmac";
|
||||
public static final String PXE_SERVER_TYPE = "pxeservertype";
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@ public interface Host {
|
|||
SecondaryStorage(false),
|
||||
ConsoleProxy(true),
|
||||
ExternalFirewall(false),
|
||||
ExternalLoadBalancer(false);
|
||||
ExternalLoadBalancer(false),
|
||||
PxeServer(false);
|
||||
|
||||
boolean _virtual;
|
||||
private Type(boolean virtual) {
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ public interface VirtualMachineProfile<T extends VirtualMachine> {
|
|||
public static final Param VmPassword = new Param("VmPassword");
|
||||
public static final Param ControlNic = new Param("ControlNic");
|
||||
public static final Param RestartNetwork = new Param("RestartNetwork");
|
||||
|
||||
public static final Param PxeSeverType = new Param("PxeSeverType");
|
||||
|
||||
private String name;
|
||||
|
||||
public Param(String name) {
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ import com.cloud.agent.api.StartupCommand;
|
|||
import com.cloud.agent.api.StartupExternalFirewallCommand;
|
||||
import com.cloud.agent.api.StartupExternalLoadBalancerCommand;
|
||||
import com.cloud.agent.api.StartupProxyCommand;
|
||||
import com.cloud.agent.api.StartupPxeServerCommand;
|
||||
import com.cloud.agent.api.StartupRoutingCommand;
|
||||
import com.cloud.agent.api.StartupStorageCommand;
|
||||
import com.cloud.agent.api.UnsupportedAnswer;
|
||||
|
|
@ -2363,6 +2364,8 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory,
|
|||
type = Host.Type.ExternalFirewall;
|
||||
} else if (startup instanceof StartupExternalLoadBalancerCommand) {
|
||||
type = Host.Type.ExternalLoadBalancer;
|
||||
} else if (startup instanceof StartupPxeServerCommand) {
|
||||
type = Host.Type.PxeServer;
|
||||
} else {
|
||||
assert false : "Did someone add a new Startup command?";
|
||||
}
|
||||
|
|
@ -2617,7 +2620,8 @@ public class AgentManagerImpl implements AgentManager, HandlerFactory,
|
|||
if (p == null) {
|
||||
if (type != Host.Type.SecondaryStorage
|
||||
&& type != Host.Type.ExternalFirewall
|
||||
&& type != Host.Type.ExternalLoadBalancer) {
|
||||
&& type != Host.Type.ExternalLoadBalancer
|
||||
&& type != Host.Type.PxeServer) {
|
||||
|
||||
/*
|
||||
* s_logger.info("Unable to find the pod so we are creating one."
|
||||
|
|
|
|||
|
|
@ -0,0 +1,103 @@
|
|||
package com.cloud.api;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.api.ApiConstants;
|
||||
import com.cloud.api.BaseCmd;
|
||||
import com.cloud.api.Implementation;
|
||||
import com.cloud.api.Parameter;
|
||||
import com.cloud.api.ServerApiException;
|
||||
import com.cloud.api.response.PxeServerResponse;
|
||||
import com.cloud.baremetal.LinMinPxeServerManager;
|
||||
import com.cloud.baremetal.PxeServerManager;
|
||||
import com.cloud.baremetal.PxeServerManager.PxeServerType;
|
||||
import com.cloud.exception.ConcurrentOperationException;
|
||||
import com.cloud.exception.InsufficientCapacityException;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.server.ManagementService;
|
||||
import com.cloud.utils.component.ComponentLocator;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
|
||||
@Implementation(description="Adds a PXE server appliance", responseObject = PxeServerResponse.class)
|
||||
public class AddPxeServerCmd extends BaseCmd {
|
||||
public static final Logger s_logger = Logger.getLogger(AddPxeServerCmd.class.getName());
|
||||
private static final String s_name = "addpxeserverresponse";
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
//////////////// API parameters /////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Parameter(name=ApiConstants.ZONE_ID, type=CommandType.LONG, required = true, description="Zone in which to add the external firewall appliance.")
|
||||
private Long zoneId;
|
||||
|
||||
@Parameter(name=ApiConstants.URL, type=CommandType.STRING, required = true, description="URL of the PXE server appliance.")
|
||||
private String url;
|
||||
|
||||
@Parameter(name=ApiConstants.USERNAME, type=CommandType.STRING, required = true, description="Username of PXE server appliance.")
|
||||
private String username;
|
||||
|
||||
@Parameter(name=ApiConstants.PASSWORD, type=CommandType.STRING, required = true, description="Password of the PXE server appliance.")
|
||||
private String password;
|
||||
|
||||
@Parameter(name=ApiConstants.PXE_SERVER_TYPE, type=CommandType.STRING, required = true, description="Type of PXE server. Current values are LinMin, DMCD")
|
||||
private String type;
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
/////////////////// Accessors ///////////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
public Long getZoneId() {
|
||||
return zoneId;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
/////////////// API Implementation///////////////////
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public String getCommandName() {
|
||||
return s_name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException,
|
||||
ResourceAllocationException {
|
||||
try {
|
||||
PxeServerManager pxeServerMgr;
|
||||
ComponentLocator locator = ComponentLocator.getLocator(ManagementService.Name);
|
||||
if (getType().equalsIgnoreCase(PxeServerType.LinMin.getName())) {
|
||||
pxeServerMgr = locator.getManager(LinMinPxeServerManager.class);
|
||||
} else {
|
||||
throw new ServerApiException(BaseCmd.PARAM_ERROR, "Unsupport PXE server type " + getType());
|
||||
}
|
||||
Host pxeServer = pxeServerMgr.addPxeServer(this);
|
||||
PxeServerResponse response = pxeServerMgr.getApiResponse(pxeServer);
|
||||
response.setObjectName("pxeserver");
|
||||
response.setResponseName(getCommandName());
|
||||
this.setResponseObject(response);
|
||||
} catch (InvalidParameterValueException ipve) {
|
||||
throw new ServerApiException(BaseCmd.PARAM_ERROR, ipve.getMessage());
|
||||
} catch (CloudRuntimeException cre) {
|
||||
throw new ServerApiException(BaseCmd.INTERNAL_ERROR, cre.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.cloud.api.response;
|
||||
|
||||
import com.cloud.api.ApiConstants;
|
||||
import com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class PxeServerResponse extends BaseResponse {
|
||||
@SerializedName(ApiConstants.ID) @Param(description="the ID of the PXE server")
|
||||
private Long id;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.cloud.baremetal;
|
||||
|
||||
public interface LinMinPxeServerManager extends PxeServerManager {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
package com.cloud.baremetal;
|
||||
|
||||
import java.net.URI;
|
||||
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.AgentManager;
|
||||
import com.cloud.agent.api.baremetal.PrepareLinMinPxeServerAnswer;
|
||||
import com.cloud.agent.api.baremetal.PrepareLinMinPxeServerCommand;
|
||||
import com.cloud.api.AddPxeServerCmd;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
import com.cloud.dc.dao.DataCenterDao;
|
||||
import com.cloud.deploy.DeployDestination;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.utils.component.Inject;
|
||||
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 = {LinMinPxeServerManager.class})
|
||||
public class LinMinPxeServerManagerImpl extends PxeServerManagerImpl implements LinMinPxeServerManager {
|
||||
private static final org.apache.log4j.Logger s_logger = Logger.getLogger(LinMinPxeServerManagerImpl.class);
|
||||
@Inject DataCenterDao _dcDao;
|
||||
@Inject HostDao _hostDao;
|
||||
@Inject AgentManager _agentMgr;
|
||||
|
||||
@Override
|
||||
public Host addPxeServer(AddPxeServerCmd cmd) throws InvalidParameterValueException, CloudRuntimeException {
|
||||
long zoneId = cmd.getZoneId();
|
||||
|
||||
DataCenterVO zone = _dcDao.findById(zoneId);
|
||||
String zoneName;
|
||||
if (zone == null) {
|
||||
throw new InvalidParameterValueException("Could not find zone with ID: " + zoneId);
|
||||
} else {
|
||||
zoneName = zone.getName();
|
||||
}
|
||||
|
||||
List<HostVO> pxeServers = _hostDao.listByTypeDataCenter(Host.Type.PxeServer, zoneId);
|
||||
if (pxeServers.size() != 0) {
|
||||
throw new InvalidParameterValueException("Already had a PXE server in zone: " + zoneName);
|
||||
}
|
||||
|
||||
URI uri;
|
||||
try {
|
||||
uri = new URI(cmd.getUrl());
|
||||
} catch (Exception e) {
|
||||
s_logger.debug(e);
|
||||
throw new InvalidParameterValueException(e.getMessage());
|
||||
}
|
||||
|
||||
String ipAddress = uri.getHost();
|
||||
String username = cmd.getUsername();
|
||||
String password = cmd.getPassword();
|
||||
String guid = getPxeServerGuid(Long.toString(zoneId), PxeServerType.LinMin.getName(), ipAddress);
|
||||
Map params = new HashMap<String, String>();
|
||||
params.put("zone", Long.toString(zoneId));
|
||||
params.put("ip", ipAddress);
|
||||
params.put("username", username);
|
||||
params.put("password", password);
|
||||
params.put("guid", guid);
|
||||
|
||||
ServerResource resource = null;
|
||||
try {
|
||||
if (cmd.getType().equalsIgnoreCase(PxeServerType.LinMin.getName())) {
|
||||
resource = new LinMinPxeServerResource();
|
||||
resource.configure("LinMin PXE resource", params);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.debug(e);
|
||||
throw new CloudRuntimeException(e.getMessage());
|
||||
}
|
||||
|
||||
Host pxeServer = _agentMgr.addHost(zoneId, resource, Host.Type.PxeServer, params);
|
||||
if (pxeServer == null) {
|
||||
throw new CloudRuntimeException("Cannot add PXE server as a host");
|
||||
}
|
||||
|
||||
return pxeServer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean prepare(VirtualMachineProfile<UserVmVO> profile, DeployDestination dest, ReservationContext context, Long pxeServerId) {
|
||||
List<NicProfile> nics = profile.getNics();
|
||||
if (nics.size() == 0) {
|
||||
throw new CloudRuntimeException("Cannot do PXE start without nic");
|
||||
}
|
||||
|
||||
NicProfile pxeNic = nics.get(0);
|
||||
String mac = pxeNic.getMacAddress();
|
||||
String ip = pxeNic.getIp4Address();
|
||||
String gateway = pxeNic.getGateway();
|
||||
String mask = pxeNic.getNetmask();
|
||||
String dns = pxeNic.getDns1();
|
||||
if (dns == null) {
|
||||
dns = pxeNic.getDns2();
|
||||
}
|
||||
|
||||
try {
|
||||
String linMinTpl = profile.getTemplate().getUrl();
|
||||
assert linMinTpl != null : "How can a null template get here!!!";
|
||||
PrepareLinMinPxeServerCommand cmd = new PrepareLinMinPxeServerCommand(ip, mac, mask, gateway, dns, linMinTpl,
|
||||
profile.getVirtualMachine().getName(), dest.getHost().getName());
|
||||
PrepareLinMinPxeServerAnswer ans = (PrepareLinMinPxeServerAnswer) _agentMgr.send(pxeServerId, cmd);
|
||||
return ans.getResult();
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("Cannot prepare PXE server", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,321 @@
|
|||
package com.cloud.baremetal;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.naming.ConfigurationException;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
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.ReadyAnswer;
|
||||
import com.cloud.agent.api.ReadyCommand;
|
||||
import com.cloud.agent.api.StartupCommand;
|
||||
import com.cloud.agent.api.StartupPxeServerCommand;
|
||||
import com.cloud.agent.api.baremetal.PrepareLinMinPxeServerAnswer;
|
||||
import com.cloud.agent.api.baremetal.PrepareLinMinPxeServerCommand;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.host.Host.Type;
|
||||
import com.cloud.resource.ServerResource;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.ssh.SSHCmdHelper;
|
||||
|
||||
public class LinMinPxeServerResource implements ServerResource {
|
||||
private static final Logger s_logger = Logger.getLogger(LinMinPxeServerResource.class);
|
||||
String _name;
|
||||
String _guid;
|
||||
String _username;
|
||||
String _password;
|
||||
String _ip;
|
||||
String _zoneId;
|
||||
|
||||
class XmlReturn {
|
||||
NodeList nList;
|
||||
public XmlReturn(InputSource s, String tagName) {
|
||||
try {
|
||||
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
|
||||
Document doc = dBuilder.parse(s);
|
||||
doc.getDocumentElement().normalize();
|
||||
nList = doc.getElementsByTagName(tagName);
|
||||
} catch (Exception e) {
|
||||
s_logger.debug("The XML file:");
|
||||
s_logger.debug(s.toString());
|
||||
s_logger.debug("Cannot parse XMl file", e);
|
||||
nList = null;
|
||||
}
|
||||
}
|
||||
|
||||
public String getValue(String tag) {
|
||||
if (nList == null || nList.getLength() == 0) {
|
||||
throw new InvalidParameterValueException("invalid XML file");
|
||||
}
|
||||
|
||||
Element e = (Element)nList.item(0);
|
||||
NodeList nlList= e.getElementsByTagName(tag).item(0).getChildNodes();
|
||||
Node nValue = (Node)nlList.item(0);
|
||||
return nValue.getNodeValue();
|
||||
}
|
||||
}
|
||||
|
||||
@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");
|
||||
|
||||
if (_guid == null) {
|
||||
throw new ConfigurationException("No Guid specified");
|
||||
}
|
||||
|
||||
if (_zoneId == null) {
|
||||
throw new ConfigurationException("No Zone 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");
|
||||
}
|
||||
|
||||
com.trilead.ssh2.Connection sshConnection = new com.trilead.ssh2.Connection(_ip, 22);
|
||||
|
||||
s_logger.debug(String.format("Trying to connect to LinMin PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username, _password));
|
||||
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 LinMin PXE server(IP=%1$s, username=%2$s, password=%3$s", _ip, _username,
|
||||
_password));
|
||||
}
|
||||
|
||||
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, "[ -d '/home/tftpboot' ] && [ -d '/usr/local/linmin' ]")) {
|
||||
throw new ConfigurationException("Cannot find LinMin directory /home/tftpboot, /usr/local/linmin on PXE server");
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
throw new ConfigurationException(e.getMessage());
|
||||
} finally {
|
||||
if (sshConnection != null) {
|
||||
sshConnection.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType() {
|
||||
return Type.PxeServer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StartupCommand[] initialize() {
|
||||
StartupPxeServerCommand cmd = new StartupPxeServerCommand();
|
||||
cmd.setName(_name);
|
||||
cmd.setDataCenter(_zoneId);
|
||||
cmd.setPod("");
|
||||
cmd.setPrivateIpAddress(_ip);
|
||||
cmd.setStorageIpAddress("");
|
||||
cmd.setVersion("");
|
||||
cmd.setGuid(_guid);
|
||||
return new StartupCommand[]{cmd};
|
||||
}
|
||||
|
||||
@Override
|
||||
public PingCommand getCurrentStatus(long id) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
protected ReadyAnswer execute(ReadyCommand cmd) {
|
||||
s_logger.debug("LinMin resource " + _name + " is ready");
|
||||
return new ReadyAnswer(cmd);
|
||||
}
|
||||
|
||||
private InputSource httpCall(String urlStr) {
|
||||
try {
|
||||
s_logger.debug("Execute http call " + urlStr);
|
||||
URL url = new URL(urlStr);
|
||||
URLConnection conn = url.openConnection();
|
||||
conn.setReadTimeout(30000);
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
StringBuffer xmlStuff = new StringBuffer();
|
||||
String line;
|
||||
while ((line = in.readLine()) != null) {
|
||||
xmlStuff.append(line);
|
||||
}
|
||||
StringReader statsReader = new StringReader(xmlStuff.toString());
|
||||
InputSource statsSource = new InputSource(statsReader);
|
||||
s_logger.debug("Http call retrun:");
|
||||
s_logger.debug(xmlStuff.toString());
|
||||
return statsSource;
|
||||
} catch (MalformedURLException e) {
|
||||
throw new CloudRuntimeException("URL is malformed " + urlStr, e);
|
||||
} catch (IOException e) {
|
||||
s_logger.warn("can not do http call", e);
|
||||
return null;
|
||||
}catch (Exception e) {
|
||||
s_logger.warn("Cannot do http call " + urlStr, e);
|
||||
throw new CloudRuntimeException(e.getStackTrace().toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected PrepareLinMinPxeServerAnswer execute(PrepareLinMinPxeServerCommand cmd) {
|
||||
String apiUserName = "root";
|
||||
String apiPassword = "password";
|
||||
String apid = "2ad644fb479871a0f5543dd6d29fe9ed";
|
||||
StringBuffer askApid = new StringBuffer();
|
||||
|
||||
askApid.append("http://");
|
||||
askApid.append(_ip);
|
||||
askApid.append("/tftpboot/www/lbmp-API.php?actiontype=provision&apid=");
|
||||
askApid.append(apid);
|
||||
askApid.append("&auth_user=");
|
||||
askApid.append(apiUserName);
|
||||
askApid.append("&auth_user_pw=");
|
||||
askApid.append(apiPassword);
|
||||
askApid.append("&rtn_format=XML&action=authorize");
|
||||
InputSource s = httpCall(askApid.toString());
|
||||
if (s == null) {
|
||||
return new PrepareLinMinPxeServerAnswer(cmd, "Http call failed");
|
||||
}
|
||||
|
||||
try {
|
||||
XmlReturn r = new XmlReturn(s, "LinMinBareMetalAPI");
|
||||
String res = r.getValue("actionResultsMsg");
|
||||
s_logger.debug(s.toString());
|
||||
if (!res.startsWith("Successful")) {
|
||||
return new PrepareLinMinPxeServerAnswer(cmd, "Acquire APID failed");
|
||||
}
|
||||
|
||||
String apid5 = r.getValue("apid");
|
||||
if (apid5 == null) {
|
||||
return new PrepareLinMinPxeServerAnswer(cmd, "Cannot get 5 minutes APID " + apid5);
|
||||
}
|
||||
|
||||
StringBuffer addRole = new StringBuffer();
|
||||
addRole.append("http://");
|
||||
addRole.append(_ip);
|
||||
addRole.append("/tftpboot/www/lbmp-API.php?actiontype=provision&user_supplied_id=");
|
||||
addRole.append(cmd.getVmName());
|
||||
addRole.append("&mac_address=");
|
||||
addRole.append(cmd.getMac().replaceAll(":", "%3A"));
|
||||
addRole.append("&apid=");
|
||||
addRole.append(apid5);
|
||||
addRole.append("&control_file_template=");
|
||||
addRole.append(cmd.getTemplate().replace(' ', '+'));
|
||||
addRole.append("&node_name=");
|
||||
addRole.append(cmd.getHostName());
|
||||
addRole.append("&node_domain=");
|
||||
addRole.append(cmd.getHostName());
|
||||
addRole.append("&node_password=password");
|
||||
addRole.append("&node_time_zone=Etc%2FGMT-8");
|
||||
if (cmd.getIp() != null) {
|
||||
addRole.append("&node_ip_address=");
|
||||
addRole.append(cmd.getIp());
|
||||
}
|
||||
if (cmd.getNetMask() != null) {
|
||||
addRole.append("&node_subnet_mask=");
|
||||
addRole.append(cmd.getNetMask());
|
||||
}
|
||||
if (cmd.getDns() != null) {
|
||||
addRole.append("&node_nameserver=");
|
||||
addRole.append(cmd.getDns());
|
||||
}
|
||||
if (cmd.getGateWay() != null) {
|
||||
addRole.append("&node_default_gateway=");
|
||||
addRole.append(cmd.getGateWay());
|
||||
}
|
||||
addRole.append("&enable_provisioning_flag=nextbootonly&rtn_format=XML&action=add");
|
||||
|
||||
s = httpCall(addRole.toString());
|
||||
if (s == null) {
|
||||
return new PrepareLinMinPxeServerAnswer(cmd, "Http call failed");
|
||||
}
|
||||
r = new XmlReturn(s, "LinMinBareMetalAPI");
|
||||
res = r.getValue("actionResultsMsg");
|
||||
s_logger.debug(s.toString());
|
||||
if (!res.startsWith("Successful")) {
|
||||
return new PrepareLinMinPxeServerAnswer(cmd, "Add LinMin role failed");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
s_logger.warn("Cannot parse result from Lin Min server", e);
|
||||
return new PrepareLinMinPxeServerAnswer(cmd, e.getMessage());
|
||||
}
|
||||
|
||||
s_logger.debug("Prepare LinMin PXE server successfully");
|
||||
return new PrepareLinMinPxeServerAnswer(cmd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Answer executeRequest(Command cmd) {
|
||||
if (cmd instanceof ReadyCommand) {
|
||||
return execute((ReadyCommand) cmd);
|
||||
} else if (cmd instanceof PrepareLinMinPxeServerCommand) {
|
||||
return execute((PrepareLinMinPxeServerCommand)cmd);
|
||||
} else {
|
||||
return Answer.createUnsupportedCommandAnswer(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnected() {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAgentControl getAgentControl() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAgentControl(IAgentControl agentControl) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
package com.cloud.baremetal;
|
||||
|
||||
import com.cloud.agent.api.baremetal.PrepareLinMinPxeServerCommand;
|
||||
import com.cloud.api.AddPxeServerCmd;
|
||||
import com.cloud.api.response.PxeServerResponse;
|
||||
import com.cloud.deploy.DeployDestination;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.utils.component.Manager;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.ReservationContext;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
|
||||
public interface PxeServerManager extends Manager {
|
||||
public static class PxeServerType {
|
||||
private String _name;
|
||||
|
||||
public static final PxeServerType LinMin = new PxeServerType("LinMin");
|
||||
public static final PxeServerType DMCD = new PxeServerType("DMCD");
|
||||
|
||||
public PxeServerType(String name) {
|
||||
_name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Host addPxeServer(AddPxeServerCmd cmd) throws InvalidParameterValueException, CloudRuntimeException;
|
||||
|
||||
public PxeServerResponse getApiResponse(Host pxeServer);
|
||||
|
||||
public boolean prepare(VirtualMachineProfile<UserVmVO> profile, DeployDestination dest, ReservationContext context, Long pxeServerId);
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
package com.cloud.baremetal;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ejb.Local;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.baremetal.PrepareLinMinPxeServerCommand;
|
||||
import com.cloud.api.AddPxeServerCmd;
|
||||
import com.cloud.api.response.PxeServerResponse;
|
||||
import com.cloud.deploy.DeployDestination;
|
||||
import com.cloud.exception.InvalidParameterValueException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.ReservationContext;
|
||||
import com.cloud.vm.UserVmVO;
|
||||
import com.cloud.vm.VirtualMachineProfile;
|
||||
|
||||
@Local(value = {PxeServerManager.class})
|
||||
public class PxeServerManagerImpl implements PxeServerManager {
|
||||
private static final org.apache.log4j.Logger s_logger = Logger.getLogger(PxeServerManagerImpl.class);
|
||||
protected String _name;
|
||||
|
||||
@Override
|
||||
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
|
||||
_name = name;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean start() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
protected String getPxeServerGuid(String zoneId, String name, String ip) {
|
||||
return zoneId + "-" + name + "-" + ip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Host addPxeServer(AddPxeServerCmd cmd) throws InvalidParameterValueException, CloudRuntimeException {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PxeServerResponse getApiResponse(Host pxeServer) {
|
||||
PxeServerResponse response = new PxeServerResponse();
|
||||
response.setId(pxeServer.getId());
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean prepare(VirtualMachineProfile<UserVmVO> profile, DeployDestination dest, ReservationContext context, Long pxeServerId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
package com.cloud.hypervisor.kvm.discoverer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
|
|
@ -38,6 +36,7 @@ import com.cloud.resource.ServerResource;
|
|||
import com.cloud.utils.component.ComponentLocator;
|
||||
import com.cloud.utils.component.Inject;
|
||||
import com.cloud.utils.script.Script;
|
||||
import com.cloud.utils.ssh.SSHCmdHelper;
|
||||
import com.trilead.ssh2.ChannelCondition;
|
||||
import com.trilead.ssh2.SCPClient;
|
||||
import com.trilead.ssh2.Session;
|
||||
|
|
@ -101,85 +100,6 @@ public class KvmServerDiscoverer extends DiscovererBase implements Discoverer,
|
|||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean sshExecuteCmd(com.trilead.ssh2.Connection sshConnection, String cmd) {
|
||||
s_logger.debug("Executing cmd: " + cmd);
|
||||
Session sshSession = null;
|
||||
try {
|
||||
sshSession = sshConnection.openSession();
|
||||
// There is a bug in Trilead library, wait a second before
|
||||
// starting a shell and executing commands, from http://spci.st.ewi.tudelft.nl/chiron/xref/nl/tudelft/swerl/util/SSHConnection.html
|
||||
Thread.sleep(1000);
|
||||
|
||||
if (sshSession == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sshSession.execCommand(cmd);
|
||||
|
||||
InputStream stdout = sshSession.getStdout();
|
||||
InputStream stderr = sshSession.getStderr();
|
||||
|
||||
|
||||
byte[] buffer = new byte[8192];
|
||||
while (true) {
|
||||
if (stdout == null || stderr == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((stdout.available() == 0) && (stderr.available() == 0)) {
|
||||
int conditions = sshSession.waitForCondition(
|
||||
ChannelCondition.STDOUT_DATA
|
||||
| ChannelCondition.STDERR_DATA
|
||||
| ChannelCondition.EOF, 120000);
|
||||
|
||||
if ((conditions & ChannelCondition.TIMEOUT) != 0) {
|
||||
s_logger.info("Timeout while waiting for data from peer.");
|
||||
break;
|
||||
}
|
||||
|
||||
if ((conditions & ChannelCondition.EOF) != 0) {
|
||||
if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (stdout.available() > 0) {
|
||||
stdout.read(buffer);
|
||||
}
|
||||
|
||||
while (stderr.available() > 0) {
|
||||
stderr.read(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
Thread.sleep(1000);
|
||||
if (sshSession.getExitStatus() != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
s_logger.debug("Executing cmd: " + cmd + " failed, due to: " + e.toString());
|
||||
return false;
|
||||
} catch (InterruptedException e) {
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
} finally {
|
||||
if (sshSession != null)
|
||||
sshSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean sshExecuteCmd(com.trilead.ssh2.Connection sshConnection, String cmd, int nTimes) {
|
||||
for (int i = 0; i < nTimes; i ++) {
|
||||
if (sshExecuteCmd(sshConnection, cmd))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<? extends ServerResource, Map<String, String>> find(long dcId,
|
||||
|
|
@ -222,7 +142,7 @@ public class KvmServerDiscoverer extends DiscovererBase implements Discoverer,
|
|||
return null;
|
||||
}
|
||||
|
||||
if (!sshExecuteCmd(sshConnection, "lsmod|grep kvm >& /dev/null", 3)) {
|
||||
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, "lsmod|grep kvm >& /dev/null", 3)) {
|
||||
s_logger.debug("It's not a KVM enabled machine");
|
||||
return null;
|
||||
}
|
||||
|
|
@ -241,7 +161,7 @@ public class KvmServerDiscoverer extends DiscovererBase implements Discoverer,
|
|||
parameters += " -N " + _kvmPrivateNic;
|
||||
}
|
||||
|
||||
sshExecuteCmd(sshConnection, "/usr/bin/setup_agent.sh " + parameters + " 1>&2", 3);
|
||||
SSHCmdHelper.sshExecuteCmd(sshConnection, "/usr/bin/setup_agent.sh " + parameters + " 1>&2", 3);
|
||||
|
||||
KvmDummyResourceBase kvmResource = new KvmDummyResourceBase();
|
||||
Map<String, Object> params = new HashMap<String, Object>();
|
||||
|
|
|
|||
|
|
@ -380,13 +380,18 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
|
|||
if (imgfmt == null) {
|
||||
throw new IllegalArgumentException("Image format is incorrect " + format + ". Supported formats are " + EnumUtils.listValues(ImageFormat.values()));
|
||||
}
|
||||
|
||||
URI uri = new URI(url);
|
||||
if ((uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("http") && !uri.getScheme().equalsIgnoreCase("https") && !uri.getScheme().equalsIgnoreCase("file") && !uri.getScheme().equalsIgnoreCase("baremetal"))) {
|
||||
throw new IllegalArgumentException("Unsupported scheme for url: " + url);
|
||||
}
|
||||
|
||||
if (!uri.getScheme().equalsIgnoreCase("baremetal")) {
|
||||
|
||||
String uriStr;
|
||||
if (url.startsWith("baremetal://")) {
|
||||
uriStr = url.substring("baremetal://".length());
|
||||
} else {
|
||||
URI uri = new URI(url);
|
||||
if ((uri.getScheme() == null)
|
||||
|| (!uri.getScheme().equalsIgnoreCase("http") && !uri.getScheme().equalsIgnoreCase("https") && !uri.getScheme()
|
||||
.equalsIgnoreCase("file"))) {
|
||||
throw new IllegalArgumentException("Unsupported scheme for url: " + url);
|
||||
}
|
||||
|
||||
int port = uri.getPort();
|
||||
if (!(port == 80 || port == 443 || port == -1)) {
|
||||
throw new IllegalArgumentException("Only ports 80 and 443 are allowed");
|
||||
|
|
@ -403,6 +408,7 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
|
|||
} catch (UnknownHostException uhe) {
|
||||
throw new IllegalArgumentException("Unable to resolve " + host);
|
||||
}
|
||||
uriStr = uri.toString();
|
||||
}
|
||||
|
||||
// Check that the resource limit for templates/ISOs won't be exceeded
|
||||
|
|
@ -431,13 +437,13 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
|
|||
}
|
||||
}
|
||||
|
||||
return create(userId, accountId, zoneId, name, displayText, isPublic, featured, isExtractable, imgfmt, diskType, uri, chksum, requiresHvm, bits, enablePassword, guestOSId, bootable, hypervisorType);
|
||||
return create(userId, accountId, zoneId, name, displayText, isPublic, featured, isExtractable, imgfmt, diskType, uriStr, chksum, requiresHvm, bits, enablePassword, guestOSId, bootable, hypervisorType);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new IllegalArgumentException("Invalid URL " + url);
|
||||
}
|
||||
}
|
||||
|
||||
private VMTemplateVO create(long userId, long accountId, Long zoneId, String name, String displayText, boolean isPublic, boolean featured, boolean isExtractable, ImageFormat format, TemplateType type, URI url, String chksum, boolean requiresHvm, int bits, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType) {
|
||||
private VMTemplateVO create(long userId, long accountId, Long zoneId, String name, String displayText, boolean isPublic, boolean featured, boolean isExtractable, ImageFormat format, TemplateType type, String url, String chksum, boolean requiresHvm, int bits, boolean enablePassword, long guestOSId, boolean bootable, HypervisorType hyperType) {
|
||||
Long id = _tmpltDao.getNextInSequence(Long.class, "id");
|
||||
|
||||
AccountVO account = _accountDao.findById(accountId);
|
||||
|
|
@ -445,7 +451,7 @@ public class TemplateManagerImpl implements TemplateManager, Manager, TemplateSe
|
|||
throw new IllegalArgumentException("Only admins can create templates in all zones");
|
||||
}
|
||||
|
||||
VMTemplateVO template = new VMTemplateVO(id, name, format, isPublic, featured, isExtractable, type, url.toString(), requiresHvm, bits, accountId, chksum, displayText, enablePassword, guestOSId, bootable, hyperType);
|
||||
VMTemplateVO template = new VMTemplateVO(id, name, format, isPublic, featured, isExtractable, type, url, requiresHvm, bits, accountId, chksum, displayText, enablePassword, guestOSId, bootable, hyperType);
|
||||
if (zoneId == null) {
|
||||
List<DataCenterVO> dcs = _dcDao.listAllIncludingRemoved();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
package com.cloud.vm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executors;
|
||||
|
|
@ -10,12 +16,16 @@ import javax.naming.ConfigurationException;
|
|||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.baremetal.PrepareLinMinPxeServerCommand;
|
||||
import com.cloud.agent.manager.Commands;
|
||||
import com.cloud.api.commands.AttachVolumeCmd;
|
||||
import com.cloud.api.commands.CreateTemplateCmd;
|
||||
import com.cloud.api.commands.DeployVMCmd;
|
||||
import com.cloud.api.commands.DetachVolumeCmd;
|
||||
import com.cloud.api.commands.UpgradeVMCmd;
|
||||
import com.cloud.baremetal.LinMinPxeServerManager;
|
||||
import com.cloud.baremetal.PxeServerManager;
|
||||
import com.cloud.baremetal.PxeServerManager.PxeServerType;
|
||||
import com.cloud.configuration.ResourceCount.ResourceType;
|
||||
import com.cloud.configuration.dao.ConfigurationDao;
|
||||
import com.cloud.dc.DataCenterVO;
|
||||
|
|
@ -32,28 +42,36 @@ import com.cloud.exception.PermissionDeniedException;
|
|||
import com.cloud.exception.ResourceAllocationException;
|
||||
import com.cloud.exception.ResourceUnavailableException;
|
||||
import com.cloud.exception.StorageUnavailableException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.network.Network;
|
||||
import com.cloud.network.NetworkVO;
|
||||
import com.cloud.network.IpAddrAllocator.IpAddr;
|
||||
import com.cloud.network.Networks.TrafficType;
|
||||
import com.cloud.server.ManagementService;
|
||||
import com.cloud.service.ServiceOfferingVO;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.VMTemplateVO;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.Storage.TemplateType;
|
||||
import com.cloud.user.Account;
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.user.SSHKeyPair;
|
||||
import com.cloud.user.UserContext;
|
||||
import com.cloud.user.UserVO;
|
||||
import com.cloud.uservm.UserVm;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.utils.Pair;
|
||||
import com.cloud.utils.component.ComponentLocator;
|
||||
import com.cloud.utils.component.Manager;
|
||||
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||
import com.cloud.utils.crypt.RSAHelper;
|
||||
import com.cloud.utils.db.DB;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.utils.net.NetUtils;
|
||||
import com.cloud.vm.VirtualMachine.Type;
|
||||
import com.cloud.vm.VirtualMachineProfile.Param;
|
||||
|
||||
@Local(value={BareMetalVmManager.class, BareMetalVmService.class})
|
||||
public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMetalVmManager, BareMetalVmService, Manager {
|
||||
|
|
@ -286,7 +304,30 @@ public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMet
|
|||
}
|
||||
|
||||
public UserVm startVirtualMachine(DeployVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException {
|
||||
return super.startVirtualMachine(cmd);
|
||||
long vmId = cmd.getEntityId();
|
||||
UserVmVO vm = _vmDao.findById(vmId);
|
||||
_vmDao.loadDetails(vm);
|
||||
|
||||
List<HostVO> servers = _hostDao.listBy(Host.Type.PxeServer, vm.getDataCenterId());
|
||||
if (servers.size() == 0) {
|
||||
throw new CloudRuntimeException("Cannot find PXE server, please make sure there is one PXE server per zone");
|
||||
}
|
||||
HostVO pxeServer = servers.get(0);
|
||||
|
||||
VMTemplateVO template = _templateDao.findById(vm.getTemplateId());
|
||||
if (template == null || template.getFormat() != Storage.ImageFormat.BAREMETAL) {
|
||||
throw new InvalidParameterValueException("Invalid template with id = " + vm.getTemplateId());
|
||||
}
|
||||
|
||||
Map<VirtualMachineProfile.Param, Object> params = new HashMap<VirtualMachineProfile.Param, Object>();
|
||||
//TODO: have to ugly harding code here
|
||||
if (pxeServer.getResource().equalsIgnoreCase("com.cloud.baremetal.LinMinPxeServerResource")) {
|
||||
params.put(Param.PxeSeverType, PxeServerType.LinMin);
|
||||
} else {
|
||||
throw new CloudRuntimeException("Unkown PXE server resource " + pxeServer.getResource());
|
||||
}
|
||||
|
||||
return startVirtualMachine(cmd, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -333,6 +374,39 @@ public class BareMetalVmManagerImpl extends UserVmManagerImpl implements BareMet
|
|||
throw new PermissionDeniedException("The owner of " + vm + " either does not exist or is disabled: " + vm.getAccountId());
|
||||
}
|
||||
|
||||
if (profile.getTemplate() == null) {
|
||||
s_logger.debug("This is a normal IPMI start, skip prepartion of PXE server");
|
||||
return true;
|
||||
}
|
||||
|
||||
s_logger.debug("This is a PXE start, prepare PXE server first");
|
||||
PxeServerType pxeType = (PxeServerType) profile.getParameter(Param.PxeSeverType);
|
||||
if (pxeType == null) {
|
||||
throw new CloudRuntimeException("No PXE type specified");
|
||||
}
|
||||
|
||||
PxeServerManager pxeMgr = null;
|
||||
ComponentLocator locator = ComponentLocator.getLocator(ManagementService.Name);
|
||||
if (pxeType == PxeServerType.LinMin) {
|
||||
pxeMgr = locator.getManager(LinMinPxeServerManager.class);
|
||||
} else {
|
||||
throw new CloudRuntimeException("Unsupport PXE type " + pxeType.toString());
|
||||
}
|
||||
|
||||
if (pxeMgr == null) {
|
||||
throw new CloudRuntimeException("No PXE manager find for type " + pxeType.toString());
|
||||
}
|
||||
|
||||
List<HostVO> servers = _hostDao.listBy(Host.Type.PxeServer, vm.getDataCenterId());
|
||||
if (servers.size() == 0) {
|
||||
throw new CloudRuntimeException("Cannot find PXE server, please make sure there is one PXE server per zone");
|
||||
}
|
||||
HostVO pxeServer = servers.get(0);
|
||||
|
||||
if (!pxeMgr.prepare(profile, dest, context, pxeServer.getId())) {
|
||||
throw new CloudRuntimeException("Pepare PXE server failed");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2106,6 +2106,10 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
|
|||
|
||||
@Override @ActionEvent (eventType=EventTypes.EVENT_VM_CREATE, eventDescription="starting Vm", async=true)
|
||||
public UserVm startVirtualMachine(DeployVMCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException {
|
||||
return startVirtualMachine(cmd, null);
|
||||
}
|
||||
|
||||
protected UserVm startVirtualMachine(DeployVMCmd cmd, Map<VirtualMachineProfile.Param, Object> additonalParams) throws ResourceUnavailableException, InsufficientCapacityException, ConcurrentOperationException {
|
||||
long vmId = cmd.getEntityId();
|
||||
UserVmVO vm = _vmDao.findById(vmId);
|
||||
_vmDao.loadDetails(vm);
|
||||
|
|
@ -2142,6 +2146,9 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
|
|||
|
||||
try {
|
||||
Map<VirtualMachineProfile.Param, Object> params = new HashMap<VirtualMachineProfile.Param, Object>();
|
||||
if (additonalParams != null) {
|
||||
params.putAll(additonalParams);
|
||||
}
|
||||
params.put(VirtualMachineProfile.Param.VmPassword, password);
|
||||
vm = _itMgr.start(vm, params, caller, owner);
|
||||
} finally {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
package com.cloud.utils.ssh;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.trilead.ssh2.ChannelCondition;
|
||||
import com.trilead.ssh2.Session;
|
||||
|
||||
public class SSHCmdHelper {
|
||||
private static final Logger s_logger = Logger.getLogger(SSHCmdHelper.class);
|
||||
|
||||
public static boolean sshExecuteCmd(com.trilead.ssh2.Connection sshConnection, String cmd, int nTimes) {
|
||||
for (int i = 0; i < nTimes; i ++) {
|
||||
if (sshExecuteCmdOneShot(sshConnection, cmd))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean sshExecuteCmd(com.trilead.ssh2.Connection sshConnection, String cmd) {
|
||||
return sshExecuteCmd(sshConnection, cmd, 3);
|
||||
}
|
||||
|
||||
public static boolean sshExecuteCmdOneShot(com.trilead.ssh2.Connection sshConnection, String cmd) {
|
||||
s_logger.debug("Executing cmd: " + cmd);
|
||||
Session sshSession = null;
|
||||
try {
|
||||
sshSession = sshConnection.openSession();
|
||||
// There is a bug in Trilead library, wait a second before
|
||||
// starting a shell and executing commands, from http://spci.st.ewi.tudelft.nl/chiron/xref/nl/tudelft/swerl/util/SSHConnection.html
|
||||
Thread.sleep(1000);
|
||||
|
||||
if (sshSession == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sshSession.execCommand(cmd);
|
||||
|
||||
InputStream stdout = sshSession.getStdout();
|
||||
InputStream stderr = sshSession.getStderr();
|
||||
|
||||
|
||||
byte[] buffer = new byte[8192];
|
||||
while (true) {
|
||||
if (stdout == null || stderr == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((stdout.available() == 0) && (stderr.available() == 0)) {
|
||||
int conditions = sshSession.waitForCondition(
|
||||
ChannelCondition.STDOUT_DATA
|
||||
| ChannelCondition.STDERR_DATA
|
||||
| ChannelCondition.EOF, 120000);
|
||||
|
||||
if ((conditions & ChannelCondition.TIMEOUT) != 0) {
|
||||
s_logger.info("Timeout while waiting for data from peer.");
|
||||
break;
|
||||
}
|
||||
|
||||
if ((conditions & ChannelCondition.EOF) != 0) {
|
||||
if ((conditions & (ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA)) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (stdout.available() > 0) {
|
||||
stdout.read(buffer);
|
||||
}
|
||||
|
||||
while (stderr.available() > 0) {
|
||||
stderr.read(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
Thread.sleep(1000);
|
||||
if (sshSession.getExitStatus() != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
s_logger.debug("Executing cmd: " + cmd + " failed, due to: " + e.toString());
|
||||
return false;
|
||||
} catch (InterruptedException e) {
|
||||
return false;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
} finally {
|
||||
if (sshSession != null)
|
||||
sshSession.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue