diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalPingServiceImpl.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalPingServiceImpl.java index 66bbb618e20..70b9b586844 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalPingServiceImpl.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BareMetalPingServiceImpl.java @@ -30,6 +30,7 @@ import java.util.Map; import javax.ejb.Local; import javax.inject.Inject; +import com.cloud.network.Network; import org.apache.log4j.Logger; import org.apache.cloudstack.api.AddBaremetalPxeCmd; @@ -83,7 +84,7 @@ public class BareMetalPingServiceImpl extends BareMetalPxeServiceBase implements BaremetalPxeDao _pxeDao; @Override - public boolean prepare(VirtualMachineProfile profile, NicProfile pxeNic, DeployDestination dest, ReservationContext context) { + public boolean prepare(VirtualMachineProfile profile, NicProfile pxeNic, Network network, DeployDestination dest, ReservationContext context) { QueryBuilder sc = QueryBuilder.create(BaremetalPxeVO.class); sc.and(sc.entity().getDeviceType(), Op.EQ, BaremetalPxeType.PING.toString()); sc.and(sc.entity().getPodId(), Op.EQ, dest.getPod().getId()); diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java index 62b312398f3..cc9fce7c948 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalKickStartServiceImpl.java @@ -20,6 +20,7 @@ package com.cloud.baremetal.networkservice; import java.net.URI; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -27,6 +28,18 @@ import java.util.Map; import javax.ejb.Local; import javax.inject.Inject; +import com.cloud.dc.DataCenter; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.OperationTimedoutException; +import com.cloud.hypervisor.Hypervisor; +import com.cloud.network.Network; +import com.cloud.network.guru.ControlNetworkGuru; +import com.cloud.network.guru.NetworkGuru; +import com.cloud.network.router.VirtualRouter; +import com.cloud.vm.DomainRouterVO; +import com.cloud.vm.NicVO; +import com.cloud.vm.dao.DomainRouterDao; +import com.cloud.vm.dao.NicDao; import org.apache.log4j.Logger; import org.apache.cloudstack.api.AddBaremetalKickStartPxeCmd; @@ -62,6 +75,8 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.NicProfile; import com.cloud.vm.ReservationContext; import com.cloud.vm.VirtualMachineProfile; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; @Local(value = BaremetalPxeService.class) public class BaremetalKickStartServiceImpl extends BareMetalPxeServiceBase implements BaremetalPxeService { @@ -80,9 +95,67 @@ public class BaremetalKickStartServiceImpl extends BareMetalPxeServiceBase imple NetworkDao _nwDao; @Inject VMTemplateDao _tmpDao; + @Inject + DomainRouterDao _routerDao; + @Inject + NicDao _nicDao; - @Override - public boolean prepare(VirtualMachineProfile profile, NicProfile nic, DeployDestination dest, ReservationContext context) { + private DomainRouterVO getVirtualRouter(Network network) { + List routers = _routerDao.listByNetworkAndRole(network.getId(), VirtualRouter.Role.VIRTUAL_ROUTER); + + if (routers.isEmpty()) { + throw new CloudRuntimeException(String.format("cannot find any running virtual router on network[id:%s, uuid:%s]", network.getId(), network.getUuid())); + } + + if (routers.size() > 1) { + throw new CloudRuntimeException(String.format("baremetal hasn't supported redundant router yet")); + } + + DomainRouterVO vr = routers.get(0); + if (!Hypervisor.HypervisorType.VMware.equals(vr.getHypervisorType())) { + throw new CloudRuntimeException(String.format("baremetal only support vmware virtual router, but get %s", vr.getHypervisorType())); + } + + return vr; + } + + private List parseKickstartUrl(VirtualMachineProfile profile) { + String tpl = profile.getTemplate().getUrl(); + assert tpl != null : "How can a null template get here!!!"; + String[] tpls = tpl.split(";"); + CloudRuntimeException err = + new CloudRuntimeException( + String.format( + "template url[%s] is not correctly encoded. it must be in format of ks=http_link_to_kickstartfile;kernel=nfs_path_to_pxe_kernel;initrd=nfs_path_to_pxe_initrd", + tpl)); + if (tpls.length != 3) { + throw err; + } + + String ks = null; + String kernel = null; + String initrd = null; + + for (String t : tpls) { + String[] kv = t.split("="); + if (kv.length != 2) { + throw err; + } + if (kv[0].equals("ks")) { + ks = kv[1]; + } else if (kv[0].equals("kernel")) { + kernel = kv[1]; + } else if (kv[0].equals("initrd")) { + initrd = kv[1]; + } else { + throw err; + } + } + + return Arrays.asList(ks, kernel, initrd); + } + + private boolean preparePxeInBasicZone(VirtualMachineProfile profile, NicProfile nic, DeployDestination dest, ReservationContext context) throws AgentUnavailableException, OperationTimedoutException { NetworkVO nwVO = _nwDao.findById(nic.getNetworkId()); QueryBuilder sc = QueryBuilder.create(BaremetalPxeVO.class); sc.and(sc.entity().getDeviceType(), Op.EQ, BaremetalPxeType.KICK_START.toString()); @@ -92,54 +165,81 @@ public class BaremetalKickStartServiceImpl extends BareMetalPxeServiceBase imple throw new CloudRuntimeException("No kickstart PXE server found in pod: " + dest.getPod().getId() + ", you need to add it before starting VM"); } VMTemplateVO template = _tmpDao.findById(profile.getTemplateId()); + List tuple = parseKickstartUrl(profile); + String ks = tuple.get(0); + String kernel = tuple.get(1); + String initrd = tuple.get(2); + + PrepareKickstartPxeServerCommand cmd = new PrepareKickstartPxeServerCommand(); + cmd.setKsFile(ks); + cmd.setInitrd(initrd); + cmd.setKernel(kernel); + cmd.setMac(nic.getMacAddress()); + cmd.setTemplateUuid(template.getUuid()); + Answer aws = _agentMgr.send(pxeVo.getHostId(), cmd); + if (!aws.getResult()) { + s_logger.warn("Unable to set host: " + dest.getHost().getId() + " to PXE boot because " + aws.getDetails()); + return false; + } + + return true; + } + + private URI buildUrl(String mgmtIp, String subPath) { + UriComponentsBuilder ub = UriComponentsBuilder.newInstance(); + ub.scheme("http"); + ub.scheme(mgmtIp); + ub.port(10086); + ub.path(subPath); + return ub.build().toUri(); + } + + private boolean preparePxeInAdvancedZone(VirtualMachineProfile profile, NicProfile nic, Network network, DeployDestination dest, ReservationContext context) { + DomainRouterVO vr = getVirtualRouter(network); + List nics = _nicDao.listByVmId(vr.getId()); + NicVO mgmtNic = null; + for (NicVO nicvo : nics) { + if (ControlNetworkGuru.class.getSimpleName().equals(nicvo.getReserver())) { + mgmtNic = nicvo; + break; + } + } + + if (mgmtNic == null) { + throw new CloudRuntimeException(String.format("cannot find management nic on virutal router[id:%s]", vr.getId())); + } + + BaremetalVritualRouterCommands.PreparePxeCmd cmd = new BaremetalVritualRouterCommands.PreparePxeCmd(); + List tuple = parseKickstartUrl(profile); + cmd.setKickStartUrl(tuple.get(0)); + cmd.setKernelUrl(tuple.get(1)); + cmd.setInitrdUrl(tuple.get(2)); + cmd.setGuestMac(nic.getMacAddress()); + RestTemplate rst = new RestTemplate(); + BaremetalVritualRouterCommands.PreparePxeRsp rsp = rst.getForObject(buildUrl(mgmtNic.getIp4Address(), BaremetalVritualRouterCommands.PREPARE_PXE_URL), BaremetalVritualRouterCommands.PreparePxeRsp.class); + if (!rsp.isSuccess()) { + throw new CloudRuntimeException(String.format("failed preparing PXE in virtual router[id:%s], because %s", vr.getId(), rsp.getError())); + } + + return true; + } + + @Override + public boolean prepare(VirtualMachineProfile profile, NicProfile nic, Network network, DeployDestination dest, ReservationContext context) { try { - String tpl = profile.getTemplate().getUrl(); - assert tpl != null : "How can a null template get here!!!"; - String[] tpls = tpl.split(";"); - CloudRuntimeException err = - new CloudRuntimeException( - String.format( - "template url[%s] is not correctly encoded. it must be in format of ks=http_link_to_kickstartfile;kernel=nfs_path_to_pxe_kernel;initrd=nfs_path_to_pxe_initrd", - tpl)); - if (tpls.length != 3) { - throw err; - } - - String ks = null; - String kernel = null; - String initrd = null; - - for (String t : tpls) { - String[] kv = t.split("="); - if (kv.length != 2) { - throw err; + if (DataCenter.NetworkType.Basic.equals(dest.getDataCenter().getNetworkType())) { + if (!preparePxeInBasicZone(profile, nic, dest, context)) { + return false; } - if (kv[0].equals("ks")) { - ks = kv[1]; - } else if (kv[0].equals("kernel")) { - kernel = kv[1]; - } else if (kv[0].equals("initrd")) { - initrd = kv[1]; - } else { - throw err; + } else { + if (!preparePxeInAdvancedZone(profile, nic, network, dest, context)) { + return false; } } - PrepareKickstartPxeServerCommand cmd = new PrepareKickstartPxeServerCommand(); - cmd.setKsFile(ks); - cmd.setInitrd(initrd); - cmd.setKernel(kernel); - cmd.setMac(nic.getMacAddress()); - cmd.setTemplateUuid(template.getUuid()); - Answer aws = _agentMgr.send(pxeVo.getHostId(), cmd); - if (!aws.getResult()) { - s_logger.warn("Unable to set host: " + dest.getHost().getId() + " to PXE boot because " + aws.getDetails()); - return aws.getResult(); - } - IpmISetBootDevCommand bootCmd = new IpmISetBootDevCommand(BootDev.pxe); - aws = _agentMgr.send(dest.getHost().getId(), bootCmd); + Answer aws = _agentMgr.send(dest.getHost().getId(), bootCmd); if (!aws.getResult()) { s_logger.warn("Unable to set host: " + dest.getHost().getId() + " to PXE boot because " + aws.getDetails()); } diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java index d5a7188cc9e..ab8eae90288 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeElement.java @@ -123,7 +123,7 @@ public class BaremetalPxeElement extends AdapterBase implements NetworkElement { _nicDao.update(nicVo.getId(), nicVo); /*This vm is just being created */ - if (!_pxeMgr.prepare(vm, nic, dest, context)) { + if (!_pxeMgr.prepare(vm, nic, network, dest, context)) { throw new CloudRuntimeException("Cannot prepare pxe server"); } } diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManager.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManager.java index fce27a472ed..38f1799c101 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManager.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManager.java @@ -44,7 +44,7 @@ public interface BaremetalPxeManager extends Manager, PluggableService { PING, KICK_START, } - boolean prepare(VirtualMachineProfile profile, NicProfile nic, DeployDestination dest, ReservationContext context); + boolean prepare(VirtualMachineProfile profile, NicProfile nic, Network network, DeployDestination dest, ReservationContext context); boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl); diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java index 261534a3dd9..e133f7d7b14 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeManagerImpl.java @@ -30,6 +30,7 @@ import javax.ejb.Local; import javax.inject.Inject; import javax.naming.ConfigurationException; +import com.cloud.network.Network; import org.apache.log4j.Logger; import org.apache.cloudstack.api.AddBaremetalKickStartPxeCmd; @@ -132,10 +133,10 @@ public class BaremetalPxeManagerImpl extends ManagerBase implements BaremetalPxe } @Override - public boolean prepare(VirtualMachineProfile profile, NicProfile nic, DeployDestination dest, ReservationContext context) { + public boolean prepare(VirtualMachineProfile profile, NicProfile nic, Network network, DeployDestination dest, ReservationContext context) { //TODO: select type from template BaremetalPxeType type = BaremetalPxeType.KICK_START; - return getServiceByType(type.toString()).prepare(profile, nic, dest, context); + return getServiceByType(type.toString()).prepare(profile, nic, network, dest, context); } @Override diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeService.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeService.java index c45f99e59d5..ef7494ac4db 100755 --- a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeService.java +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalPxeService.java @@ -24,6 +24,7 @@ package com.cloud.baremetal.networkservice; import java.util.List; +import com.cloud.network.Network; import org.apache.cloudstack.api.AddBaremetalPxeCmd; import org.apache.cloudstack.api.ListBaremetalPxeServersCmd; @@ -37,7 +38,7 @@ import com.cloud.vm.VirtualMachineProfile; public interface BaremetalPxeService extends Adapter { - public boolean prepare(VirtualMachineProfile profile, NicProfile nic, DeployDestination dest, ReservationContext context); + public boolean prepare(VirtualMachineProfile profile, NicProfile nic, Network network, DeployDestination dest, ReservationContext context); public boolean prepareCreateTemplate(Long pxeServerId, UserVm vm, String templateUrl); diff --git a/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalVritualRouterCommands.java b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalVritualRouterCommands.java new file mode 100755 index 00000000000..12bffd40b31 --- /dev/null +++ b/plugins/hypervisors/baremetal/src/com/cloud/baremetal/networkservice/BaremetalVritualRouterCommands.java @@ -0,0 +1,74 @@ +package com.cloud.baremetal.networkservice; + +/** + * Created by frank on 7/23/14. + */ +public class BaremetalVritualRouterCommands { + public static String PREPARE_PXE_URL = "/baremetal/pxe/prepare"; + + public abstract static class AgentCommand { + } + + public abstract static class AgentResponse { + private boolean success; + private String error; + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public String getError() { + return error; + } + + public void setError(String error) { + this.error = error; + } + } + + public static class PreparePxeCmd extends AgentCommand { + private String guestMac; + private String kickStartUrl; + private String initrdUrl; + private String kernelUrl; + + public String getGuestMac() { + return guestMac; + } + + public void setGuestMac(String guestMac) { + this.guestMac = guestMac; + } + + public String getKickStartUrl() { + return kickStartUrl; + } + + public void setKickStartUrl(String kickStartUrl) { + this.kickStartUrl = kickStartUrl; + } + + public String getInitrdUrl() { + return initrdUrl; + } + + public void setInitrdUrl(String initrdUrl) { + this.initrdUrl = initrdUrl; + } + + public String getKernelUrl() { + return kernelUrl; + } + + public void setKernelUrl(String kernelUrl) { + this.kernelUrl = kernelUrl; + } + } + + public static class PreparePxeRsp extends AgentResponse { + } +}