Mutiple winpes support. nodeset (Windows.pm) will generate configuration file (path of winpe) in /var/lib/xcat/proxydhcp.cfg and send signal to proxydhcp daemon, proxydhcp daemon loads configuration file and offers 4011 service to windows compute nodes.

This commit is contained in:
daniceexi 2013-12-10 05:34:09 -05:00
parent 2dd2518120
commit 663a0b7da8
5 changed files with 369 additions and 99 deletions

View File

@ -736,15 +736,16 @@ linuximage => {
},
},
winimage => {
cols => [qw(imagename template installto partitionfile comments disable)],
cols => [qw(imagename template installto partitionfile winpepath comments disable)],
keys => [qw(imagename)],
tablespace =>'XCATTBS32K',
table_desc => 'Information about a Windows operating system image that can be used to deploy cluster nodes.',
descriptions => {
imagename => 'The name of this xCAT OS image definition.',
template => 'The fully qualified name of the template file that is used to create the windows unattend.xml file for diskful installation.',
installto => 'The disk and partition that the Windows will be deployed to. The valid format is <disk>:<partition>. If it is not set, default value is 0:1 for bios boot mode(legacy) and 0:3 for uefi boot mode; If it is set to 1, it means 1:1 for bios boot and 1:3 for uefi boot',
partitionfile => 'The path of partition configuration file. Since the partition configuration for bios boot mode and uefi boot mode are different, this configuration file should include two parts if customer wants to support both bios and uefi mode. If customer just wants to support one of the modes, specify one of them anyway. Example of partition configuration file: [BIOS]xxxxxxx[UEFI]yyyyyyy.',
installto => 'The disk and partition that the Windows will be deployed to. The valid format is <disk>:<partition>. If not set, default value is 0:1 for bios boot mode(legacy) and 0:3 for uefi boot mode; If setting to 1, it means 1:1 for bios boot and 1:3 for uefi boot',
partitionfile => 'The path of partition configuration file. Since the partition configuration for bios boot mode and uefi boot mode are different, this configuration file should include two parts if customer wants to support both bios and uefi mode. If customer just wants to support one of the modes, specify one of them anyway. Example of partition configuration file: [BIOS]xxxxxxx[UEFI]yyyyyyy. To simplify the setting, you also can set installto in partitionfile with section likes [INSTALLTO]0:1',
winpepath => 'The path of winpe which will be used to boot this image. If the real path is /tftpboot/winboot/winpe1/, the value for winpepath should be set to winboot/winpe1',
comments => 'Any user-written notes.',
disable => "Set to 'yes' or '1' to comment out this row.",
}
@ -2749,6 +2750,11 @@ push(@{$defspec{node}->{'attrs'}}, @nodeattrs);
tabentry => 'winimage.partitionfile',
access_tabentry => 'winimage.imagename=attr:imagename',
},
{attr_name => 'winpepath',
only_if => 'imagetype=windows',
tabentry => 'winimage.winpepath',
access_tabentry => 'winimage.imagename=attr:imagename',
},
####################
# nimimage table#
####################

View File

@ -6,84 +6,275 @@
#include <stdlib.h>
#include <errno.h>
#include <netinet/in.h>
int main() {
int serverfd,port;
int getpktinfo = 1;
struct addrinfo hint, *res;
char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))];
char clientpacket[1024];
struct sockaddr_in clientaddr;
struct msghdr msg;
struct cmsghdr *cmsgptr;
struct iovec iov[1];
unsigned int myip;
char *txtptr;
iov[0].iov_base = clientpacket;
iov[0].iov_len = 1024;
memset(&msg,0,sizeof(msg));
memset(&clientaddr,0,sizeof(clientaddr));
msg.msg_name=&clientaddr;
msg.msg_namelen = sizeof(clientaddr);
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_control=&cmsg;
msg.msg_controllen = sizeof(cmsg);
char bootpmagic[4] = {0x63,0x82,0x53,0x63};
int pktsize;
int doexit=0;
port = 4011;
memset(&hint,0,sizeof(hint));
hint.ai_family = PF_INET; /* Would've done UNSPEC, but it doesn't work right and this is heavily v4 specific anyway */
hint.ai_socktype = SOCK_DGRAM;
hint.ai_flags = AI_PASSIVE;
getaddrinfo(NULL,"4011",&hint,&res);
serverfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (!serverfd) { fprintf(stderr,"That's odd...\n"); }
setsockopt(serverfd,IPPROTO_IP,IP_PKTINFO,&getpktinfo,sizeof(getpktinfo));
if (bind(serverfd,res->ai_addr ,res->ai_addrlen) < 0) {
fprintf(stderr,"Unable to bind 4011");
exit(1);
}
while (!doexit) {
pktsize = recvmsg(serverfd,&msg,0);
if (pktsize < 320) {
continue;
}
if (clientpacket[0] != 1 || memcmp(clientpacket+0xec,bootpmagic,4)) {
continue;
}
for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg,cmsgptr)) {
if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO) {
myip = ((struct in_pktinfo*)(CMSG_DATA(cmsgptr)))->ipi_addr.s_addr;
}
}
clientpacket[0] = 2; //change to a reply
myip = htonl(myip); //endian neutral change
clientpacket[0x14] = (myip>>24)&0xff; //maybe don't need to do this, maybe assigning the whole int would be better
clientpacket[0x15] = (myip>>16)&0xff;
clientpacket[0x16] = (myip>>8)&0xff;
clientpacket[0x17] = (myip)&0xff;
txtptr = clientpacket+0x6c;
strncpy(txtptr,"Boot/bootmgfw.efi",128); // keeping 128 in there just in case someone changes the string
clientpacket[0xf0]=0x35; //DHCP MSG type
clientpacket[0xf1]=0x1; // LEN of 1
clientpacket[0xf2]=0x5; //DHCP ACK
clientpacket[0xf3]=0x36; //DHCP server identifier
clientpacket[0xf4]=0x4; //DHCP server identifier length
clientpacket[0xf5] = (myip>>24)&0xff; //maybe don't need to do this, maybe assigning the whole int would be better
clientpacket[0xf6] = (myip>>16)&0xff;
clientpacket[0xf7] = (myip>>8)&0xff;
clientpacket[0xf8] = (myip)&0xff;
clientpacket[0xf9] = 0xfc; // dhcp 252 'proxy', but coopeted by bootmgfw, it's actually suggesting the boot config file
clientpacket[0xfa] = 9; //length of 9
txtptr = clientpacket+0xfb;
strncpy(txtptr,"Boot/BCD",8);
clientpacket[0x103]=0;
clientpacket[0x104]=0xff;
sendto(serverfd,clientpacket,pktsize,0,(struct sockaddr*)&clientaddr,sizeof(clientaddr));
}
#include <signal.h>
#include <syslog.h>
// the chunk size for each alloc
int chunknum = 200;
int doreload = 0;
int verbose = 0;
char logmsg[50];
// the struct to store the winpe configuration for each node
struct nodecfg {
char node[50];
char data[150];
};
char *data = NULL; // the ptr to the array of all node config
int nodenum = 0;
// trigger the main program to reload configuration file
void reload(int sig) {
doreload = 1;
}
// the subroutine which is used to load configuration from
// /var/lib/xcat/proxydhcp.cfg to *data
void loadcfg () {
nodenum = 0;
free(data);
data = NULL;
doreload = 0;
char *dp = NULL;
FILE *fp;
fp = fopen("/var/lib/xcat/proxydhcp.cfg", "r");
if (fp) {
int num = chunknum;
int rtime = 1;
while (num == chunknum) {
// realloc the chunknum size of memory each to save memory usage
data = realloc(data, sizeof(struct nodecfg) * chunknum * rtime);
if (NULL == data) {
fprintf (stderr, "Cannot get enough memory.\n");
free (data);
return;
}
dp = data + sizeof(struct nodecfg) * chunknum * (rtime - 1);
memset(dp, 0, sizeof(struct nodecfg) * chunknum);
num = fread(dp, sizeof (struct nodecfg), chunknum, fp);
nodenum += num;
rtime++;
}
fclose(fp);
}
}
// get the path of winpe from configuration file which is stored in *data
char *getwinpepath(char *node) {
int i;
struct nodecfg *nc = (struct nodecfg *)data;
for (i=0; i<nodenum;i++) {
if (0 == strcmp(nc->node, node)) {
return nc->data;
}
nc++;
}
return NULL;
}
int main(int argc, char *argv[]) {
int i;
for(i = 0; i < argc; i++)
{
if (strcmp(argv[i], "-V") == 0) {
verbose = 1;
setlogmask(LOG_UPTO(LOG_DEBUG));
openlog("proxydhcp", LOG_NDELAY, LOG_LOCAL0);
}
}
// regist my pid to /var/run/xcat/proxydhcp.pid
int pid = getpid();
FILE *pidf = fopen ("/var/run/xcat/proxydhcp.pid", "w");
if (pidf) {
fprintf(pidf, "%d", pid);
fclose (pidf);
} else {
fprintf (stderr, "Cannot open /var/run/xcat/proxydhcp.pid\n");
return 1;
}
// load configuration at first start
loadcfg();
// regist signal SIGUSR1 for triggering reload configuration from outside
struct sigaction sigact;
sigact.sa_handler = &reload;
sigaction(SIGUSR1, &sigact, NULL);
int serverfd,port;
int getpktinfo = 1;
struct addrinfo hint, *res;
char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))];
char clientpacket[1024];
struct sockaddr_in clientaddr;
struct msghdr msg;
struct cmsghdr *cmsgptr;
struct iovec iov[1];
unsigned int myip, clientip;
char *txtptr;
iov[0].iov_base = clientpacket;
iov[0].iov_len = 1024;
memset(&msg,0,sizeof(msg));
memset(&clientaddr,0,sizeof(clientaddr));
msg.msg_name=&clientaddr;
msg.msg_namelen = sizeof(clientaddr);
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_control=&cmsg;
msg.msg_controllen = sizeof(cmsg);
char defaultwinpe[20] = "Boot/bootmgfw.efi";
char bootpmagic[4] = {0x63,0x82,0x53,0x63};
int pktsize;
int doexit=0;
port = 4011;
memset(&hint,0,sizeof(hint));
hint.ai_family = PF_INET; /* Would've done UNSPEC, but it doesn't work right and this is heavily v4 specific anyway */
hint.ai_socktype = SOCK_DGRAM;
hint.ai_flags = AI_PASSIVE;
getaddrinfo(NULL,"4011",&hint,&res);
serverfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if (!serverfd) { fprintf(stderr,"That's odd...\n"); }
setsockopt(serverfd,IPPROTO_IP,IP_PKTINFO,&getpktinfo,sizeof(getpktinfo));
if (bind(serverfd,res->ai_addr ,res->ai_addrlen) < 0) {
fprintf(stderr,"Unable to bind 4011");
exit(1);
}
while (!doexit) {
// use select to wait for the 4011 request packages coming
fd_set fds;
FD_ZERO(&fds);
FD_SET(serverfd, &fds);
struct timeval timeout;
timeout.tv_sec = 30;
timeout.tv_usec = 0;
int rc;
if ((rc = select(serverfd+1,&fds,0,0, &timeout)) <= 0) {
if (doreload) {
loadcfg();
fprintf(stderr, "load in select\n");
}
if (verbose) {syslog(LOG_DEBUG, "reload /var/lib/xcat/proxydhcp.cfg\n");}
continue;
}
if (doreload) {
loadcfg();
if (verbose) {syslog(LOG_DEBUG, "reload /var/lib/xcat/proxydhcp.cfg\n");}
}
pktsize = recvmsg(serverfd,&msg,0);
if (pktsize < 320) {
continue;
}
if (clientpacket[0] != 1 || memcmp(clientpacket+0xec,bootpmagic,4)) {
continue;
}
for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg,cmsgptr)) {
if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO) {
myip = ((struct in_pktinfo*)(CMSG_DATA(cmsgptr)))->ipi_addr.s_addr;
}
}
// get the ip of dhcp client
clientip = 0;
int i;
for (i = 0; i< 4; i++) {
clientip = clientip << 8;
clientip += (unsigned char)clientpacket[15-i];
}
// get the winpe path
struct hostent *host = gethostbyaddr(&clientip, sizeof(clientip), AF_INET);
char *winpepath = defaultwinpe;
if (host) {
if (host->h_name) {
// remove the domain part from hostname
char *place = strstr(host->h_name, ".");
if (place) {
*place = '\0';
}
winpepath = getwinpepath(host->h_name);
if (winpepath == NULL) {
winpepath = defaultwinpe;
}
if (verbose) {
sprintf(logmsg, "Received proxydhcp request from %s\n", host->h_name);
syslog(LOG_DEBUG, logmsg);
}
}
} else {
winpepath = defaultwinpe;
}
// get the Vendor class identifier
char *arch = NULL;
unsigned char *p = clientpacket + 0xf0;
while (*p != 0xff && p < (unsigned char *)clientpacket + pktsize) {
if (*p == 60) {
arch = p + 0x11;
break;
} else {
p += *(p+1) + 2;
}
}
char winboot[50]; // the bootload of winpe
memset(winboot, 0, 50);
if (0 == memcmp(arch, "00000", 5)) { // bios boot mode
strcpy(winboot, winpepath);
strcat(winboot, "Boot/pxeboot.0");
} else if (0 == memcmp(arch, "00007", 5)) { // uefi boot mode
strcpy(winboot, winpepath);
strcat(winboot, "Boot/bootmgfw.efi");
}
clientpacket[0] = 2; //change to a reply
myip = htonl(myip); //endian neutral change
clientpacket[0x14] = (myip>>24)&0xff; //maybe don't need to do this, maybe assigning the whole int would be better
clientpacket[0x15] = (myip>>16)&0xff;
clientpacket[0x16] = (myip>>8)&0xff;
clientpacket[0x17] = (myip)&0xff;
txtptr = clientpacket+0x6c;
strncpy(txtptr, winboot ,128); // keeping 128 in there just in case someone changes the string
//strncpy(txtptr,"winboot/new/Boot/bootmgfw.efi",128); // keeping 128 in there just in case someone changes the string
//strncpy(txtptr,"Boot/pxeboot.0",128); // keeping 128 in there just in case someone changes the string
clientpacket[0xf0]=0x35; //DHCP MSG type
clientpacket[0xf1]=0x1; // LEN of 1
clientpacket[0xf2]=0x5; //DHCP ACK
clientpacket[0xf3]=0x36; //DHCP server identifier
clientpacket[0xf4]=0x4; //DHCP server identifier length
clientpacket[0xf5] = (myip>>24)&0xff; //maybe don't need to do this, maybe assigning the whole int would be better
clientpacket[0xf6] = (myip>>16)&0xff;
clientpacket[0xf7] = (myip>>8)&0xff;
clientpacket[0xf8] = (myip)&0xff;
char winBCD[50];
strcpy(winBCD, winpepath);
strcat(winBCD, "Boot/BCD");
clientpacket[0xf9] = 0xfc; // dhcp 252 'proxy', but coopeted by bootmgfw, it's actually suggesting the boot config file
clientpacket[0xfa] = strlen(winBCD) + 1; //length of 9
txtptr = clientpacket+0xfb;
strncpy(txtptr, winBCD, strlen(winBCD));
clientpacket[0xfa + strlen(winBCD) + 1] = 0;
clientpacket[0xfa + strlen(winBCD) + 2] = 0xff;
sendto(serverfd,clientpacket,pktsize,0,(struct sockaddr*)&clientaddr,sizeof(clientaddr));
if (verbose) {
sprintf(logmsg, "Path of bootloader:%s. Path of BCD:%s\n", winboot, winBCD);
syslog(LOG_DEBUG, logmsg);
}
}
if (verbose) { closelog();}
}

View File

@ -100,6 +100,17 @@ sub check_uefi_support {
return 1;
}
# check whether the proxydhcp has been enabled.
sub proxydhcp {
my @output = xCAT::Utils->runcmd("ps -C proxydhcp", -1);
if (@output) {
if (grep /proxydhcp/, @output) {
return 1;
}
}
return 0;
}
sub ipIsDynamic {
#meant to be v4/v6 agnostic. DHCPv6 however takes some care to allow a dynamic range to overlap static reservations
@ -574,14 +585,18 @@ sub addnode
if ($doiscsi and $chainent and $chainent->{currstate} and ($chainent->{currstate} eq 'iscsiboot' or $chainent->{currstate} eq 'boot')) {
$lstatements = 'if option client-architecture = 00:00 and not exists gpxe.bus-id { filename = \"xcat/xnba.kpxe\"; } else { filename = \"\"; } '.$lstatements;
} else {
#TODO: if windows uefi, do vendor-class-identifier of "PXEClient" to bump it over to proxydhcp.c
if (($douefi == 2 and $chainent->{currstate} =~ /^install/) or $chainent->{currstate} =~ /^winshell/) { #proxy dhcp required in uefi invocation
$lstatements = 'if option user-class-identifier = \"xNBA\" and option client-architecture = 00:00 { always-broadcast on; filename = \"http://'.$nxtsrv.'/tftpboot/xcat/xnba/nodes/'.$node.'\"; } else if option client-architecture = 00:07 or option client-architecture = 00:09 { filename = \"\"; option vendor-class-identifier \"PXEClient\"; } else if option client-architecture = 00:00 { filename = \"xcat/xnba.kpxe\"; } else { filename = \"\"; }'.$lstatements; #Only PXE compliant clients should ever receive xNBA
} elsif ($douefi and $chainent->{currstate} ne "boot" and $chainent->{currstate} ne "iscsiboot") {
# If proxydhcp daemon is enabled for windows deployment, do vendor-class-identifier of "PXEClient" to bump it over to proxydhcp.c
if (($douefi == 2 and $chainent->{currstate} =~ /^install/) or $chainent->{currstate} =~ /^winshell/) {
if (proxydhcp()){ #proxy dhcp required in uefi invocation
$lstatements = 'if option client-architecture = 00:00 or option client-architecture = 00:07 or option client-architecture = 00:09 { filename = \"\"; option vendor-class-identifier \"PXEClient\"; } else { filename = \"\"; }'.$lstatements; #If proxydhcp daemon is enable, use it.
} else {
$lstatements = 'if option user-class-identifier = \"xNBA\" and option client-architecture = 00:00 { always-broadcast on; filename = \"http://'.$nxtsrv.'/tftpboot/xcat/xnba/nodes/'.$node.'\"; } else if option client-architecture = 00:07 or option client-architecture = 00:09 { filename = \"\"; option vendor-class-identifier \"PXEClient\"; } else if option client-architecture = 00:00 { filename = \"xcat/xnba.kpxe\"; } else { filename = \"\"; }'.$lstatements; #Only PXE compliant clients should ever receive xNBA
}
} elsif ($douefi and $chainent->{currstate} ne "boot" and $chainent->{currstate} ne "iscsiboot") {
$lstatements = 'if option user-class-identifier = \"xNBA\" and option client-architecture = 00:00 { always-broadcast on; filename = \"http://'.$nxtsrv.'/tftpboot/xcat/xnba/nodes/'.$node.'\"; } else if option user-class-identifier = \"xNBA\" and option client-architecture = 00:09 { filename = \"http://'.$nxtsrv.'/tftpboot/xcat/xnba/nodes/'.$node.'.uefi\"; } else if option client-architecture = 00:07 { filename = \"xcat/xnba.efi\"; } else if option client-architecture = 00:00 { filename = \"xcat/xnba.kpxe\"; } else { filename = \"\"; }'.$lstatements; #Only PXE compliant clients should ever receive xNBA
} else {
} else {
$lstatements = 'if option user-class-identifier = \"xNBA\" and option client-architecture = 00:00 { filename = \"http://'.$nxtsrv.'/tftpboot/xcat/xnba/nodes/'.$node.'\"; } else if option client-architecture = 00:00 { filename = \"xcat/xnba.kpxe\"; } else { filename = \"\"; }'.$lstatements; #Only PXE compliant clients should ever receive xNBA
}
}
}
} #TODO: warn when windows
} elsif ($nrent and $nrent->{netboot} and $nrent->{netboot} eq 'pxe' and $lstatements !~ /filename/) {

View File

@ -244,13 +244,15 @@ sub mkinstall
my %img_hash=();
my $winimagetab;
my $osimagetab;
my $winpepathcfg; # the configuration of winpepath for each node. the format is nodename(50)data(150)
my $dowinpecfg = 0;
unless (-r "$tftpdir/Boot/pxeboot.0" ) {
$callback->(
{error => [ "The Windows netboot image is not created, consult documentation on how to add Windows deployment support to xCAT"],errorcode=>[1]
});
return;
}
#unless (-r "$tftpdir/Boot/pxeboot.0" ) {
# $callback->(
# {error => [ "The Windows netboot image is not created, consult documentation on how to add Windows deployment support to xCAT"],errorcode=>[1]
# });
# return;
#}
my $xcatsslname=get_server_certname();
unless (-r "$installroot/xcat/ca.pem" and stat("/etc/xcat/cert/ca.pem")->mtime <= stat("$installroot/xcat/ca.pem")->mtime) {
mkpath("$installroot/xcat/");
@ -260,7 +262,13 @@ sub mkinstall
# get image attributes
my $osents = $ostab->getNodesAttribs(\@nodes, ['profile', 'os', 'arch', 'provmethod']);
# get the proxydhcp configuration
if (open (FILE, "</var/lib/xcat/proxydhcp.cfg")) {
$winpepathcfg = <FILE>;
close(FILE);
}
foreach $node (@nodes)
{
my $os;
@ -270,6 +278,7 @@ sub mkinstall
my $imagename; # set it if running of 'nodeset osimage=xxx'
my $partfile;
my $installto;
my $winpepath;
my $ent = $osents->{$node}->[0];
if ($ent and $ent->{provmethod} and ($ent->{provmethod} ne 'install') and ($ent->{provmethod} ne 'netboot') and ($ent->{provmethod} ne 'statelite')) {
@ -288,7 +297,7 @@ sub mkinstall
if (!$winimagetab) {
$winimagetab=xCAT::Table->new('winimage', -create=>1);
}
my $ref1 = $winimagetab->getAttribs({imagename => $imagename}, 'template', 'installto', 'partitionfile');
my $ref1 = $winimagetab->getAttribs({imagename => $imagename}, 'template', 'installto', 'partitionfile', 'winpepath');
if ($ref1) {
if ($ref1->{'template'}) {
$img_hash{$imagename}->{template}=$ref1->{'template'};
@ -299,6 +308,9 @@ sub mkinstall
if ($ref1->{'partitionfile'}) {
$img_hash{$imagename}->{partitionfile}=$ref1->{'partitionfile'};
}
if ($ref1->{'winpepath'}) {
$img_hash{$imagename}->{winpepath}=$ref1->{'winpepath'};
}
}
} else {
$callback->({error => ["The os image $imagename does not exists on the osimage table for $node"], errorcode => [1]});
@ -313,6 +325,7 @@ sub mkinstall
$partfile = $ph->{partitionfile};
$tmplfile = $ph->{template};
$installto = $ph->{installto};
$winpepath = $ph->{winpepath};
} else {
unless ($ent->{os} and $ent->{arch} and $ent->{profile})
{
@ -409,6 +422,36 @@ sub mkinstall
next;
}
# generate the winpe path configuration file for proxydhcp daemon
if ($winpepath) {
if ($winpepath =~ /^\//) {
$callback->({error =>["The winpepath should be a relative path to /tftpboot/"],errorcode => [1]});
return;
}
if ($winpepath !~ /\/$/) {
$winpepath .= '/';
}
}
my $nodename .= pack("a50", $node);
my $winpevalue .= pack("a150", $winpepath);
if ($winpepathcfg =~ /$nodename$winpevalue/) {
; # do nothing
} elsif ($winpepathcfg =~ /$nodename/) {
$winpepathcfg =~ s/$nodename.{150}/$nodename$winpevalue/;
$dowinpecfg = 1;
} else {
$winpepathcfg .= $nodename;
$winpepathcfg .= $winpevalue;
$dowinpecfg = 1;
}
#}
# copy bootmgr.exe from winpe path, this is shared by different winpes.
# if it cannot be shared between winpes, we must figure out a fix
if (! -r "$tftpdir/bootmgr.exe") {
copy("$tftpdir/$winpepath/Boot/bootmgr.exe", "$tftpdir/bootmgr.exe");
}
#Call the Template class to do substitution to produce an unattend.xml file in the autoinst dir
my $tmperr;
my @utilfiles = (
@ -440,17 +483,18 @@ sub mkinstall
# create the node-specific post script DEPRECATED, don't do
#mkpath "/install/postscripts/";
if (! -r "$tftpdir/Boot/pxeboot.0" ) {
if (! -r "$tftpdir/$winpepath/Boot/pxeboot.0" ) {
$callback->(
{error => [ "The Windows netboot image is not created, consult documentation on how to add Windows deployment support to xCAT"],errorcode=>[1]
});
return;
} elsif (-r $installroot."/$os/$arch/sources/install.wim") {
if ($arch =~ /x86/)
{
$bptab->setNodeAttribs(
$node,
{
kernel => "Boot/pxeboot.0",
kernel => "$winpepath"."Boot/pxeboot.0",
initrd => "",
kcmdline => ""
}
@ -496,6 +540,8 @@ sub mkinstall
$partcfg .= $1;
} elsif (/^\[uefi\](.*)/i) {
$partcfg .= "[UEFI]$1";
} elsif (/^\[installto\](.*)/i) {
$installto = $1;
} else {
$partcfg .= $_;
}
@ -577,6 +623,18 @@ sub mkinstall
# }
# }
}
# generate the winpe path configuration file for proxydhcp daemon
if ($dowinpecfg) {
open (FILE, ">/var/lib/xcat/proxydhcp.cfg");
print FILE $winpepathcfg;
close (FILE);
if (open (PDPID, "</var/run/xcat/proxydhcp.pid")) {
my $pdpid = <PDPID>;
kill 10, $pdpid;
}
}
}
sub getips { #TODO: all the possible ip addresses
my $node = shift;

View File

@ -73,7 +73,7 @@ Do Until srcfile.AtEndOfStream
if partuefi<>"" Then
fline = Replace(fline,"==DISKCONFIG==", partuefi)
else
fline = Replace(fline,"==DISKCONFIG==","<DiskID>" & instdrv & "<Disk></DiskID><WillWipeDisk>true</WillWipeDisk><CreatePartitions><CreatePartition><Order>1</Order><Type>EFI</Type><Size>260</Size></CreatePartition><CreatePartition><Order>2</Order><Type>MSR</Type><Size>128</Size></CreatePartition><CreatePartition><Order>3</Order><Type>Primary</Type><Extend>true</Extend></CreatePartition></CreatePartitions></Disk>")
fline = Replace(fline,"==DISKCONFIG==","<Disk><DiskID>" & instdrv & "</DiskID><WillWipeDisk>true</WillWipeDisk><CreatePartitions><CreatePartition><Order>1</Order><Type>EFI</Type><Size>260</Size></CreatePartition><CreatePartition><Order>2</Order><Type>MSR</Type><Size>128</Size></CreatePartition><CreatePartition><Order>3</Order><Type>Primary</Type><Extend>true</Extend></CreatePartition></CreatePartitions></Disk>")
end if
if instpart<>"0" Then
@ -87,7 +87,7 @@ Do Until srcfile.AtEndOfStream
if partbios<>"" Then
fline = Replace(fline,"==DISKCONFIG==", partbios)
else
fline = Replace(fline,"==DISKCONFIG==", "<DiskID>" & instdrv & "<Disk></DiskID><WillWipeDisk>true</WillWipeDisk><CreatePartitions><CreatePartition><Order>1</Order><Type>Primary</Type><Extend>true</Extend></CreatePartition></CreatePartitions></Disk>")
fline = Replace(fline,"==DISKCONFIG==", "<Disk><DiskID>" & instdrv & "</DiskID><WillWipeDisk>true</WillWipeDisk><CreatePartitions><CreatePartition><Order>1</Order><Type>Primary</Type><Extend>true</Extend></CreatePartition></CreatePartitions></Disk>")
end if
if instpart<>"0" Then