CloudStack CLOUDSTACK-774

Supporting kickstart in CloudStack baremetal

able to start vm

Conflicts:

	client/tomcatconf/componentContext.xml.in
	server/src/com/cloud/baremetal/BareMetalTemplateAdapter.java
	server/src/com/cloud/baremetal/BareMetalVmManagerImpl.java
	server/src/com/cloud/vm/UserVmManagerImpl.java
This commit is contained in:
frank 2013-02-19 17:10:45 -08:00
parent 55b77c7c8f
commit 15ead099a1
38 changed files with 190 additions and 3215 deletions

View File

@ -388,7 +388,7 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
} catch (InsufficientCapacityException ex) {
s_logger.info(ex);
s_logger.trace(ex);
s_logger.info(ex.getMessage(), ex);
throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage());
}
} else {
@ -477,7 +477,7 @@ public class DeployVMCmd extends BaseAsyncCreateCmd {
}
} catch (InsufficientCapacityException ex) {
s_logger.info(ex);
s_logger.trace(ex);
s_logger.trace(ex.getMessage(), ex);
throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage());
} catch (ResourceUnavailableException ex) {
s_logger.warn("Exception: ", ex);

View File

@ -65,9 +65,6 @@
<bean id="Ovs" class="com.cloud.network.element.OvsElement">
<property name="name" value="Ovs"/>
</bean>
<bean id="ExternalDhcpServer" class="com.cloud.network.element.ExternalDhcpElement">
<property name="name" value="ExternalDhcpServer"/>
</bean>
<bean id="BareMetalDhcp" class="com.cloud.baremetal.networkservice.BaremetalDhcpElement">
<property name="name" value="BareMetalDhcp"/>
</bean>
@ -223,9 +220,17 @@
<property name="name" value="UserConcentratedPod"/>
</bean>
<bean id="BareMetalPlanner" class="com.cloud.deploy.BareMetalPlanner">
<bean id="BareMetalPlanner" class="com.cloud.baremetal.manager.BareMetalPlanner">
<property name="name" value="BareMetal Fit"/>
</bean>
<bean id="BaremetalPlannerSelector" class="com.cloud.baremetal.manager.BaremetalPlannerSelector">
<property name="name" value="BaremetalPlannerSelector"/>
</bean>
<bean id="HypervisorPlannerSelector" class="com.cloud.deploy.HypervisorVmPlannerSelector">
<property name="name" value="BaremetalPlannerSelector"/>
</bean>
<!--
@ -279,10 +284,6 @@
<property name="name" value="KVMGuru"/>
</bean>
<bean id="BareMetalGuru" class="com.cloud.baremetal.BareMetalGuru">
<property name="name" value="BareMetalGuru"/>
</bean>
<bean id="HypervGuru" class="com.cloud.hypervisor.guru.HypervGuru">
<property name="name" value="HypervGuru"/>
</bean>
@ -296,5 +297,9 @@
<property name="name" value="SimulatorGuru"/>
</bean>
-->
<bean id="BaremetalGuru" class="com.cloud.baremetal.manager.BareMetalGuru">
<property name="name" value="BaremetalGuru"/>
</bean>
</beans>

View File

@ -105,7 +105,7 @@ under the License.
</category>
<category name="org.apache.cloudstack.api.command">
<priority value="DEBUG"/>
<priority value="TRACE"/>
</category>
<category name="org">

View File

@ -42,6 +42,7 @@ import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.exception.OperationTimedoutException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.dao.NetworkDao;
import com.cloud.org.Cluster;
import com.cloud.service.dao.ServiceOfferingDao;
@ -168,10 +169,13 @@ public class VMEntityManagerImpl implements VMEntityManager {
//save destination with VMEntityVO
VMReservationVO vmReservation = new VMReservationVO(vm.getId(), dest.getDataCenter().getId(), dest.getPod().getId(), dest.getCluster().getId(), dest.getHost().getId());
Map<Long,Long> volumeReservationMap = new HashMap<Long,Long>();
for(Volume vo : dest.getStorageForDisks().keySet()){
volumeReservationMap.put(vo.getId(), dest.getStorageForDisks().get(vo).getId());
if (vm.getHypervisorType() != HypervisorType.BareMetal) {
for(Volume vo : dest.getStorageForDisks().keySet()){
volumeReservationMap.put(vo.getId(), dest.getStorageForDisks().get(vo).getId());
}
vmReservation.setVolumeReservation(volumeReservationMap);
}
vmReservation.setVolumeReservation(volumeReservationMap);
vmEntityVO.setVmReservation(vmReservation);
_vmEntityDao.persist(vmEntityVO);

View File

@ -14,7 +14,7 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.deploy;
package com.cloud.baremetal.manager;
import java.util.List;
import java.util.Map;
@ -34,6 +34,10 @@ import com.cloud.dc.Pod;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.deploy.DeploymentPlanner;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;

View File

@ -0,0 +1,23 @@
package com.cloud.baremetal.manager;
import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import com.cloud.deploy.AbstractDeployPlannerSelector;
import com.cloud.deploy.DeployPlannerSelector;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.vm.UserVmVO;
@Local(value = {DeployPlannerSelector.class})
public class BaremetalPlannerSelector extends AbstractDeployPlannerSelector{
@Override
public String selectPlanner(UserVmVO vm) {
if (vm.getHypervisorType() == HypervisorType.BareMetal) {
return "BareMetalPlanner";
}
return null;
}
}

View File

@ -1,245 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
import java.net.InetAddress;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import org.apache.cloudstack.api.ApiConstants;
import com.cloud.dc.ClusterVO;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.ClusterDao;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.exception.DiscoveryException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
import com.cloud.resource.Discoverer;
import com.cloud.resource.DiscovererBase;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ResourceStateAdapter;
import com.cloud.resource.ServerResource;
import com.cloud.resource.UnableDeleteHostException;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
import com.cloud.utils.script.Script2;
import com.cloud.utils.script.Script2.ParamType;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.dao.VMInstanceDao;
@Local(value=Discoverer.class)
public class BareMetalDiscoverer extends DiscovererBase implements Discoverer, ResourceStateAdapter {
private static final Logger s_logger = Logger.getLogger(BareMetalDiscoverer.class);
@Inject ClusterDao _clusterDao;
@Inject protected HostDao _hostDao;
@Inject DataCenterDao _dcDao;
@Inject VMInstanceDao _vmDao = null;
@Inject ResourceManager _resourceMgr;
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_resourceMgr.registerResourceStateAdapter(this.getClass().getSimpleName(), this);
return super.configure(name, params);
}
@Override
public boolean stop() {
_resourceMgr.unregisterResourceStateAdapter(this.getClass().getSimpleName());
return super.stop();
}
@Override
public Map<? extends ServerResource, Map<String, String>> find(long dcId, Long podId, Long clusterId, URI url, String username, String password, List<String> hostTags)
throws DiscoveryException {
Map<BareMetalResourceBase, Map<String, String>> resources = new HashMap<BareMetalResourceBase, Map<String, String>>();
Map<String, String> details = new HashMap<String, String>();
if (!url.getScheme().equals("http")) {
String msg = "urlString is not http so we're not taking care of the discovery for this: " + url;
s_logger.debug(msg);
return null;
}
if (clusterId == null) {
String msg = "must specify cluster Id when add host";
s_logger.debug(msg);
throw new RuntimeException(msg);
}
if (podId == null) {
String msg = "must specify pod Id when add host";
s_logger.debug(msg);
throw new RuntimeException(msg);
}
ClusterVO cluster = _clusterDao.findById(clusterId);
if (cluster == null || (cluster.getHypervisorType() != HypervisorType.BareMetal)) {
if (s_logger.isInfoEnabled())
s_logger.info("invalid cluster id or cluster is not for Bare Metal hosts");
return null;
}
DataCenterVO zone = _dcDao.findById(dcId);
if (zone == null) {
throw new RuntimeException("Cannot find zone " + dcId);
}
try {
String hostname = url.getHost();
InetAddress ia = InetAddress.getByName(hostname);
String ipmiIp = ia.getHostAddress();
String guid = UUID.nameUUIDFromBytes(ipmiIp.getBytes()).toString();
String injectScript = "scripts/util/ipmi.py";
String scriptPath = Script.findScript("", injectScript);
if (scriptPath == null) {
throw new CloudRuntimeException("Unable to find key ipmi script "
+ injectScript);
}
final Script2 command = new Script2(scriptPath, s_logger);
command.add("ping");
command.add("hostname="+ipmiIp);
command.add("usrname="+username);
command.add("password="+password, ParamType.PASSWORD);
final String result = command.execute();
if (result != null) {
s_logger.warn(String.format("Can not set up ipmi connection(ip=%1$s, username=%2$s, password=%3$s, args) because %4$s", ipmiIp, username, "******", result));
return null;
}
ClusterVO clu = _clusterDao.findById(clusterId);
if (clu.getGuid() == null) {
clu.setGuid(UUID.randomUUID().toString());
_clusterDao.update(clusterId, clu);
}
Map<String, Object> params = new HashMap<String, Object>();
params.putAll(_params);
params.put("zone", Long.toString(dcId));
params.put("pod", Long.toString(podId));
params.put("cluster", Long.toString(clusterId));
params.put("guid", guid);
params.put(ApiConstants.PRIVATE_IP, ipmiIp);
params.put(ApiConstants.USERNAME, username);
params.put(ApiConstants.PASSWORD, password);
BareMetalResourceBase resource = new BareMetalResourceBase();
resource.configure("Bare Metal Agent", params);
String memCapacity = (String)params.get(ApiConstants.MEMORY);
String cpuCapacity = (String)params.get(ApiConstants.CPU_SPEED);
String cpuNum = (String)params.get(ApiConstants.CPU_NUMBER);
String mac = (String)params.get(ApiConstants.HOST_MAC);
if (hostTags != null && hostTags.size() != 0) {
details.put("hostTag", hostTags.get(0));
}
details.put(ApiConstants.MEMORY, memCapacity);
details.put(ApiConstants.CPU_SPEED, cpuCapacity);
details.put(ApiConstants.CPU_NUMBER, cpuNum);
details.put(ApiConstants.HOST_MAC, mac);
details.put(ApiConstants.USERNAME, username);
details.put(ApiConstants.PASSWORD, password);
details.put(ApiConstants.PRIVATE_IP, ipmiIp);
resources.put(resource, details);
resource.start();
zone.setGatewayProvider(Network.Provider.ExternalGateWay.getName());
zone.setDnsProvider(Network.Provider.ExternalDhcpServer.getName());
zone.setDhcpProvider(Network.Provider.ExternalDhcpServer.getName());
_dcDao.update(zone.getId(), zone);
s_logger.debug(String.format("Discover Bare Metal host successfully(ip=%1$s, username=%2$s, password=%3%s," +
"cpuNum=%4$s, cpuCapacity-%5$s, memCapacity=%6$s)", ipmiIp, username, "******", cpuNum, cpuCapacity, memCapacity));
return resources;
} catch (Exception e) {
s_logger.warn("Can not set up bare metal agent", e);
}
return null;
}
@Override
public void postDiscovery(List<HostVO> hosts, long msId)
throws DiscoveryException {
}
@Override
public boolean matchHypervisor(String hypervisor) {
return hypervisor.equalsIgnoreCase(Hypervisor.HypervisorType.BareMetal.toString());
}
@Override
public HypervisorType getHypervisorType() {
return Hypervisor.HypervisorType.BareMetal;
}
@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) {
StartupCommand firstCmd = startup[0];
if (!(firstCmd instanceof StartupRoutingCommand)) {
return null;
}
StartupRoutingCommand ssCmd = ((StartupRoutingCommand) firstCmd);
if (ssCmd.getHypervisorType() != HypervisorType.BareMetal) {
return null;
}
return _resourceMgr.fillRoutingHostVO(host, ssCmd, HypervisorType.BareMetal, details, hostTags);
}
@Override
public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
if (host.getType() != Host.Type.Routing || host.getHypervisorType() != HypervisorType.BareMetal) {
return null;
}
List<VMInstanceVO> deadVms = _vmDao.listByLastHostId(host.getId());
for (VMInstanceVO vm : deadVms) {
if (vm.getState() == State.Running || vm.getHostId() != null) {
throw new CloudRuntimeException("VM " + vm.getId() + "is still running on host " + host.getId());
}
_vmDao.remove(vm.getId());
}
return new DeleteHostAnswer(true);
}
}

View File

@ -1,59 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
import javax.ejb.Local;
import javax.inject.Inject;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.hypervisor.HypervisorGuru;
import com.cloud.hypervisor.HypervisorGuruBase;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
@Local(value=HypervisorGuru.class)
public class BareMetalGuru extends HypervisorGuruBase implements HypervisorGuru {
@Inject GuestOSDao _guestOsDao;
protected BareMetalGuru() {
super();
}
@Override
public HypervisorType getHypervisorType() {
return HypervisorType.BareMetal;
}
@Override
public <T extends VirtualMachine> VirtualMachineTO implement(VirtualMachineProfile<T> vm) {
VirtualMachineTO to = toVirtualMachineTO(vm);
// Determine the VM's OS description
GuestOSVO guestOS = _guestOsDao.findById(vm.getVirtualMachine().getGuestOSId());
to.setOs(guestOS.getDisplayName());
return to;
}
@Override
public boolean trackVmHostChange() {
return true;
}
}

View File

@ -1,199 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.agent.api.Answer;
import com.cloud.agent.api.baremetal.PreparePxeServerAnswer;
import com.cloud.agent.api.baremetal.PreparePxeServerCommand;
import com.cloud.agent.api.baremetal.prepareCreateTemplateCommand;
import com.cloud.baremetal.PxeServerManager.PxeServerType;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.HostPodVO;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ServerResource;
import com.cloud.uservm.UserVm;
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.UserVmVO;
import com.cloud.vm.VirtualMachineProfile;
@Component
@Local(value=PxeServerService.class)
public class BareMetalPingServiceImpl extends BareMetalPxeServiceBase implements PxeServerService {
private static final Logger s_logger = Logger.getLogger(BareMetalPingServiceImpl.class);
@Inject ResourceManager _resourceMgr;
@Override
public Host addPxeServer(PxeServerProfile profile) {
Long zoneId = profile.getZoneId();
Long podId = profile.getPodId();
DataCenterVO zone = _dcDao.findById(zoneId);
if (zone == null) {
throw new InvalidParameterValueException("Could not find zone with ID: " + zoneId);
}
List<HostVO> pxeServers = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.PxeServer, null, podId, zoneId);
if (pxeServers.size() != 0) {
InvalidParameterValueException ex = new InvalidParameterValueException("Already had a PXE server in Pod with specified podId and zone with specified zoneId");
ex.addProxyObject("pod", podId, "podId");
ex.addProxyObject(zone, zoneId, "zoneId");
}
String ipAddress = profile.getUrl();
String username = profile.getUsername();
String password = profile.getPassword();
ServerResource resource = null;
Map params = new HashMap<String, String>();
params.put("type", PxeServerType.PING.getName());
params.put("zone", Long.toString(zoneId));
params.put("pod", podId.toString());
params.put("ip", ipAddress);
params.put("username", username);
params.put("password", password);
if (profile.getType().equalsIgnoreCase(PxeServerType.PING.getName())) {
String storageServerIp = profile.getPingStorageServerIp();
if (storageServerIp == null) {
throw new InvalidParameterValueException("No IP for storage server specified");
}
String pingDir = profile.getPingDir();
if (pingDir == null) {
throw new InvalidParameterValueException("No direcotry for storage server specified");
}
String tftpDir = profile.getTftpDir();
if (tftpDir == null) {
throw new InvalidParameterValueException("No TFTP directory specified");
}
String cifsUsername = profile.getPingCifsUserName();
if (cifsUsername == null || cifsUsername.equalsIgnoreCase("")) {
cifsUsername = "xxx";
}
String cifsPassword = profile.getPingCifspassword();
if (cifsPassword == null || cifsPassword.equalsIgnoreCase("")) {
cifsPassword = "xxx";
}
String guid = getPxeServerGuid(Long.toString(zoneId) + "-" + Long.toString(podId), PxeServerType.PING.getName(), ipAddress);
params.put("storageServer", storageServerIp);
params.put("pingDir", pingDir);
params.put("tftpDir", tftpDir);
params.put("cifsUserName", cifsUsername);
params.put("cifsPassword", cifsPassword);
params.put("guid", guid);
resource = new PingPxeServerResource();
try {
resource.configure("PING PXE resource", params);
} catch (Exception e) {
s_logger.debug(e);
throw new CloudRuntimeException(e.getMessage());
}
} else {
throw new CloudRuntimeException("Unsupport PXE server type:" + profile.getType());
}
Host pxeServer = _resourceMgr.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 tpl = profile.getTemplate().getUrl();
assert tpl != null : "How can a null template get here!!!";
PreparePxeServerCommand cmd = new PreparePxeServerCommand(ip, mac, mask, gateway, dns, tpl,
profile.getVirtualMachine().getInstanceName(), dest.getHost().getName());
PreparePxeServerAnswer ans = (PreparePxeServerAnswer) _agentMgr.send(pxeServerId, cmd);
return ans.getResult();
} catch (Exception e) {
s_logger.warn("Cannot prepare PXE server", e);
return false;
}
}
@Override
public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl) {
List<NicVO> nics = _nicDao.listByVmId(vm.getId());
if (nics.size() != 1) {
throw new CloudRuntimeException("Wrong nic number " + nics.size() + " of vm " + vm.getId());
}
/* use last host id when VM stopped */
Long hostId = (vm.getHostId() == null ? vm.getLastHostId() : vm.getHostId());
HostVO host = _hostDao.findById(hostId);
DataCenterVO dc = _dcDao.findById(host.getDataCenterId());
NicVO nic = nics.get(0);
String mask = nic.getNetmask();
String mac = nic.getMacAddress();
String ip = nic.getIp4Address();
String gateway = nic.getGateway();
String dns = dc.getDns1();
if (dns == null) {
dns = dc.getDns2();
}
try {
prepareCreateTemplateCommand cmd = new prepareCreateTemplateCommand(ip, mac, mask, gateway, dns, templateUrl);
Answer ans = _agentMgr.send(pxeServerId, cmd);
return ans.getResult();
} catch (Exception e) {
s_logger.debug("Prepare for creating baremetal template failed", e);
return false;
}
}
}

View File

@ -1,56 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
import java.util.Map;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.agent.AgentManager;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.Host;
import com.cloud.host.dao.HostDao;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.NicDao;
public abstract class BareMetalPxeServiceBase extends ManagerBase implements PxeServerService {
@Inject DataCenterDao _dcDao;
@Inject HostDao _hostDao;
@Inject AgentManager _agentMgr;
@Inject ExternalDhcpManager exDhcpMgr;
@Inject HostPodDao _podDao;
@Inject NicDao _nicDao;
@Override
public boolean prepare(VirtualMachineProfile<UserVmVO> profile, DeployDestination dest, ReservationContext context, Long pxeServerId) {
throw new CloudRuntimeException("Dervied class should implement this method");
}
protected String getPxeServerGuid(String zoneId, String name, String ip) {
return zoneId + "-" + name + "-" + ip;
}
@Override
public abstract Host addPxeServer(PxeServerProfile profile);
}

View File

@ -1,630 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
import java.util.HashMap;
import java.util.Map;
import javax.ejb.Local;
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.CheckNetworkAnswer;
import com.cloud.agent.api.CheckNetworkCommand;
import com.cloud.agent.api.CheckVirtualMachineAnswer;
import com.cloud.agent.api.CheckVirtualMachineCommand;
import com.cloud.agent.api.Command;
import com.cloud.agent.api.MaintainAnswer;
import com.cloud.agent.api.MaintainCommand;
import com.cloud.agent.api.MigrateAnswer;
import com.cloud.agent.api.MigrateCommand;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.PrepareForMigrationAnswer;
import com.cloud.agent.api.PrepareForMigrationCommand;
import com.cloud.agent.api.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.RebootAnswer;
import com.cloud.agent.api.RebootCommand;
import com.cloud.agent.api.StartAnswer;
import com.cloud.agent.api.StartCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupRoutingCommand;
import com.cloud.agent.api.StopAnswer;
import com.cloud.agent.api.StopCommand;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand;
import com.cloud.agent.api.baremetal.IpmISetBootDevCommand.BootDev;
import com.cloud.agent.api.baremetal.IpmiBootorResetCommand;
import com.cloud.agent.api.to.VirtualMachineTO;
import org.apache.cloudstack.api.ApiConstants;
import com.cloud.host.Host.Type;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.resource.ServerResource;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.OutputInterpreter;
import com.cloud.utils.script.Script;
import com.cloud.utils.script.Script2;
import com.cloud.utils.script.Script2.ParamType;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
@Local(value = ServerResource.class)
public class BareMetalResourceBase implements ServerResource {
private static final Logger s_logger = Logger.getLogger(BareMetalResourceBase.class);
protected HashMap<String, State> _vms = new HashMap<String, State>(2);
protected String _name;
protected String _uuid;
protected String _zone;
protected String _pod;
protected String _cluster;
protected long _memCapacity;
protected long _cpuCapacity;
protected long _cpuNum;
protected String _mac;
protected String _username;
protected String _password;
protected String _ip;
protected IAgentControl _agentControl;
protected Script2 _pingCommand;
protected Script2 _setPxeBootCommand;
protected Script2 _setDiskBootCommand;
protected Script2 _rebootCommand;
protected Script2 _getStatusCommand;
protected Script2 _powerOnCommand;
protected Script2 _powerOffCommand;
protected Script2 _forcePowerOffCommand;
protected Script2 _bootOrRebootCommand;
protected String _vmName;
private void changeVmState(String vmName, VirtualMachine.State state) {
synchronized (_vms) {
_vms.put(vmName, state);
}
}
private State removeVmState(String vmName) {
synchronized (_vms) {
return _vms.remove(vmName);
}
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
_name = name;
_uuid = (String) params.get("guid");
try {
_memCapacity = Long.parseLong((String)params.get(ApiConstants.MEMORY)) * 1024L * 1024L;
_cpuCapacity = Long.parseLong((String)params.get(ApiConstants.CPU_SPEED));
_cpuNum = Long.parseLong((String)params.get(ApiConstants.CPU_NUMBER));
} catch (NumberFormatException e) {
throw new ConfigurationException(String.format("Unable to parse number of CPU or memory capacity " +
"or cpu capacity(cpu number = %1$s memCapacity=%2$s, cpuCapacity=%3$s", (String)params.get(ApiConstants.CPU_NUMBER),
(String)params.get(ApiConstants.MEMORY), (String)params.get(ApiConstants.CPU_SPEED)));
}
_zone = (String) params.get("zone");
_pod = (String) params.get("pod");
_cluster = (String) params.get("cluster");
_ip = (String)params.get(ApiConstants.PRIVATE_IP);
_mac = (String)params.get(ApiConstants.HOST_MAC);
_username = (String)params.get(ApiConstants.USERNAME);
_password = (String)params.get(ApiConstants.PASSWORD);
_vmName = (String)params.get("vmName");
if (_pod == null) {
throw new ConfigurationException("Unable to get the pod");
}
if (_cluster == null) {
throw new ConfigurationException("Unable to get the pod");
}
if (_ip == null) {
throw new ConfigurationException("Unable to get the host address");
}
if (_mac.equalsIgnoreCase("unknown")) {
throw new ConfigurationException("Unable to get the host mac address");
}
if (_mac.split(":").length != 6) {
throw new ConfigurationException("Wrong MAC format(" + _mac + "). It must be in format of for example 00:11:ba:33:aa:dd which is not case sensitive");
}
if (_uuid == null) {
throw new ConfigurationException("Unable to get the uuid");
}
String injectScript = "scripts/util/ipmi.py";
String scriptPath = Script.findScript("", injectScript);
if (scriptPath == null) {
throw new ConfigurationException("Cannot find ping script " + scriptPath);
}
_pingCommand = new Script2(scriptPath, s_logger);
_pingCommand.add("ping");
_pingCommand.add("hostname="+_ip);
_pingCommand.add("usrname="+_username);
_pingCommand.add("password="+_password, ParamType.PASSWORD);
_setPxeBootCommand = new Script2(scriptPath, s_logger);
_setPxeBootCommand.add("boot_dev");
_setPxeBootCommand.add("hostname="+_ip);
_setPxeBootCommand.add("usrname="+_username);
_setPxeBootCommand.add("password="+_password, ParamType.PASSWORD);
_setPxeBootCommand.add("dev=pxe");
_setDiskBootCommand = new Script2(scriptPath, s_logger);
_setDiskBootCommand.add("boot_dev");
_setDiskBootCommand.add("hostname="+_ip);
_setDiskBootCommand.add("usrname="+_username);
_setDiskBootCommand.add("password="+_password, ParamType.PASSWORD);
_setDiskBootCommand.add("dev=disk");
_rebootCommand = new Script2(scriptPath, s_logger);
_rebootCommand.add("reboot");
_rebootCommand.add("hostname="+_ip);
_rebootCommand.add("usrname="+_username);
_rebootCommand.add("password="+_password, ParamType.PASSWORD);
_getStatusCommand = new Script2(scriptPath, s_logger);
_getStatusCommand.add("ping");
_getStatusCommand.add("hostname="+_ip);
_getStatusCommand.add("usrname="+_username);
_getStatusCommand.add("password="+_password, ParamType.PASSWORD);
_powerOnCommand = new Script2(scriptPath, s_logger);
_powerOnCommand.add("power");
_powerOnCommand.add("hostname="+_ip);
_powerOnCommand.add("usrname="+_username);
_powerOnCommand.add("password="+_password, ParamType.PASSWORD);
_powerOnCommand.add("action=on");
_powerOffCommand = new Script2(scriptPath, s_logger);
_powerOffCommand.add("power");
_powerOffCommand.add("hostname="+_ip);
_powerOffCommand.add("usrname="+_username);
_powerOffCommand.add("password="+_password, ParamType.PASSWORD);
_powerOffCommand.add("action=soft");
_forcePowerOffCommand = new Script2(scriptPath, s_logger);
_forcePowerOffCommand.add("power");
_forcePowerOffCommand.add("hostname=" + _ip);
_forcePowerOffCommand.add("usrname=" + _username);
_forcePowerOffCommand.add("password=" + _password, ParamType.PASSWORD);
_forcePowerOffCommand.add("action=off");
_bootOrRebootCommand = new Script2(scriptPath, s_logger);
_bootOrRebootCommand.add("boot_or_reboot");
_bootOrRebootCommand.add("hostname="+_ip);
_bootOrRebootCommand.add("usrname="+_username);
_bootOrRebootCommand.add("password="+_password, ParamType.PASSWORD);
return true;
}
protected boolean doScript(Script cmd) {
return doScript(cmd, null);
}
protected boolean doScript(Script cmd, OutputInterpreter interpreter) {
int retry = 5;
String res = null;
while (retry-- > 0) {
if (interpreter == null) {
res = cmd.execute();
} else {
res = cmd.execute(interpreter);
}
if (res != null && res.startsWith("Error: Unable to establish LAN")) {
s_logger.warn("IPMI script timeout(" + cmd.toString() + "), will retry " + retry + " times");
continue;
} else if (res == null) {
return true;
} else {
break;
}
}
s_logger.warn("IPMI Scirpt failed due to " + res + "(" + cmd.toString() +")");
return false;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public String getName() {
return _name;
}
@Override
public Type getType() {
return com.cloud.host.Host.Type.Routing;
}
protected State getVmState() {
OutputInterpreter.AllLinesParser interpreter = new OutputInterpreter.AllLinesParser();
if (!doScript(_getStatusCommand, interpreter)) {
s_logger.warn("Cannot get power status of " + _name + ", assume VM state was not changed");
return null;
}
if (isPowerOn(interpreter.getLines())) {
return State.Running;
} else {
return State.Stopped;
}
}
protected Map<String, State> fullSync() {
Map<String, State> changes = new HashMap<String, State>();
if (_vmName != null) {
State state = getVmState();
if (state != null) {
changes.put(_vmName, state);
}
}
return changes;
}
@Override
public StartupCommand[] initialize() {
StartupRoutingCommand cmd = new StartupRoutingCommand(0, 0, 0, 0, null, Hypervisor.HypervisorType.BareMetal,
new HashMap<String, String>(), null);
cmd.setDataCenter(_zone);
cmd.setPod(_pod);
cmd.setCluster(_cluster);
cmd.setGuid(_uuid);
cmd.setName(_ip);
cmd.setPrivateIpAddress(_ip);
cmd.setStorageIpAddress(_ip);
cmd.setVersion(BareMetalResourceBase.class.getPackage().getImplementationVersion());
cmd.setCpus((int)_cpuNum);
cmd.setSpeed(_cpuCapacity);
cmd.setMemory(_memCapacity);
cmd.setPrivateMacAddress(_mac);
cmd.setPublicMacAddress(_mac);
cmd.setStateChanges(fullSync());
return new StartupCommand[] {cmd};
}
private boolean ipmiPing() {
return doScript(_pingCommand);
}
@Override
public PingCommand getCurrentStatus(long id) {
try {
if (!ipmiPing()) {
Thread.sleep(1000);
if (!ipmiPing()) {
s_logger.warn("Cannot ping ipmi nic " + _ip);
return null;
}
}
} catch (Exception e) {
s_logger.debug("Cannot ping ipmi nic " + _ip, e);
return null;
}
return new PingRoutingCommand(getType(), id, deltaSync());
}
protected Answer execute(IpmISetBootDevCommand cmd) {
Script bootCmd = null;
if (cmd.getBootDev() == BootDev.disk) {
bootCmd = _setDiskBootCommand;
} else if (cmd.getBootDev() == BootDev.pxe) {
bootCmd = _setPxeBootCommand;
} else {
throw new CloudRuntimeException("Unkonwn boot dev " + cmd.getBootDev());
}
String bootDev = cmd.getBootDev().name();
if (!doScript(bootCmd)) {
s_logger.warn("Set " + _ip + " boot dev to " + bootDev + "failed");
return new Answer(cmd, false, "Set " + _ip + " boot dev to " + bootDev + "failed");
}
s_logger.warn("Set " + _ip + " boot dev to " + bootDev + "Success");
return new Answer(cmd, true, "Set " + _ip + " boot dev to " + bootDev + "Success");
}
protected MaintainAnswer execute(MaintainCommand cmd) {
return new MaintainAnswer(cmd, false);
}
protected PrepareForMigrationAnswer execute(PrepareForMigrationCommand cmd) {
return new PrepareForMigrationAnswer(cmd);
}
protected MigrateAnswer execute(MigrateCommand cmd) {
if (!doScript(_powerOffCommand)) {
return new MigrateAnswer(cmd, false, "IPMI power off failed", null);
}
return new MigrateAnswer(cmd, true, "success", null);
}
protected CheckVirtualMachineAnswer execute(final CheckVirtualMachineCommand cmd) {
return new CheckVirtualMachineAnswer(cmd, State.Stopped, null);
}
protected Answer execute(IpmiBootorResetCommand cmd) {
if (!doScript(_bootOrRebootCommand)) {
return new Answer(cmd ,false, "IPMI boot or reboot failed");
}
return new Answer(cmd, true, "Success");
}
protected CheckNetworkAnswer execute(CheckNetworkCommand cmd) {
return new CheckNetworkAnswer(cmd, true, "Success");
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof ReadyCommand) {
return execute((ReadyCommand)cmd);
} else if (cmd instanceof StartCommand) {
return execute((StartCommand)cmd);
} else if (cmd instanceof StopCommand) {
return execute((StopCommand)cmd);
} else if (cmd instanceof RebootCommand) {
return execute((RebootCommand)cmd);
} else if (cmd instanceof IpmISetBootDevCommand) {
return execute((IpmISetBootDevCommand)cmd);
} else if (cmd instanceof MaintainCommand) {
return execute((MaintainCommand)cmd);
} else if (cmd instanceof PrepareForMigrationCommand) {
return execute((PrepareForMigrationCommand)cmd);
} else if (cmd instanceof MigrateCommand) {
return execute((MigrateCommand)cmd);
} else if (cmd instanceof CheckVirtualMachineCommand) {
return execute((CheckVirtualMachineCommand)cmd);
} else if (cmd instanceof IpmiBootorResetCommand) {
return execute((IpmiBootorResetCommand)cmd);
} else if (cmd instanceof CheckNetworkCommand) {
return execute((CheckNetworkCommand)cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
}
protected boolean isPowerOn(String str) {
if (str.startsWith("Chassis Power is on")) {
return true;
} else if (str.startsWith("Chassis Power is off")) {
return false;
} else {
throw new CloudRuntimeException("Cannot parse IPMI power status " + str);
}
}
protected RebootAnswer execute(final RebootCommand cmd) {
if (!doScript(_rebootCommand)) {
return new RebootAnswer(cmd, "IPMI reboot failed", false);
}
return new RebootAnswer(cmd, "reboot succeeded", true);
}
protected StopAnswer execute(final StopCommand cmd) {
boolean success = false;
int count = 0;
Script powerOff = _powerOffCommand;
while (count < 10) {
if (!doScript(powerOff)) {
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
OutputInterpreter.AllLinesParser interpreter = new OutputInterpreter.AllLinesParser();
if (!doScript(_getStatusCommand, interpreter)) {
s_logger.warn("Cannot get power status of " + _name + ", assume VM state was not changed");
break;
}
if (!isPowerOn(interpreter.getLines())) {
success = true;
break;
} else {
powerOff = _forcePowerOffCommand;
}
count++;
}
return success ? new StopAnswer(cmd, "Success", null, true) : new StopAnswer(cmd, "IPMI power off failed", false);
}
protected StartAnswer execute(StartCommand cmd) {
VirtualMachineTO vm = cmd.getVirtualMachine();
State state = State.Stopped;
try {
changeVmState(vm.getName(), State.Starting);
boolean pxeBoot = false;
String[] bootArgs = vm.getBootArgs().split(" ");
for (int i = 0; i < bootArgs.length; i++) {
if (bootArgs[i].equalsIgnoreCase("PxeBoot")) {
pxeBoot = true;
break;
}
}
if (pxeBoot) {
if (!doScript(_setPxeBootCommand)) {
return new StartAnswer(cmd, "Set boot device to PXE failed");
}
s_logger.debug("Set " + vm.getHostName() + " to PXE boot successfully");
} else {
execute(new IpmISetBootDevCommand(BootDev.disk));
}
OutputInterpreter.AllLinesParser interpreter = new OutputInterpreter.AllLinesParser();
if (!doScript(_getStatusCommand, interpreter)) {
return new StartAnswer(cmd, "Cannot get current power status of " + _name);
}
if (isPowerOn(interpreter.getLines())) {
if (pxeBoot) {
if (!doScript(_rebootCommand)) {
return new StartAnswer(cmd, "IPMI reboot failed");
}
s_logger.debug("IPMI reboot " + vm.getHostName() + " successfully");
} else {
s_logger.warn("Machine " + _name + " is alreay power on, why we still get a Start command? ignore it");
}
} else {
if (!doScript(_powerOnCommand)) {
return new StartAnswer(cmd, "IPMI power on failed");
}
}
s_logger.debug("Start bare metal vm " + vm.getName() + "successfully");
state = State.Running;
_vmName = vm.getName();
return new StartAnswer(cmd);
} finally {
if (state != State.Stopped) {
changeVmState(vm.getName(), state);
} else {
removeVmState(vm.getName());
}
}
}
protected HashMap<String, State> deltaSync() {
final HashMap<String, State> changes = new HashMap<String, State>();
/*
* Disable sync until we find a way that only tracks status but not does action
*
* The scenario is: Baremetal will reboot host when creating template. Given most
* servers take a long time to boot up, there would be a period that mgmt server finds
* the host is stopped through fullsync. Then mgmt server updates database with marking the host as
* stopped, after that, the host comes up and full sync then indicates it's running. Because
* in database the host is already stopped, mgmt server sends out a stop command.
* As a result, creating image gets never happened.
*
if (_vmName == null) {
return null;
}
State newState = getVmState();
if (newState == null) {
s_logger.warn("Cannot get power state of VM " + _vmName);
return null;
}
final State oldState = removeVmState(_vmName);
if (oldState == null) {
changeVmState(_vmName, newState);
changes.put(_vmName, newState);
} else if (oldState == State.Starting) {
if (newState == State.Running) {
changeVmState(_vmName, newState);
} else if (newState == State.Stopped) {
s_logger.debug("Ignoring vm " + _vmName + " because of a lag in starting the vm.");
}
} else if (oldState == State.Migrating) {
s_logger.warn("How can baremetal VM get into migrating state???");
} else if (oldState == State.Stopping) {
if (newState == State.Stopped) {
changeVmState(_vmName, newState);
} else if (newState == State.Running) {
s_logger.debug("Ignoring vm " + _vmName + " because of a lag in stopping the vm. ");
}
} else if (oldState != newState) {
changeVmState(_vmName, newState);
changes.put(_vmName, newState);
}
*/
return changes;
}
protected ReadyAnswer execute(ReadyCommand cmd) {
// derived resource should check if the PXE server is ready
s_logger.debug("Bare metal resource " + _name + " is ready");
return new ReadyAnswer(cmd);
}
@Override
public void disconnected() {
}
@Override
public IAgentControl getAgentControl() {
return _agentControl;
}
@Override
public void setAgentControl(IAgentControl agentControl) {
_agentControl = agentControl;
}
@Override
public void setName(String name) {
// TODO Auto-generated method stub
}
@Override
public void setConfigParams(Map<String, Object> params) {
// TODO Auto-generated method stub
}
@Override
public Map<String, Object> getConfigParams() {
// TODO Auto-generated method stub
return null;
}
@Override
public int getRunLevel() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void setRunLevel(int level) {
// TODO Auto-generated method stub
}
}

View File

@ -1,22 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
import com.cloud.vm.UserVmManager;
public interface BareMetalVmManager extends UserVmManager {
}

View File

@ -1,35 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
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 DhcpServerResponse extends BaseResponse {
@SerializedName(ApiConstants.ID) @Param(description="the ID of the Dhcp server")
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}

View File

@ -1,133 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
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 DhcpdResource extends ExternalDhcpResourceBase {
private static final Logger s_logger = Logger.getLogger(DhcpdResource.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);
}
}
}

View File

@ -1,123 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
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 DnsmasqResource extends ExternalDhcpResourceBase {
private static final Logger s_logger = Logger.getLogger(DnsmasqResource.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);
}
}
}

View File

@ -1,44 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
public interface ExternalDhcpEntryListener {
public class DhcpEntryState {
String _name;
public static final DhcpEntryState add = new DhcpEntryState("add");
public static final DhcpEntryState old = new DhcpEntryState("old");
public static final DhcpEntryState del = new DhcpEntryState("del");
public DhcpEntryState(String name) {
_name = name;
}
public String getName() {
return _name;
}
}
/**
* Notify that DHCP entry state change
* @param ip
* @param mac
* @param DHCP entry state
* @return: true means continuous listen on the entry, false cancels the listener
*/
public boolean notify(String ip, String mac, DhcpEntryState state, Object userData);
}

View File

@ -1,54 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
import com.cloud.baremetal.ExternalDhcpEntryListener.DhcpEntryState;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.Host;
import com.cloud.network.Network;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Manager;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
public interface ExternalDhcpManager extends Manager {
public static class DhcpServerType {
private String _name;
public static final DhcpServerType Dnsmasq = new DhcpServerType("Dnsmasq");
public static final DhcpServerType Dhcpd = new DhcpServerType("Dhcpd");
public DhcpServerType(String name) {
_name = name;
}
public String getName() {
return _name;
}
}
DhcpServerResponse getApiResponse(Host dhcpServer);
boolean addVirtualMachineIntoNetwork(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException;
Host addDhcpServer(Long zoneId, Long podId, String type, String url, String username, String password);
}

View File

@ -1,250 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
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.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.InvalidParameterValueException;
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.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
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.ManagerBase;
import com.cloud.utils.db.DB;
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.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
@Component
@Local(value = {ExternalDhcpManager.class})
public class ExternalDhcpManagerImpl extends ManagerBase implements ExternalDhcpManager, ResourceStateAdapter {
private static final org.apache.log4j.Logger s_logger = Logger.getLogger(ExternalDhcpManagerImpl.class);
@Inject DataCenterDao _dcDao;
@Inject HostDao _hostDao;
@Inject AgentManager _agentMgr;
@Inject HostPodDao _podDao;
@Inject UserVmDao _userVmDao;
@Inject ResourceManager _resourceMgr;
@Inject NicDao _nicDao;
@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;
}
protected String getDhcpServerGuid(String zoneId, String name, String ip) {
return zoneId + "-" + name + "-" + ip;
}
@Override @DB
public Host addDhcpServer(Long zoneId, Long podId, String type, String url, String username, String password) {
DataCenterVO zone = _dcDao.findById(zoneId);
if (zone == null) {
throw new InvalidParameterValueException("Could not find zone with ID: " + zoneId);
}
HostPodVO pod = _podDao.findById(podId);
if (pod == null) {
throw new InvalidParameterValueException("Could not find pod with ID: " + podId);
}
List<HostVO> dhcps = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.ExternalDhcp, null, podId, zoneId);
if (dhcps.size() != 0) {
throw new InvalidParameterValueException("Already had a DHCP server in Pod: " + podId + " zone: " + zoneId);
}
String ipAddress = url;
String guid = getDhcpServerGuid(Long.toString(zoneId) + "-" + Long.toString(podId), "ExternalDhcp", ipAddress);
Map params = new HashMap<String, String>();
params.put("type", type);
params.put("zone", Long.toString(zoneId));
params.put("pod", podId.toString());
params.put("ip", ipAddress);
params.put("username", username);
params.put("password", password);
params.put("guid", guid);
params.put("pod", Long.toString(podId));
params.put("gateway", pod.getGateway());
String dns = zone.getDns1();
if (dns == null) {
dns = zone.getDns2();
}
params.put("dns", dns);
ServerResource resource = null;
try {
if (type.equalsIgnoreCase(DhcpServerType.Dnsmasq.getName())) {
resource = new DnsmasqResource();
resource.configure("Dnsmasq resource", params);
} else if (type.equalsIgnoreCase(DhcpServerType.Dhcpd.getName())) {
resource = new DhcpdResource();
resource.configure("Dhcpd resource", params);
} else {
throw new CloudRuntimeException("Unsupport DHCP server " + type);
}
} catch (Exception e) {
s_logger.debug(e);
throw new CloudRuntimeException(e.getMessage());
}
Host dhcpServer = _resourceMgr.addHost(zoneId, resource, Host.Type.ExternalDhcp, params);
if (dhcpServer == null) {
throw new CloudRuntimeException("Cannot add external Dhcp server as a host");
}
Transaction txn = Transaction.currentTxn();
txn.start();
pod.setExternalDhcp(true);
_podDao.update(pod.getId(), pod);
txn.commit();
return dhcpServer;
}
@Override
public DhcpServerResponse getApiResponse(Host dhcpServer) {
DhcpServerResponse response = new DhcpServerResponse();
response.setId(dhcpServer.getUuid());
return response;
}
private void prepareBareMetalDhcpEntry(NicProfile nic, DhcpEntryCommand cmd) {
Long vmId = nic.getVmId();
UserVmVO vm = _userVmDao.findById(vmId);
if (vm == null || vm.getHypervisorType() != HypervisorType.BareMetal) {
s_logger.debug("VM " + vmId + " is not baremetal machine, skip preparing baremetal DHCP entry");
return;
}
List<HostVO> servers = _resourceMgr.listAllUpAndEnabledHosts(Host.Type.PxeServer, null, vm.getPodIdToDeployIn(), vm.getDataCenterId());
if (servers.size() != 1) {
throw new CloudRuntimeException("Wrong number of PXE server found in zone " + vm.getDataCenterId()
+ " Pod " + vm.getPodIdToDeployIn() + ", number is " + servers.size());
}
HostVO pxeServer = servers.get(0);
cmd.setNextServer(pxeServer.getPrivateIpAddress());
s_logger.debug("Set next-server to " + pxeServer.getPrivateIpAddress() + " for VM " + vm.getId());
}
@Override
public boolean addVirtualMachineIntoNetwork(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> profile, DeployDestination dest,
ReservationContext context) throws ResourceUnavailableException {
Long zoneId = profile.getVirtualMachine().getDataCenterId();
Long podId = profile.getVirtualMachine().getPodIdToDeployIn();
List<HostVO> hosts = _resourceMgr.listAllUpAndEnabledHosts(Type.ExternalDhcp, 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(), null, dns, nic.getGateway(), null);
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.ExternalDhcp);
return host;
}
@Override
public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -1,198 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
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 ExternalDhcpResourceBase implements ServerResource {
private static final Logger s_logger = Logger.getLogger(ExternalDhcpResourceBase.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.ExternalDhcp;
}
@Override
public StartupCommand[] initialize() {
StartupExternalDhcpCommand cmd = new StartupExternalDhcpCommand();
cmd.setName(_name);
cmd.setDataCenter(_zoneId);
cmd.setPod(_podId);
cmd.setPrivateIpAddress(_ip);
cmd.setStorageIpAddress("");
cmd.setVersion(ExternalDhcpResourceBase.class.getPackage().getImplementationVersion());
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) {
}
@Override
public void setName(String name) {
// TODO Auto-generated method stub
}
@Override
public void setConfigParams(Map<String, Object> params) {
// TODO Auto-generated method stub
}
@Override
public Map<String, Object> getConfigParams() {
// TODO Auto-generated method stub
return null;
}
@Override
public int getRunLevel() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void setRunLevel(int level) {
// TODO Auto-generated method stub
}
}

View File

@ -1,28 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
import com.cloud.utils.SerialVersionUID;
import com.cloud.exception.CloudException;
public class HttpCallException extends CloudException {
private static final long serialVersionUID= SerialVersionUID.HttpCallException;
public HttpCallException(String msg) {
super(msg);
}
}

View File

@ -1,196 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
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.baremetal.PreparePxeServerAnswer;
import com.cloud.agent.api.baremetal.PreparePxeServerCommand;
import com.cloud.agent.api.baremetal.prepareCreateTemplateCommand;
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 PingPxeServerResource extends PxeServerResourceBase {
private static final Logger s_logger = Logger.getLogger(PingPxeServerResource.class);
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("storageServer");
_pingDir = (String)params.get("pingDir");
_tftpDir = (String)params.get("tftpDir");
_cifsUserName = (String)params.get("cifsUserName");
_cifsPassword = (String)params.get("cifsPassword");
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");
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());
s_logger.debug("Prepare Ping PXE server successfully");
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
return new PreparePxeServerAnswer(cmd, "prepare PING at " + _ip + " failed, command:" + script);
}
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());
s_logger.debug("Prepare for creating template successfully");
if (!SSHCmdHelper.sshExecuteCmd(sshConnection, script)) {
return new Answer(cmd, false, "prepare for creating template failed, 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 PreparePxeServerCommand) {
return execute((PreparePxeServerCommand) cmd);
} else if (cmd instanceof prepareCreateTemplateCommand) {
return execute((prepareCreateTemplateCommand)cmd);
} else {
return super.executeRequest(cmd);
}
}
}

View File

@ -1,54 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Manager;
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 PING = new PxeServerType("PING");
public static final PxeServerType DMCD = new PxeServerType("DMCD");
public PxeServerType(String name) {
_name = name;
}
public String getName() {
return _name;
}
}
public PxeServerResponse getApiResponse(Host pxeServer);
public boolean prepare(PxeServerType type, VirtualMachineProfile<UserVmVO> profile, DeployDestination dest, ReservationContext context, Long pxeServerId);
Host addPxeServer(PxeServerProfile profile);
public boolean prepareCreateTemplate(PxeServerType type, Long pxeServerId, UserVm vm, String templateUrl);
public PxeServerType getPxeServerType(HostVO host);
}

View File

@ -1,145 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.agent.AgentManager;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupPxeServerCommand;
import com.cloud.baremetal.PxeServerManager.PxeServerType;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.resource.ResourceManager;
import com.cloud.resource.ResourceStateAdapter;
import com.cloud.resource.ServerResource;
import com.cloud.resource.UnableDeleteHostException;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.VirtualMachineProfile.Param;
@Component
@Local(value = {PxeServerManager.class})
public class PxeServerManagerImpl extends ManagerBase implements PxeServerManager, ResourceStateAdapter {
private static final org.apache.log4j.Logger s_logger = Logger.getLogger(PxeServerManagerImpl.class);
@Inject DataCenterDao _dcDao;
@Inject HostDao _hostDao;
@Inject AgentManager _agentMgr;
@Inject ExternalDhcpManager exDhcpMgr;
@Inject ResourceManager _resourceMgr;
// @com.cloud.utils.component.Inject(adapter=PxeServerService.class)
@Inject protected List<PxeServerService> _services;
@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;
}
protected PxeServerService getServiceByType(String type) {
PxeServerService _service;
_service = AdapterBase.getAdapterByName(_services, type);
if (_service == null) {
throw new CloudRuntimeException("Cannot find PXE service for " + type);
}
return _service;
}
@Override
public Host addPxeServer(PxeServerProfile profile) {
return getServiceByType(profile.getType()).addPxeServer(profile);
}
@Override
public PxeServerResponse getApiResponse(Host pxeServer) {
PxeServerResponse response = new PxeServerResponse();
response.setId(pxeServer.getUuid());
return response;
}
@Override
public boolean prepare(PxeServerType type, VirtualMachineProfile<UserVmVO> profile, DeployDestination dest, ReservationContext context, Long pxeServerId) {
return getServiceByType(type.getName()).prepare(profile, dest, context, pxeServerId);
}
@Override
public boolean prepareCreateTemplate(PxeServerType type, Long pxeServerId, UserVm vm, String templateUrl) {
return getServiceByType(type.getName()).prepareCreateTemplate(pxeServerId, vm, templateUrl);
}
@Override
public PxeServerType getPxeServerType(HostVO host) {
if (host.getResource().equalsIgnoreCase(PingPxeServerResource.class.getName())) {
return PxeServerType.PING;
} else {
throw new CloudRuntimeException("Unkown PXE server resource " + host.getResource());
}
}
@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 StartupPxeServerCommand)) {
return null;
}
host.setType(Host.Type.PxeServer);
return host;
}
@Override
public DeleteHostAnswer deleteHost(HostVO host, boolean isForced, boolean isForceDeleteStorage) throws UnableDeleteHostException {
// TODO Auto-generated method stub
return null;
}
}

View File

@ -1,90 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
public class PxeServerProfile {
Long zoneId;
Long podId;
String url;
String username;
String password;
String type;
String pingStorageServerIp;
String pingDir;
String tftpDir;
String pingCifsUserName;
String pingCifspassword;
public PxeServerProfile (Long zoneId, Long podId, String url, String username, String password, String type,
String pingStorageServerIp, String pingDir, String tftpDir, String pingCifsUserName, String pingCifsPassword) {
this.zoneId = zoneId;
this.podId = podId;
this.url = url;
this.username = username;
this.password = password;
this.type = type;
this.pingStorageServerIp = pingStorageServerIp;
this.pingDir = pingDir;
this.tftpDir = tftpDir;
this.pingCifsUserName = pingCifsUserName;
this.pingCifspassword = pingCifsPassword;
}
public Long getZoneId() {
return zoneId;
}
public Long getPodId() {
return podId;
}
public String getUrl() {
return url;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public String getType() {
return type;
}
public String getPingStorageServerIp() {
return pingStorageServerIp;
}
public String getPingDir() {
return pingDir;
}
public String getTftpDir() {
return tftpDir;
}
public String getPingCifsUserName() {
return pingCifsUserName;
}
public String getPingCifspassword() {
return pingCifspassword;
}
}

View File

@ -1,185 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
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.ReadyAnswer;
import com.cloud.agent.api.ReadyCommand;
import com.cloud.agent.api.StartupCommand;
import com.cloud.agent.api.StartupPxeServerCommand;
import com.cloud.host.Host.Type;
import com.cloud.resource.ServerResource;
public class PxeServerResourceBase implements ServerResource {
private static final Logger s_logger = Logger.getLogger(PxeServerResourceBase.class);
String _name;
String _guid;
String _username;
String _password;
String _ip;
String _zoneId;
String _podId;
@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");
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");
}
return true;
}
protected ReadyAnswer execute(ReadyCommand cmd) {
s_logger.debug("Pxe resource " + _name + " is ready");
return new ReadyAnswer(cmd);
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
@Override
public String getName() {
// TODO Auto-generated method stub
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(_podId);
cmd.setPrivateIpAddress(_ip);
cmd.setStorageIpAddress("");
cmd.setVersion(PxeServerResourceBase.class.getPackage().getImplementationVersion());
cmd.setGuid(_guid);
return new StartupCommand[]{cmd};
}
@Override
public PingCommand getCurrentStatus(long id) {
// TODO Auto-generated method stub
return null;
}
@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
}
@Override
public Answer executeRequest(Command cmd) {
if (cmd instanceof ReadyCommand) {
return execute((ReadyCommand) cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
}
@Override
public void setName(String name) {
// TODO Auto-generated method stub
}
@Override
public void setConfigParams(Map<String, Object> params) {
// TODO Auto-generated method stub
}
@Override
public Map<String, Object> getConfigParams() {
// TODO Auto-generated method stub
return null;
}
@Override
public int getRunLevel() {
// TODO Auto-generated method stub
return 0;
}
@Override
public void setRunLevel(int level) {
// TODO Auto-generated method stub
}
}

View File

@ -1,35 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
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 PxeServerResponse extends BaseResponse {
@SerializedName(ApiConstants.ID) @Param(description="the ID of the PXE server")
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}

View File

@ -1,35 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.baremetal;
import com.cloud.baremetal.PxeServerManager.PxeServerType;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.Host;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Adapter;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachineProfile;
public interface PxeServerService extends Adapter {
public Host addPxeServer(PxeServerProfile profile);
public boolean prepare(VirtualMachineProfile<UserVmVO> profile, DeployDestination dest, ReservationContext context, Long pxeServerId);
public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl);
}

View File

@ -0,0 +1,58 @@
package com.cloud.deploy;
import java.util.Map;
import javax.naming.ConfigurationException;
import com.cloud.vm.UserVmVO;
public abstract class AbstractDeployPlannerSelector implements DeployPlannerSelector {
protected Map<String, Object> params;
protected String name;
protected int runLevel;
@Override
public String getName() {
return name;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public void setConfigParams(Map<String, Object> params) {
this.params = params;
}
@Override
public Map<String, Object> getConfigParams() {
return params;
}
@Override
public int getRunLevel() {
return runLevel;
}
@Override
public void setRunLevel(int level) {
this.runLevel = level;
}
@Override
public boolean configure(String name, Map<String, Object> params) throws ConfigurationException {
return true;
}
@Override
public boolean start() {
return true;
}
@Override
public boolean stop() {
return true;
}
}

View File

@ -0,0 +1,8 @@
package com.cloud.deploy;
import com.cloud.utils.component.Adapter;
import com.cloud.vm.UserVmVO;
public interface DeployPlannerSelector extends Adapter {
String selectPlanner(UserVmVO vm);
}

View File

@ -0,0 +1,17 @@
package com.cloud.deploy;
import javax.ejb.Local;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.vm.UserVmVO;
@Local(value = {DeployPlannerSelector.class})
public class HypervisorVmPlannerSelector extends AbstractDeployPlannerSelector {
@Override
public String selectPlanner(UserVmVO vm) {
if (vm.getHypervisorType() != HypervisorType.BareMetal) {
return "FirstFitPlanner";
}
return null;
}
}

View File

@ -491,7 +491,7 @@ public class HostDaoImpl extends GenericDaoBase<HostVO, Long> implements HostDao
txn.start();
SearchCriteria<HostVO> sc = UnmanagedApplianceSearch.create();
sc.setParameters("lastPinged", lastPingSecondsAfter);
sc.setParameters("types", Type.ExternalDhcp, Type.ExternalFirewall, Type.ExternalLoadBalancer, Type.PxeServer, Type.TrafficMonitor, Type.L2Networking);
sc.setParameters("types", Type.ExternalDhcp, Type.ExternalFirewall, Type.ExternalLoadBalancer, Type.BaremetalDhcp, Type.BaremetalPxe, Type.TrafficMonitor, Type.L2Networking);
List<HostVO> hosts = lockRows(sc, null, true);
for (HostVO host : hosts) {

View File

@ -25,7 +25,6 @@ import java.util.concurrent.ScheduledExecutorService;
import javax.ejb.Local;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.command.admin.network.AddNetworkDeviceCmd;
@ -37,14 +36,7 @@ import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import com.cloud.agent.AgentManager;
import com.cloud.api.ApiDBUtils;
import com.cloud.baremetal.ExternalDhcpManager;
import com.cloud.baremetal.PxeServerManager;
import com.cloud.baremetal.PxeServerManager.PxeServerType;
import com.cloud.baremetal.PxeServerProfile;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.DataCenter;
import com.cloud.dc.Pod;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.VlanDao;
import com.cloud.host.Host;
@ -63,8 +55,6 @@ import com.cloud.network.dao.PhysicalNetworkServiceProviderDao;
import com.cloud.network.dao.VpnUserDao;
import com.cloud.network.rules.dao.PortForwardingRulesDao;
import com.cloud.offerings.dao.NetworkOfferingDao;
import com.cloud.server.api.response.NwDeviceDhcpResponse;
import com.cloud.server.api.response.PxePingResponse;
import com.cloud.user.AccountManager;
import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserStatisticsDao;
@ -77,8 +67,6 @@ import com.cloud.vm.dao.NicDao;
@Local(value = {ExternalNetworkDeviceManager.class})
public class ExternalNetworkDeviceManagerImpl extends ManagerBase implements ExternalNetworkDeviceManager {
@Inject ExternalDhcpManager _dhcpMgr;
@Inject PxeServerManager _pxeMgr;
@Inject AgentManager _agentMgr;
@Inject NetworkModel _networkMgr;
@Inject HostDao _hostDao;
@ -121,80 +109,12 @@ public class ExternalNetworkDeviceManagerImpl extends ManagerBase implements Ext
Collection paramsCollection = paramList.values();
HashMap params = (HashMap) (paramsCollection.toArray())[0];
if (cmd.getDeviceType().equalsIgnoreCase(NetworkDevice.ExternalDhcp.getName())) {
//Long zoneId = _identityService.getIdentityId("data_center", (String) params.get(ApiConstants.ZONE_ID));
//Long podId = _identityService.getIdentityId("host_pod_ref", (String)params.get(ApiConstants.POD_ID));
Long zoneId = Long.valueOf((String) params.get(ApiConstants.ZONE_ID));
Long podId = Long.valueOf((String)params.get(ApiConstants.POD_ID));
String type = (String) params.get(ApiConstants.DHCP_SERVER_TYPE);
String url = (String) params.get(ApiConstants.URL);
String username = (String) params.get(ApiConstants.USERNAME);
String password = (String) params.get(ApiConstants.PASSWORD);
return _dhcpMgr.addDhcpServer(zoneId, podId, type, url, username, password);
} else if (cmd.getDeviceType().equalsIgnoreCase(NetworkDevice.PxeServer.getName())) {
Long zoneId = Long.parseLong((String) params.get(ApiConstants.ZONE_ID));
Long podId = Long.parseLong((String)params.get(ApiConstants.POD_ID));
//Long zoneId = _identityService.getIdentityId("data_center", (String) params.get(ApiConstants.ZONE_ID));
//Long podId = _identityService.getIdentityId("host_pod_ref", (String)params.get(ApiConstants.POD_ID));
String type = (String) params.get(ApiConstants.PXE_SERVER_TYPE);
String url = (String) params.get(ApiConstants.URL);
String username = (String) params.get(ApiConstants.USERNAME);
String password = (String) params.get(ApiConstants.PASSWORD);
String pingStorageServerIp = (String) params.get(ApiConstants.PING_STORAGE_SERVER_IP);
String pingDir = (String) params.get(ApiConstants.PING_DIR);
String tftpDir = (String) params.get(ApiConstants.TFTP_DIR);
String pingCifsUsername = (String) params.get(ApiConstants.PING_CIFS_USERNAME);
String pingCifsPassword = (String) params.get(ApiConstants.PING_CIFS_PASSWORD);
PxeServerProfile profile = new PxeServerProfile(zoneId, podId, url, username, password, type, pingStorageServerIp, pingDir, tftpDir,
pingCifsUsername, pingCifsPassword);
return _pxeMgr.addPxeServer(profile);
} else {
throw new CloudRuntimeException("Unsupported network device type:" + cmd.getDeviceType());
}
return null;
}
@Override
public NetworkDeviceResponse getApiResponse(Host device) {
NetworkDeviceResponse response;
HostVO host = (HostVO)device;
_hostDao.loadDetails(host);
if (host.getType() == Host.Type.ExternalDhcp) {
NwDeviceDhcpResponse r = new NwDeviceDhcpResponse();
r.setZoneId(host.getDataCenterId());
r.setPodId(host.getPodId());
r.setUrl(host.getPrivateIpAddress());
r.setType(host.getDetail("type"));
response = r;
} else if (host.getType() == Host.Type.PxeServer) {
String pxeType = host.getDetail("type");
if (pxeType.equalsIgnoreCase(PxeServerType.PING.getName())) {
PxePingResponse r = new PxePingResponse();
DataCenter zone = ApiDBUtils.findZoneById(host.getDataCenterId());
if (zone != null) {
r.setZoneId(zone.getUuid());
}
if (host.getPodId() != null) {
Pod pod = ApiDBUtils.findPodById(host.getPodId());
if (pod != null) {
r.setPodId(pod.getUuid());
}
}
r.setUrl(host.getPrivateIpAddress());
r.setType(pxeType);
r.setStorageServerIp(host.getDetail("storageServer"));
r.setPingDir(host.getDetail("pingDir"));
r.setTftpDir(host.getDetail("tftpDir"));
response = r;
} else {
throw new CloudRuntimeException("Unsupported PXE server type:" + pxeType);
}
} else {
throw new CloudRuntimeException("Unsupported network device type:" + host.getType());
}
response.setId(device.getUuid());
return response;
return null;
}
private List<Host> listNetworkDevice(Long zoneId, Long physicalNetworkId, Long podId, Host.Type type) {

View File

@ -1517,7 +1517,7 @@ public class NetworkManagerImpl extends ManagerBase implements NetworkManager, L
DeployDestination dest, ReservationContext context) throws InsufficientCapacityException,
ConcurrentOperationException, ResourceUnavailableException {
element.prepare(network, profile, vmProfile, dest, context);
if (vmProfile.getType() == Type.User && vmProfile.getHypervisorType() != HypervisorType.BareMetal && element.getProvider() != null) {
if (vmProfile.getType() == Type.User && element.getProvider() != null) {
if (_networkModel.areServicesSupportedInNetwork(network.getId(), Service.Dhcp) &&
_networkModel.isProviderSupportServiceInNetwork(network.getId(), Service.Dhcp, element.getProvider()) &&
(element instanceof DhcpServiceProvider)) {

View File

@ -1,128 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.network.element;
import java.util.Map;
import java.util.Set;
import javax.ejb.Local;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import com.cloud.baremetal.ExternalDhcpManager;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.host.Host;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
import com.cloud.network.Network.Service;
import com.cloud.network.PhysicalNetworkServiceProvider;
import com.cloud.offering.NetworkOffering;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.Transaction;
import com.cloud.vm.NicProfile;
import com.cloud.vm.NicVO;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.NicDao;
@Local(value=NetworkElement.class)
public class BareMetalElement extends AdapterBase implements NetworkElement {
private static final Logger s_logger = Logger.getLogger(BareMetalElement.class);
@Inject NicDao _nicDao;
@Inject ExternalDhcpManager _dhcpMgr;
@Override
public Map<Service, Map<Capability, String>> getCapabilities() {
return null;
}
@Override
public Provider getProvider() {
return null;
}
@Override
public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
return true;
}
@Override @DB
public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
Host host = dest.getHost();
if (host == null || host.getHypervisorType() != HypervisorType.BareMetal) {
return true;
}
Transaction txn = Transaction.currentTxn();
txn.start();
nic.setMacAddress(host.getPrivateMacAddress());
NicVO vo = _nicDao.findById(nic.getId());
assert vo != null : "Where ths nic " + nic.getId() + " going???";
vo.setMacAddress(nic.getMacAddress());
_nicDao.update(vo.getId(), vo);
txn.commit();
s_logger.debug("Bare Metal changes mac address of nic " + nic.getId() + " to " + nic.getMacAddress());
return _dhcpMgr.addVirtualMachineIntoNetwork(network, nic, vm, dest, context);
}
@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 destroy(Network network, ReservationContext context) 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 verifyServicesCombination(Set<Service> services) {
return true;
}
}

View File

@ -1,152 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package com.cloud.network.element;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.ejb.Local;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import com.cloud.baremetal.ExternalDhcpManager;
import com.cloud.dc.DataCenter;
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.host.Host;
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.offering.NetworkOffering;
import com.cloud.utils.component.AdapterBase;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
@Local(value = NetworkElement.class)
public class ExternalDhcpElement extends AdapterBase implements NetworkElement, DhcpServiceProvider {
private static final Logger s_logger = Logger.getLogger(ExternalDhcpElement.class);
@Inject
ExternalDhcpManager _dhcpMgr;
private static final Map<Service, Map<Capability, String>> capabilities = setCapabilities();
private boolean canHandle(DeployDestination dest, TrafficType trafficType, GuestType networkType) {
DataCenter dc = dest.getDataCenter();
Pod pod = dest.getPod();
if ((pod != null && pod.getExternalDhcp()) && dc.getNetworkType() == NetworkType.Basic && trafficType == TrafficType.Guest
&& networkType == Network.GuestType.Shared) {
s_logger.debug("External DHCP can handle");
return true;
}
return false;
}
private static Map<Service, Map<Capability, String>> setCapabilities() {
// No external dhcp support for Acton release
Map<Service, Map<Capability, String>> capabilities = new HashMap<Service, Map<Capability, String>>();
//capabilities.put(Service.Dhcp, null);
return capabilities;
}
@Override
public Map<Service, Map<Capability, String>> getCapabilities() {
return capabilities;
}
@Override
public Provider getProvider() {
return Provider.ExternalDhcpServer;
}
@Override
public boolean implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
if (!canHandle(dest, offering.getTrafficType(), network.getGuestType())) {
return false;
}
return true;
}
@Override
public boolean prepare(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest,
ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException, InsufficientCapacityException {
return true;
}
@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 destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
return true;
}
@Override
public boolean isReady(PhysicalNetworkServiceProvider provider) {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean shutdownProviderInstances(PhysicalNetworkServiceProvider provider, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean canEnableIndividualServices() {
return false;
}
@Override
public boolean addDhcpEntry(Network network, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, InsufficientCapacityException, ResourceUnavailableException {
Host host = dest.getHost();
if (host.getHypervisorType() == HypervisorType.BareMetal || !canHandle(dest, network.getTrafficType(), network.getGuestType())) {
// BareMetalElement or DhcpElement handle this
return false;
}
return _dhcpMgr.addVirtualMachineIntoNetwork(network, nic, vm, dest, context);
}
@Override
public boolean verifyServicesCombination(Set<Service> services) {
return true;
}
}

32
server/src/com/cloud/vm/UserVmManagerImpl.java Normal file → Executable file
View File

@ -89,6 +89,7 @@ import com.cloud.dc.dao.DataCenterDao;
import com.cloud.dc.dao.HostPodDao;
import com.cloud.deploy.DataCenterDeployment;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeployPlannerSelector;
import com.cloud.deploy.DeploymentPlanner.ExcludeList;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
@ -397,6 +398,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
@Inject
protected VMSnapshotManager _vmSnapshotMgr;
@Inject
List<DeployPlannerSelector> plannerSelectors;
protected ScheduledExecutorService _executor = null;
protected int _expungeInterval;
protected int _expungeDelay;
@ -2167,14 +2171,13 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
}
}
}
// check if we have available pools for vm deployment
long availablePools = _storagePoolDao
.countPoolsByStatus(StoragePoolStatus.Up);
if (availablePools < 1) {
throw new StorageUnavailableException(
"There are no available pools in the UP state for vm deployment",
-1);
if (template.getHypervisorType() != null && template.getHypervisorType() != HypervisorType.BareMetal) {
// check if we have available pools for vm deployment
long availablePools = _storagePoolDao.countPoolsByStatus(StoragePoolStatus.Up);
if (availablePools < 1) {
throw new StorageUnavailableException("There are no available pools in the UP state for vm deployment", -1);
}
}
if (template.getTemplateType().equals(TemplateType.SYSTEM)) {
@ -2860,8 +2863,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Use
}
VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid());
String plannerName = null;
for (DeployPlannerSelector dps : plannerSelectors) {
plannerName = dps.selectPlanner(vm);
if (plannerName != null) {
break;
}
}
if (plannerName == null) {
throw new CloudRuntimeException(String.format("cannot find DeployPlannerSelector for vm[uuid:%s, hypervisorType:%s]", vm.getUuid(), vm.getHypervisorType()));
}
String reservationId = vmEntity.reserve("FirstFitPlanner", plan, new ExcludeList(), new Long(callerUser.getId()).toString());
String reservationId = vmEntity.reserve(plannerName, plan, new ExcludeList(), new Long(callerUser.getId()).toString());
vmEntity.deploy(reservationId, new Long(callerUser.getId()).toString());
Pair<UserVmVO, Map<VirtualMachineProfile.Param, Object>> vmParamPair = new Pair(vm, params);

View File

@ -343,11 +343,6 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
return (VirtualMachineGuru<T>) _vmGurus.get(vm.getType());
}
@SuppressWarnings("unchecked")
private <T extends VMInstanceVO> VirtualMachineGuru<T> getBareMetalVmGuru(T vm) {
return (VirtualMachineGuru<T>) _vmGurus.get(VirtualMachine.Type.UserBareMetal);
}
@Override
public <T extends VMInstanceVO> boolean expunge(T vm, User caller, Account account) throws ResourceUnavailableException {
try {
@ -593,12 +588,7 @@ public class VirtualMachineManagerImpl extends ManagerBase implements VirtualMac
public <T extends VMInstanceVO> T advanceStart(T vm, Map<VirtualMachineProfile.Param, Object> params, User caller, Account account, DeploymentPlan planToDeploy)
throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException {
long vmId = vm.getId();
VirtualMachineGuru<T> vmGuru;
if (vm.getHypervisorType() == HypervisorType.BareMetal) {
vmGuru = getBareMetalVmGuru(vm);
} else {
vmGuru = getVmGuru(vm);
}
VirtualMachineGuru<T> vmGuru = getVmGuru(vm);
vm = vmGuru.findById(vm.getId());
Ternary<T, ReservationContext, ItWorkVO> start = changeToStartState(vmGuru, vm, caller, account);

View File

@ -1631,3 +1631,31 @@ CREATE VIEW `cloud`.`data_center_view` AS
left join
`cloud`.`domain` ON data_center.domain_id = domain.id;
INSERT INTO `cloud`.`region` values ('1','Local','http://localhost:8080/client/api','','');
ALTER TABLE `cloud`.`account` ADD COLUMN `region_id` int unsigned NOT NULL DEFAULT '1';
ALTER TABLE `cloud`.`user` ADD COLUMN `region_id` int unsigned NOT NULL DEFAULT '1';
ALTER TABLE `cloud`.`domain` ADD COLUMN `region_id` int unsigned NOT NULL DEFAULT '1';
ALTER TABLE `cloud_usage`.`account` ADD COLUMN `region_id` int unsigned NOT NULL DEFAULT '1';
CREATE TABLE `cloud`.`baremetal_dhcp_devices` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`uuid` varchar(40) UNIQUE,
`nsp_id` bigint unsigned DEFAULT NULL COMMENT 'Network Service Provider ID',
`pod_id` bigint unsigned DEFAULT NULL COMMENT 'Pod id where this dhcp server in',
`device_type` varchar(255) DEFAULT NULL COMMENT 'type of the external device',
`physical_network_id` bigint unsigned DEFAULT NULL COMMENT 'id of the physical network in to which external dhcp device is added',
`host_id` bigint unsigned DEFAULT NULL COMMENT 'host id coresponding to the external dhcp device',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`baremetal_pxe_devices` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
`uuid` varchar(40) UNIQUE,
`nsp_id` bigint unsigned DEFAULT NULL COMMENT 'Network Service Provider ID',
`pod_id` bigint unsigned DEFAULT NULL COMMENT 'Pod id where this pxe server in, for pxe per zone this field is null',
`device_type` varchar(255) DEFAULT NULL COMMENT 'type of the pxe device',
`physical_network_id` bigint unsigned DEFAULT NULL COMMENT 'id of the physical network in to which external pxe device is added',
`host_id` bigint unsigned DEFAULT NULL COMMENT 'host id coresponding to the external pxe device',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;