CloudStack CLOUDSTACK-774

Supporting kickstart in CloudStack baremetal

adding missing scripts back

Conflicts:

	client/pom.xml
	client/tomcatconf/commands.properties.in
	server/src/com/cloud/server/ManagementServerImpl.java
This commit is contained in:
frank 2013-02-15 17:09:05 -08:00
parent 1f15c1e9e7
commit 55b77c7c8f
19 changed files with 300 additions and 29 deletions

View File

@ -273,6 +273,12 @@
</goals>
<configuration>
<target>
<exec executable="cp">
<arg value="-r" />
<arg value="${basedir}/../scripts" />
<arg value="${basedir}/target/generated-webapp/WEB-INF/classes/scripts" />
</exec>
<copy
todir="${basedir}/target/generated-webapp/WEB-INF/">
<fileset dir="${basedir}/WEB-INF/">
@ -285,13 +291,7 @@
<include name="resources/**/*" />
</fileset>
</copy>
<copy
todir="${basedir}/target/generated-webapp/WEB-INF/classes/scripts">
<fileset dir="${basedir}/../scripts">
</fileset>
</copy>
<copy
todir="${basedir}/target/generated-webapp/WEB-INF/classes/vms">
<copy todir="${basedir}/target/generated-webapp/WEB-INF/classes/vms">
<fileset dir="${basedir}/../services/console-proxy/server/dist">
<include name="systemvm.zip" />
<include name="systemvm.iso" />

View File

@ -543,3 +543,6 @@ listVMSnapshot=15
createVMSnapshot=15
deleteVMSnapshot=15
revertToSnapshot=15
#### Baremetal commands
addBaremetalHost=1

View File

@ -74,6 +74,9 @@
<bean id="BareMetalPxe" class="com.cloud.baremetal.networkservice.BaremetalPxeElement">
<property name="name" value="BareMetalPxe"/>
</bean>
<bean id="BareMetalUserdata" class="com.cloud.baremetal.networkservice.BaremetalUserdataElement">
<property name="name" value="BareMetalUserdata"/>
</bean>
<bean id="SecurityGroupProvider" class="com.cloud.network.element.SecurityGroupElement">
<property name="name" value="SecurityGroupProvider"/>
</bean>

View File

@ -30,7 +30,12 @@ public class AddBaremetalHostCmd extends AddHostCmd {
private String vmIpAddress;
public AddBaremetalHostCmd() {
}
@Override
public void execute(){
this.getFullUrlParams().put(ApiConstants.BAREMETAL_DISCOVER_NAME, BareMetalDiscoverer.class.getName());
super.execute();
}
public String getVmIpAddress() {

View File

@ -20,8 +20,9 @@ package com.cloud.baremetal.manager;
import com.cloud.network.Network.Provider;
import com.cloud.utils.component.Manager;
import com.cloud.utils.component.PluggableService;
public interface BaremetalManager extends Manager {
public interface BaremetalManager extends Manager, PluggableService {
public static final String EchoSecurityGroupAgent = "EchoSecurityGroupAgent";
public static final String ExternalBaremetalSystemUrl = "ExternalBaremetalSystemUrl";
public static final String DO_PXE = "doPxe";

View File

@ -18,6 +18,8 @@
// Automatically generated by addcopyright.py at 01/29/2013
package com.cloud.baremetal.manager;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
@ -110,4 +112,11 @@ public class BaremetalManagerImpl extends ManagerBase implements BaremetalManage
return true;
}
@Override
public List<Class<?>> getCommands() {
List<Class<?>> cmds = new ArrayList<Class<?>>();
cmds.add(AddBaremetalHostCmd.class);
return cmds;
}
}

View File

@ -26,6 +26,8 @@ import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.BaseCmd.CommandType;
import org.apache.cloudstack.api.response.PhysicalNetworkResponse;
import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.log4j.Logger;
@ -48,10 +50,10 @@ public class AddBaremetalDhcpCmd extends BaseAsyncCmd {
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.LONG, required=true, description="the Physical Network ID")
@Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.UUID, entityType=PhysicalNetworkResponse.class, required=true, description="the Physical Network ID")
private Long physicalNetworkId;
@Parameter(name=ApiConstants.POD_ID, type=CommandType.LONG, required = true, description="Pod Id")
@Parameter(name=ApiConstants.POD_ID, type=CommandType.UUID, entityType=PodResponse.class, required = true, description="Pod Id")
private Long podId;
@Parameter(name=ApiConstants.DHCP_SERVER_TYPE, type=CommandType.STRING, required = true, description="Type of dhcp device")

View File

@ -26,6 +26,8 @@ import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.BaseAsyncCmd;
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.BaseCmd.CommandType;
import org.apache.cloudstack.api.response.PhysicalNetworkResponse;
import org.apache.cloudstack.api.response.PodResponse;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.log4j.Logger;
@ -46,10 +48,10 @@ public class AddBaremetalPxeCmd extends BaseAsyncCmd {
/////////////////////////////////////////////////////
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
@Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.LONG, required=true, description="the Physical Network ID")
@Parameter(name=ApiConstants.PHYSICAL_NETWORK_ID, type=CommandType.UUID, entityType=PhysicalNetworkResponse.class, required=true, description="the Physical Network ID")
private Long physicalNetworkId;
@Parameter(name=ApiConstants.POD_ID, type=CommandType.LONG, description="Pod Id")
@Parameter(name=ApiConstants.POD_ID, type=CommandType.UUID, entityType=PodResponse.class, description="Pod Id")
private Long podId;
@Parameter(name=ApiConstants.URL, type=CommandType.STRING, required = true, description="URL of the external pxe device")

View File

@ -297,4 +297,10 @@ public class BareMetalPingServiceImpl extends BareMetalPxeServiceBase implements
}
return responses;
}
@Override
public String getPxeServiceType() {
return BaremetalPxeManager.BaremetalPxeType.PING.toString();
}
}

View File

@ -32,6 +32,7 @@ import com.cloud.agent.api.Command;
import com.cloud.agent.api.PingCommand;
import com.cloud.agent.api.PingRoutingCommand;
import com.cloud.agent.api.routing.VmDataCommand;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.script.Script;
import com.cloud.utils.ssh.SSHCmdHelper;
import com.cloud.vm.VirtualMachine.State;
@ -70,27 +71,27 @@ public class BaremetalKickStartPxeResource extends BaremetalPxeResourceBase {
String prepareScript = "scripts/network/ping/prepare_kickstart_bootfile.py";
String prepareScriptPath = Script.findScript("", prepareScript);
if (prepareScriptPath == null) {
throw new ConfigurationException("Can not find prepare_kickstart_bootfile.py at " + prepareScriptPath);
throw new ConfigurationException("Can not find prepare_kickstart_bootfile.py at " + prepareScript);
}
scp.put(prepareScriptPath, "/usr/bin/", "0755");
String cpScript = "scripts/network/ping/prepare_kickstart_kernel_initrd.py";
String cpScriptPath = Script.findScript("", cpScript);
if (cpScriptPath == null) {
throw new ConfigurationException("Can not find prepare_kickstart_kernel_initrd.py at " + cpScriptPath);
throw new ConfigurationException("Can not find prepare_kickstart_kernel_initrd.py at " + cpScript);
}
scp.put(cpScriptPath, "/usr/bin/", "0755");
String userDataScript = "scripts/network/ping/baremetal_user_data.py";
String userDataScriptPath = Script.findScript("", userDataScript);
if (userDataScriptPath == null) {
throw new ConfigurationException("Can not find baremetal_user_data.py at " + userDataScriptPath);
throw new ConfigurationException("Can not find baremetal_user_data.py at " + userDataScript);
}
scp.put(userDataScriptPath, "/usr/bin/", "0755");
return true;
} catch (Exception e) {
throw new ConfigurationException(e.getMessage());
throw new CloudRuntimeException(e);
} finally {
if (sshConnection != null) {
sshConnection.close();

View File

@ -235,4 +235,9 @@ public class BaremetalKickStartServiceImpl extends BareMetalPxeServiceBase imple
return responses;
}
@Override
public String getPxeServiceType() {
return BaremetalPxeManager.BaremetalPxeType.KICK_START.toString();
}
}

View File

@ -54,7 +54,6 @@ import com.cloud.resource.UnableDeleteHostException;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.uservm.UserVm;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.SearchCriteria.Op;
import com.cloud.utils.db.SearchCriteria2;
@ -107,12 +106,13 @@ public class BaremetalPxeManagerImpl extends ManagerBase implements BaremetalPxe
}
protected BaremetalPxeService getServiceByType(String type) {
BaremetalPxeService _service;
_service = AdapterBase.getAdapterByName(_services, type);
if (_service == null) {
throw new CloudRuntimeException("Cannot find PXE service for " + type);
for (BaremetalPxeService service : _services) {
if (service.getPxeServiceType().equals(type)) {
return service;
}
}
return _service;
throw new CloudRuntimeException("Cannot find PXE service for " + type);
}
@Override

View File

@ -46,6 +46,8 @@ public interface BaremetalPxeService extends Adapter {
List<BaremetalPxeResponse> listPxeServers(ListBaremetalPxePingServersCmd cmd);
String getPxeServiceType();
public static final String PXE_PARAM_TYPE = "type";
public static final String PXE_PARAM_ZONE = "zone";
public static final String PXE_PARAM_POD = "pod";

View File

@ -149,7 +149,7 @@ public class BaremetalUserdataElement extends AdapterBase implements NetworkElem
@Override
public boolean canEnableIndividualServices() {
// TODO Auto-generated method stub
return false;
return true;
}
@ -162,14 +162,12 @@ public class BaremetalUserdataElement extends AdapterBase implements NetworkElem
@Override
public boolean destroy(Network network, ReservationContext context) throws ConcurrentOperationException, ResourceUnavailableException {
// TODO Auto-generated method stub
return false;
return true;
}
@Override
public boolean verifyServicesCombination(Set<Service> services) {
// TODO Auto-generated method stub
return false;
return true;
}
}

View File

@ -0,0 +1,87 @@
'''
Created on Jul 2, 2012
@author: frank
'''
import sys
import os
import os.path
import base64
HTML_ROOT = "/var/www/html/"
def writeIfNotHere(fileName, texts):
if not os.path.exists(fileName):
entries = []
else:
f = open(fileName, 'r')
entries = f.readlines()
f.close()
texts = [ "%s\n" % t for t in texts ]
need = False
for t in texts:
if not t in entries:
entries.append(t)
need = True
if need:
f = open(fileName, 'w')
f.write(''.join(entries))
f.close()
def createRedirectEntry(vmIp, folder, filename):
entry = "RewriteRule ^%s$ ../%s/%%{REMOTE_ADDR}/%s [L,NC,QSA]" % (filename, folder, filename)
htaccessFolder="/var/www/html/latest"
htaccessFile=os.path.join(htaccessFolder, ".htaccess")
if not os.path.exists(htaccessFolder):
os.makedirs(htaccessFolder)
writeIfNotHere(htaccessFile, ["Options +FollowSymLinks", "RewriteEngine On", entry])
htaccessFolder = os.path.join("/var/www/html/", folder, vmIp)
if not os.path.exists(htaccessFolder):
os.makedirs(htaccessFolder)
htaccessFile=os.path.join(htaccessFolder, ".htaccess")
entry="Options -Indexes\nOrder Deny,Allow\nDeny from all\nAllow from %s" % vmIp
f = open(htaccessFile, 'w')
f.write(entry)
f.close()
if folder in ['metadata', 'meta-data']:
entry1="RewriteRule ^meta-data/(.+)$ ../%s/%%{REMOTE_ADDR}/$1 [L,NC,QSA]" % folder
htaccessFolder="/var/www/html/latest"
htaccessFile=os.path.join(htaccessFolder, ".htaccess")
entry2="RewriteRule ^meta-data/$ ../%s/%%{REMOTE_ADDR}/meta-data [L,NC,QSA]" % folder
writeIfNotHere(htaccessFile, [entry1, entry2])
def addUserData(vmIp, folder, fileName, contents):
baseFolder = os.path.join(HTML_ROOT, folder, vmIp)
if not os.path.exists(baseFolder):
os.makedirs(baseFolder)
createRedirectEntry(vmIp, folder, fileName)
datafileName = os.path.join(HTML_ROOT, folder, vmIp, fileName)
metaManifest = os.path.join(HTML_ROOT, folder, vmIp, "meta-data")
if folder == "userdata":
if contents != "none":
contents = base64.urlsafe_b64decode(contents)
else:
contents = ""
f = open(datafileName, 'w')
f.write(contents)
f.close()
if folder == "metadata" or folder == "meta-data":
writeIfNotHere(metaManifest, fileName)
if __name__ == '__main__':
string = sys.argv[1]
allEntires = string.split(";")
for entry in allEntires:
(vmIp, folder, fileName, contents) = entry.split(',', 3)
addUserData(vmIp, folder, fileName, contents)
sys.exit(0)

View File

@ -0,0 +1,78 @@
#!/usr/bin/python
# Copyright 2012 Citrix Systems, Inc. Licensed under the
# Apache License, Version 2.0 (the "License"); you may not use this
# file except in compliance with the License. Citrix Systems, Inc.
# reserves all rights not expressly granted by the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Automatically generated by addcopyright.py at 04/03/2012
# Usage: prepare_tftp_bootfile.py tftp_dir mac cifs_server share directory image_to_restore cifs_username cifs_password
import os, sys
from sys import exit
from os import makedirs
from os.path import exists, join
fmt1 = '''DEFAULT default
PROMPT 1
TIMEOUT 26
DISPLAY boot.msg
LABEL default
KERNEL %s
APPEND ramdisk_size=66000 initrd=%s ksdevice=%s ks=%s
'''
fmt2 = '''DEFAULT default
PROMPT 1
TIMEOUT 26
DISPLAY boot.msg
LABEL default
KERNEL %s
APPEND ramdisk_size=66000 initrd=%s ks=%s
'''
tftp_dir = ''
mac = ''
kernel = ''
initrd = ''
ks_file = ''
ks_device = ''
def prepare():
try:
pxelinux = join(tftp_dir, "pxelinux.cfg")
if exists(pxelinux) == False:
makedirs(pxelinux)
cfg_name = "01-" + mac.replace(':','-').lower()
cfg_path = join(pxelinux, cfg_name)
f = open(cfg_path, "w")
if ks_device == '':
stuff = fmt2 % (kernel, initrd, ks_file)
else:
stuff = fmt1 % (kernel, initrd, ks_device, ks_file)
f.write(stuff)
f.close()
return 0
except Exception, e:
print e
return 1
if __name__ == "__main__":
if len(sys.argv) < 7:
print "Usage: prepare_kickstart_bootfile.py tftp_dir mac kernel initrd ks_file ks_device"
exit(1)
(tftp_dir, mac, kernel, initrd, ks_file, ks_device) = sys.argv[1:]
ret = prepare()
exit(ret)

View File

@ -0,0 +1,54 @@
#!/usr/bin/python
import sys
import tempfile
import os.path
import os
iso_folder = ''
copy_to = ''
def cmd(cmdstr, err=True):
if os.system(cmdstr) != 0 and err:
raise Exception("Failed to run shell command: %s" % cmdstr)
def prepare():
try:
kernel = os.path.join(copy_to, "vmlinuz")
initrd = os.path.join(copy_to, "initrd.img")
if os.path.exists(kernel) and os.path.exists(initrd):
print "Having template(%s) prepared already, skip copying" % copy_to
return 0
else:
if not os.path.exists(copy_to):
os.makedirs(copy_to)
mnt_path = tempfile.mkdtemp()
try:
mnt = "mount %s %s" % (iso_folder, mnt_path)
cmd(mnt)
kernel = os.path.join(mnt_path, "vmlinuz")
initrd = os.path.join(mnt_path, "initrd.img")
cp = "cp -f %s %s/" % (kernel, copy_to)
cmd(cp)
cp = "cp -f %s %s/" % (initrd, copy_to)
cmd(cp)
finally:
umnt = "umount %s" % mnt_path
cmd(umnt, False)
rm = "rm -r %s" % mnt_path
cmd(rm, False)
return 0
except Exception, e:
print e
return 1
if __name__ == "__main__":
if len(sys.argv) < 3:
print "Usage: prepare_kickstart_kerneal_initrd.py path_to_kernel_initrd_iso path_kernel_initrd_copy_to"
sys.exit(1)
(iso_folder, copy_to) = sys.argv[1:]
sys.exit(prepare())

0
scripts/util/ipmi.py Normal file → Executable file
View File

View File

@ -1939,6 +1939,9 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
// add VPCVirtualRouter as the defualt network service provider
addDefaultVpcVirtualRouterToPhysicalNetwork(pNetwork.getId());
// add baremetal pxe/dhcp provider to the physical network
addDefaultBaremetalProvidersToPhysicalNetwork(pNetwork.getId());
txn.commit();
return pNetwork;
} catch (Exception ex) {
@ -2747,6 +2750,18 @@ public class NetworkServiceImpl extends ManagerBase implements NetworkService {
return nsp;
}
private PhysicalNetworkServiceProvider addDefaultBaremetalProvidersToPhysicalNetwork(long physicalNetworkId) {
PhysicalNetworkVO pvo = _physicalNetworkDao.findById(physicalNetworkId);
DataCenterVO dvo = _dcDao.findById(pvo.getDataCenterId());
if (dvo.getNetworkType() == NetworkType.Basic) {
addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalDhcpProvider", null, null);
addProviderToPhysicalNetwork(physicalNetworkId, "BaremetalPxeProvider", null, null);
addProviderToPhysicalNetwork(physicalNetworkId, "BaremetaUserdataProvider", null, null);
}
return null;
}
protected PhysicalNetworkServiceProvider addDefaultVpcVirtualRouterToPhysicalNetwork(long physicalNetworkId) {
PhysicalNetworkServiceProvider nsp = addProviderToPhysicalNetwork(physicalNetworkId,