mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-10-30 19:02:27 +00:00 
			
		
		
		
	not sure what happended, fix the bad checkin 8f7633c9b5
				
					
				
			This commit is contained in:
		| @@ -0,0 +1,568 @@ | ||||
| #!/usr/bin/perl | ||||
| # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html | ||||
|  | ||||
| package xCAT::Usage; | ||||
| use Getopt::Long; | ||||
| use xCAT::Utils; | ||||
|  | ||||
| #------------------------------------------------------------------------------- | ||||
| =head1  xCAT::Usage | ||||
| =head2    Package Description | ||||
|   xCAT usage module. Some commands such as rpower have different implementations  | ||||
|   for different hardware. This module holds the usage string for these kind | ||||
|   of commands so that the usage can be referenced from different modules. | ||||
| =cut | ||||
| #------------------------------------------------------------------------------- | ||||
|  | ||||
|  | ||||
| my %usage = ( | ||||
|     "rnetboot" =>  | ||||
| "Usage: rnetboot <noderange> [-s net|hd] [-F] [-f] [-V|--verbose] [-m table.colum==expectedstatus] [-m table.colum==expectedstatus...] [-r <retrycount>] [-t <timeout>] | ||||
|        rnetboot [-h|--help|-v|--version] | ||||
|      zVM specific: | ||||
|        rnetboot <noderange> [ipl= address]", | ||||
|     "rpower" =>  | ||||
| "Usage: rpower <noderange> [--nodeps] [on|onstandby|off|suspend|reset|stat|state|boot] [-V|--verbose] [-m table.colum==expectedstatus][-m table.colum==expectedstatus...] [-r <retrycount>] [-t <timeout>] | ||||
|        rpower [-h|--help|-v|--version] | ||||
|      KVM Virtualization specific: | ||||
|        rpower <noderange> [boot] [ -c <path to iso> ] | ||||
|      PPC (with IVM or HMC) specific: | ||||
|        rpower <noderange> [--nodeps] [of] [-V|--verbose] | ||||
|      CEC (with HMC) specific: | ||||
|        rpower <noderange> [on|off|reset|boot|onstandby] | ||||
|      LPAR(with HMC) specific: | ||||
|        rpower <noderange> [on|off|reset|stat|state|boot|of|sms|softoff] | ||||
|      CEC(using Direct FSP Management) specific: | ||||
|        rpower <noderange> [on|onstandby|off|stat|state|resetsp] | ||||
|      Frame(using Direct FSP Management) specific: | ||||
|        rpower <noderange> [stat|state|rackstandby|exit_rackstandby|resetsp] | ||||
|      LPAR(using Direct FSP Management) specific: | ||||
|        rpower <noderange> [on|off|reset|stat|state|boot|of|sms] | ||||
|      Blade(using Direct FSP Management) specific: | ||||
|        rpower <noderange> [on|onstandby|off|cycle|state|sms] | ||||
|      Blade(using AMM) specific: | ||||
|        rpower <noderange> [cycle|softoff] [-V|--verbose] | ||||
|      zVM specific: | ||||
|        rpower noderange [on|off|reset|stat|softoff] | ||||
|      MIC specific: | ||||
|        rpower noderange [stat|state|on|off|reset|boot] | ||||
| ", | ||||
|     "rbeacon" =>  | ||||
| "Usage: rbeacon <noderange> [on|off|stat] [-V|--verbose] | ||||
|        rbeacon [-h|--help|-v|--version]", | ||||
|     "rvitals" =>  | ||||
| "Usage: | ||||
|   Common: | ||||
|       rvitals [-h|--help|-v|--version] | ||||
|   FSP/LPAR (with HMC) specific: | ||||
|       rvitals noderange {temp|voltage|lcds|all} | ||||
|   CEC/LPAR/Frame (using Direct FSP Management)specific: | ||||
|       rvitals noderange {rackenv|lcds|all} | ||||
|   MPA specific: | ||||
|       rvitals noderange {temp|voltage|wattage|fanspeed|power|leds|summary|all} | ||||
|   Blade specific: | ||||
|       rvitals noderange {temp|wattage|fanspeed|leds|summary|all} | ||||
|   BMC specific: | ||||
|       rvitals noderange {temp|voltage|wattage|fanspeed|power|leds|lcds|summary|all} | ||||
|   MIC specific: | ||||
|       rvitals noderange {thermal|all}", | ||||
|     "reventlog" =>  | ||||
| "Usage: reventlog <noderange> [all [-s]|clear|<number of entries to retrieve> [-s]] [-V|--verbose] | ||||
|        reventlog [-h|--help|-v|--version]", | ||||
|     "rinv" =>  | ||||
| "Usage:  | ||||
|     Common: | ||||
|        rinv <noderange> [all|model|serial] [-V|--verbose] | ||||
|        rinv [-h|--help|-v|--version] | ||||
|     BMC specific: | ||||
|        rinv <noderange> [mprom|deviceid|uuid|guid|vpd [-t]|all [-t]] | ||||
|     MPA specific: | ||||
|        rinv <noderange> [firm|bios|diag|mprom|sprom|mparom|mac|mtm [-t]]  | ||||
|     PPC specific(with HMC): | ||||
|        rinv <noderange> [all|bus|config|serial|model|firm [-t]] | ||||
|     PPC specific(using Direct FSP Management): | ||||
|        rinv <noderange> [firm] | ||||
|        rinv <noderange> [deconfig [-x]] | ||||
|     Blade specific: | ||||
|        rinv <noderange> [all|serial|mac|bios|diag|mprom|mparom|firm|mtm [-t]] | ||||
|     IBM Flex System Compute Node specific: | ||||
|        rinv <noderange> [firm] | ||||
|     VMware specific: | ||||
|        rinv <noderange> | ||||
|     zVM specific: | ||||
|        rinv noderange [all|config] | ||||
|     MIC specific: | ||||
|        rinv noderange [system|ver|board|core|gddr|all]", | ||||
|     "rsetboot" =>  | ||||
| "Usage: rsetboot <noderange> [net|hd|cd|floppy|def|stat] [-V|--verbose] | ||||
|        rsetboot [-h|--help|-v|--version]", | ||||
|     "rbootseq" =>  | ||||
| "Usage:  | ||||
|        Common: | ||||
|            rbootseq [-h|--help|-v|--version|-V|--verbose] | ||||
|        Blade specific: | ||||
|            rbootseq <noderange> [hd0|hd1|hd2|hd3|net|iscsi|usbflash|floppy|none],... | ||||
|        PPC (using Direct FSP Management) specific: | ||||
|            rbootseq <noderange> [hfi|net]", | ||||
|     "rscan" =>  | ||||
| "Usage: rscan <noderange> [-u][-w][-x|-z] [-V|--verbose] | ||||
|        rscan [-h|--help|-v|--version]", | ||||
|     "rspconfig" =>  | ||||
| "Usage:  | ||||
|    Common: | ||||
|        rspconfig [-h|--help|-v|--version|-V|--verbose] | ||||
|    BMC/MPA Common: | ||||
|        rspconfig <noderange> [snmpdest|alert|community] [-V|--verbose] | ||||
|        rspconfig <noderange> [snmpdest=<dest ip address>|alert=<on|off|en|dis|enable|disable>|community=<string>] | ||||
|    BMC specific: | ||||
|        rspconfig <noderange> [ip|netmask|gateway|backupgateway|garp] | ||||
|        rspconfig <noderange> [garp=<number of 1/2 second>] | ||||
|    iDataplex specific: | ||||
|        rspconfig <noderange> [thermprofile] | ||||
|        rspconfig <noderange> [thermprofile=<two digit number from chassis>] | ||||
|    MPA specific: | ||||
|        rspconfig <noderange>  [sshcfg|snmpcfg|pd1|pd2|network|swnet|ntp|textid|frame] | ||||
|        rspconfig <singlenode> [textid=name] | ||||
|        rspconfig <singlenode> [frame=number] | ||||
|        rspconfig <singlenode> [USERID=passwd] [updateBMC=<y|n>] | ||||
|        rspconfig <noderange>  [sshcfg=<enable|disable>| | ||||
|            snmpcfg=<enable|disable>|                              | ||||
|            pd1=<nonred|redwoperf|redwperf>| | ||||
|            pd2=<nonred|redwoperf|redwperf>| | ||||
|            network=<*|[ip],[host],[gateway],[netmask]>| | ||||
|            swnet=<[ip],[gateway],[netmask]>| | ||||
|            textid=<*>| | ||||
|            frame=<*>| | ||||
|            ntp=<[ntp],[ip],[frequency],[v3]> | ||||
|    FSP/CEC (using ASM Interface) Specific: | ||||
|        rspconfig <noderange> [autopower|iocap|decfg|memdecfg|procdecfg|time|date|spdump|sysdump|network|hostname] | ||||
|        rspconfig <noderange> autopower=<enable|disable>| | ||||
|            iocap=<enable|disable>| | ||||
|            decfg=<enable|disable>:<policy name>,...| | ||||
|            memdecfg=<configure|deconfigure>:<processing unit>:<bank|unit>:<bank/unit number>:id,...| | ||||
|            procdecfg=<configure|deconfigure>:<processing unit>:id,...| | ||||
|            date=<mm-dd-yyyy>| | ||||
|            time=<hh:mm:ss>| | ||||
|            network=<*|[ip],[host],[gateway],[netmask]>| | ||||
|            HMC_passwd=<currentpasswd,newpasswd>| | ||||
|            admin_passwd=<currentpasswd,newpasswd>| | ||||
|            general_passwd=<currentpasswd,newpasswd>| | ||||
|            *_passwd=<currentpasswd,newpasswd>| | ||||
|            hostname=<*|hostname> | ||||
|    FSP/CEC (using Direct FSP Management) Specific: | ||||
|        rspconfig <noderange> HMC_passwd=<currentpasswd,newpasswd> | ||||
|        rspconfig <noderange> admin_passwd=<currentpasswd,newpasswd> | ||||
|        rspconfig <noderange> general_passwd=<currentpasswd,newpasswd> | ||||
|        rspconfig <noderange> *_passwd=<currentpasswd,newpasswd> | ||||
|        rspconfig <noderange> [sysname] | ||||
|        rspconfig <noderange> [sysname=<*|name>] | ||||
|        rspconfig <noderange> [pending_power_on_side] | ||||
|        rspconfig <noderange> [pending_power_on_side=<temp|perm>] | ||||
|        rspconfig <noderange> [cec_off_policy] | ||||
|        rspconfig <noderange> [cec_off_policy=<poweroff|stayon>] | ||||
|        rspconfig <noderange> [huge_page] | ||||
|        rspconfig <noderange> [huge_page=<NUM>] | ||||
|        rspconfig <noderange> [BSR] | ||||
|        rspconfig <noderange> [setup_failover] | ||||
|        rspconfig <noderange> [setup_failover=<enable|disable>] | ||||
|        rspconfig <noderange> [force_failover] | ||||
|        rspconfig <noderange> --resetnet | ||||
|    BPA/Frame (using Direct FSP Management)specific: | ||||
|        rspconfig <noderange> HMC_passwd=<currentpasswd,newpasswd> | ||||
|        rspconfig <noderange> admin_passwd=<currentpasswd,newpasswd> | ||||
|        rspconfig <noderange> general_passwd=<currentpasswd,newpasswd> | ||||
|        rspconfig <noderange> *_passwd=<currentpasswd,newpasswd> | ||||
|        rspconfig <noderange> [frame] | ||||
|        rspconfig <noderange> frame=<*|frame> | ||||
|        rspconfig <noderange> [sysname] | ||||
|        rspconfig <noderange> [sysname=<*|name>] | ||||
|        rspconfig <noderange> [pending_power_on_side] | ||||
|        rspconfig <noderange> [pending_power_on_side=<temp|perm>] | ||||
|        rspconfig <noderange> --resetnet | ||||
|    HMC specific: | ||||
|        rspconfig <noderange>  [sshcfg] | ||||
|        rspconfig <noderange>  [sshcfg=<enable|disable>] | ||||
|    CEC|Frame(using ASM)Specific: | ||||
|        rspconfig <noderange>  [dev|celogin1] | ||||
|        rspconfig <noderange>  [dev=<enable|disable>]| | ||||
|        rspconfig <noderange>  [celogin1=<enable|disable>] | ||||
|     ", | ||||
|     "getmacs" =>  | ||||
| "Usage:  | ||||
|    Common: | ||||
|        getmacs [-h|--help|-v|--version] | ||||
|    PPC specific: | ||||
|        getmacs <noderange> [-F filter]  | ||||
|        getmacs <noderange> [-M] | ||||
|        getmacs <noderange> [-V| --verbose] [-f] [-d] [--arp] | [-D {[-o] [-S server] [-G gateway] [-C client] | [--noping]}] | ||||
|    blade specific: | ||||
|        getmacs <noderange> [-V| --verbose] [-d] [--arp] [-i ethN|enN] | ||||
| ", | ||||
|     "mkvm" =>  | ||||
| "Usage: | ||||
|     Common: | ||||
|        mkvm [-h|--help|-v|--version] | ||||
|     For PPC(with HMC) specific: | ||||
|        mkvm noderange -i id -l singlenode [-V|--verbose] | ||||
|        mkvm noderange -c destcec -p profile [-V|--verbose] | ||||
|        mkvm noderange --full [-V|--verbose] | ||||
|     PPC (using Direct FSP Management) specific: | ||||
|        mkvm noderange [--full] | ||||
|        mkvm noderange [vmcpus=min/req/max] [vmmemory=min/req/max] | ||||
|                       [vmphyslots=drc_index1,drc_index2...] [vmothersetting=hugepage:N,bsr:N] | ||||
|                       [vmnics=vlan1,vlan2] [vmstorage=<N|viosnode:slotid>] [--vios] | ||||
|     For KVM | ||||
|        mkvm noderange -m|--master mastername -s|--size disksize -f|--force | ||||
|     For zVM | ||||
|        mkvm noderange directory_entry_file_path | ||||
|        mkvm noderange source_virtual_machine pool=disk_pool pw=multi_password", | ||||
|     "lsvm" =>  | ||||
| "Usage: | ||||
|    Common: | ||||
|        lsvm <noderange> [-V|--verbose] | ||||
|        lsvm [-h|--help|-v|--version] | ||||
|    PPC (with HMC) specific: | ||||
|        lsvm <noderange> [-a|--all] | ||||
|    PPC (using Direct FSP Management) specific: | ||||
|        lsvm <noderange> [-l|--long] --p775 | ||||
|        lsvm <noderange>  | ||||
|    zVM specific: | ||||
|        lsvm noderange | ||||
|        lsvm noderange --getnetworknames | ||||
|        lsvm noderange --getnetwork network_name | ||||
|        lsvm noderange --diskpoolnames | ||||
|        lsvm noderange --diskpool pool_name", | ||||
|     "chvm" =>  | ||||
| "Usage: | ||||
|    Common: | ||||
|        chvm [-h|--help|-v|--version] | ||||
|    PPC (with HMC) specific: | ||||
|        chvm <noderange> [-p profile][-V|--verbose]  | ||||
|        chvm <noderange> <attr>=<val> [<attr>=<val>...] | ||||
|    PPC (using Direct FSP Management) specific: | ||||
|        chvm <noderange> --p775 [-p <profile>] | ||||
|        chvm <noderange> --p775 -i <id> [-m <memory_interleaving>] -r <partition_rule> | ||||
|        chvm <noderange> [lparname=<*|name>] | ||||
|        chvm <noderange> [vmcpus=min/req/max] [vmmemory=min/req/max] | ||||
|                         [vmothersetting=hugepage:N,bsr:N] | ||||
|                         [add_physlots=drc_index1,drc_index2...]  | ||||
|                         [add_vmnics=vlan1,vlan2] [add_vmstorage=<N|viosnode:slotid>] [--vios] | ||||
|        chvm <noderange> [del_physlots=drc_index1,drc_index2...] | ||||
|        chvm <noderange> [del_vadapter=slotid] | ||||
|    VMware specific: | ||||
|        chvm <noderange> [-a size][-d disk][-p disk][--resize disk=size][--cpus count][--mem memory] | ||||
|    zVM specific: | ||||
|        chvm noderange [--add3390 disk_pool device_address cylinders mode read_password write_password multi_password] | ||||
|        chvm noderange [--add3390active device_address mode] | ||||
|        chvm noderange [--add9336 disk_pool virtual_device block_size mode blocks read_password write_password multi_password] | ||||
|        chvm noderange [--adddisk2pool function region volume group] | ||||
|        chvm noderange [--addnic address type device_count] | ||||
|        chvm noderange [--addprocessor address] | ||||
|        chvm noderange [--addprocessoractive address type] | ||||
|        chvm noderange [--addvdisk userID] device_address size] | ||||
|        chvm noderange [--connectnic2guestlan address lan owner] | ||||
|        chvm noderange [--connectnic2vswitch address vswitch] | ||||
|        chvm noderange [--copydisk target_address source_node source_address] | ||||
|        chvm noderange [--dedicatedevice virtual_device real_device mode] | ||||
|        chvm noderange [--deleteipl] | ||||
|        chvm noderange [--formatdisk disk_address multi_password] | ||||
|        chvm noderange [--disconnectnic address] | ||||
|        chvm noderange [--grantvswitch VSwitch] | ||||
|        chvm noderange [--removedisk virtual_device] | ||||
|        chvm noderange [--resetsmapi] | ||||
|        chvm noderange [--removediskfrompool function region group] | ||||
|        chvm noderange [--removenic address] | ||||
|        chvm noderange [--removeprocessor address] | ||||
|        chvm noderange [--replacevs directory_entry] | ||||
|        chvm noderange [--setipl ipl_target load_parms parms] | ||||
|        chvm noderange [--setpassword password]", | ||||
|     "rmvm" =>  | ||||
| "Usage: rmvm <noderange> [--service][-V|--verbose]  | ||||
|        rmvm [-h|--help|-v|--version], | ||||
|        rmvm [-p] [-f] | ||||
|        PPC (using Direct FSP Management) specific: | ||||
|        rmvm <noderange>", | ||||
|     "lsslp" => | ||||
| "Usage: lsslp [-h|--help|-v|--version] | ||||
|        lsslp [<noderange>][-V|--verbose][-i ip[,ip..]][-w][-r|-x|-z][-n][-I][-s FRAME|CEC|MM|IVM|RSA|HMC|CMM|IMM2|FSP] | ||||
|              [-u] [--range IPranges][-t tries][--vpdtable][-C counts][-T timeout]", | ||||
|     "switchdiscover" => | ||||
| "Usage: switchdiscover [-h|--help|-v|--version] | ||||
|        switchdiscover [<noderange>][-V|--verbose][-i adpt[,adpt..]][-w][-r|-x|-z][-n][-s scan_methods]", | ||||
|   "rflash" => | ||||
| "Usage:  | ||||
|     rflash [ -h|--help|-v|--version] | ||||
|     PPC (with HMC) specific: | ||||
| 	rflash <noderange> -p <rpm_directory> [--activate concurrent | disruptive][-V|--verbose]  | ||||
| 	rflash <noderange> [--commit | --recover] [-V|--verbose] | ||||
|     PPC (using Direct FSP Management) specific: | ||||
| 	rflash <noderange> -p <rpm_directory> --activate <disruptive|deferred> [-d <data_directory>] | ||||
| 	rflash <noderange> [--commit | --recover] [-V|--verbose] | ||||
|         rflash <noderange> [--bpa_acdl]", | ||||
|     "mkhwconn" => | ||||
| "Usage: | ||||
|     mkhwconn [-h|--help] | ||||
|      | ||||
|     PPC (with HMC) specific: | ||||
|     mkhwconn noderange -t [--bind] [-V|--verbose] | ||||
|     mkhwconn noderange -p single_hmc [-P HMC passwd] [-V|--verbose] | ||||
|      | ||||
|     PPC (using Direct FSP Management) specific: | ||||
|     mkhwconn noderange -t [-T tooltype] [--port port_value] | ||||
|     mkhwconn noderange -s [hmcnode] [-P HMC passwd] [-V|--verbose]", | ||||
|     "rmhwconn" => | ||||
| "Usage: | ||||
|     rmhwconn [-h|--help] | ||||
|      | ||||
|     PPC (with HMC) specific: | ||||
|     rmhwconn noderange [-V|--verbose] | ||||
|      | ||||
|     PPC (using Direct FSP Management) specific: | ||||
|     rmhwconn noderange [-T tooltype] | ||||
|     rmhwconn noderange -s", | ||||
|     "lshwconn" => | ||||
| "Usage: | ||||
|     lshwconn [-h|--help] | ||||
|      | ||||
|     PPC (with HMC) specific: | ||||
|     lshwconn noderange [-V|--verbose] | ||||
|      | ||||
|     PPC (using Direct FSP Management) specific: | ||||
|     lshwconn noderange [-T tooltype] | ||||
|     lshwconn noderange -s", | ||||
|     "renergy" => | ||||
| "Usage: | ||||
|     renergy [-h | --help]  | ||||
|     renergy [-v | --version]  | ||||
|  | ||||
|     Power 6 server specific : | ||||
|       renergy noderange [-V] { all | { [savingstatus] [cappingstatus] [cappingmaxmin] [cappingvalue] [cappingsoftmin] [averageAC] [averageDC] [ambienttemp] [exhausttemp] [CPUspeed] } } | ||||
|       renergy noderange [-V] { {savingstatus}={on | off} | {cappingstatus}={on | off} | {cappingwatt}=watt | {cappingperc}=percentage }  | ||||
|  | ||||
|     Power 7 server specific : | ||||
|       renergy noderange [-V] { all | { [savingstatus] [dsavingstatus] [cappingstatus] [cappingmaxmin] [cappingvalue] [cappingsoftmin] [averageAC] [averageDC] [ambienttemp] [exhausttemp] [CPUspeed] [syssbpower] [sysIPLtime] [fsavingstatus] [ffoMin] [ffoVmin] [ffoTurbo] [ffoNorm] [ffovalue] } } | ||||
|       renergy noderange [-V] { {savingstatus}={on | off} | {dsavingstatus}={on-norm | on-maxp | off} | {fsavingstatus}={on | off} | {ffovalue}=MHZ | {cappingstatus}={on | off} | {cappingwatt}=watt | {cappingperc}=percentage } | ||||
|  | ||||
|     Power 8 server specific : | ||||
|       renergy noderange [-V] { all | [savingstatus] [dsavingstatus] [averageAC] [averageAChistory] [averageDC] [averageDChistory] [ambienttemp] [ambienttemphistory] [exhausttemp] [exhausttemphistory] [fanspeed] [fanspeedhistory] [CPUspeed] [CPUspeedhistory] [syssbpower] [sysIPLtime] [fsavingstatus] [ffoMin] [ffoVmin] [ffoTurbo] [ffoNorm] [ffovalue]} | ||||
|       renergy noderange [-V] { savingstatus={on | off} | dsavingstatus={on-norm | on-maxp | off} | fsavingstatus={on | off} | ffovalue=MHZ } | ||||
|  | ||||
|     BladeCenter specific : | ||||
|       For Management Modules: | ||||
|         renergy noderange [-V] { all | pd1all | pd2all | [pd1status] [pd2status] [pd1policy] [pd2policy] [pd1powermodule1] [pd1powermodule2] [pd2powermodule1] [pd2powermodule2] [pd1avaiablepower] [pd2avaiablepower] [pd1reservedpower] [pd2reservedpower] [pd1remainpower] [pd2remainpower] [pd1inusedpower] [pd2inusedpower] [availableDC] [averageAC] [thermaloutput] [ambienttemp] [mmtemp] } | ||||
|       For a blade server nodes: | ||||
|         renergy noderange [-V] { all | [averageDC] [capability] [cappingvalue] [CPUspeed] [maxCPUspeed] [savingstatus] [dsavingstatus] } | ||||
|         renergy noderange [-V] { savingstatus={on | off} | dsavingstatus={on-norm | on-maxp | off} } | ||||
|   | ||||
|     Flex specific : | ||||
|       For Flex Management Modules: | ||||
|         renergy noderange [-V] { all | [powerstatus] [powerpolicy] [powermodule] [avaiablepower] [reservedpower] [remainpower] [inusedpower] [availableDC] [averageAC] [thermaloutput] [ambienttemp] [mmtemp] } | ||||
|   | ||||
|       For Flex node (power and x86): | ||||
|         renergy noderange [-V] { all | [averageDC] [capability] [cappingvalue] [cappingmaxmin] [cappingmax] [cappingmin] [cappingGmin] [CPUspeed] [maxCPUspeed] [savingstatus] [dsavingstatus] } | ||||
|         renergy noderange [-V] { cappingstatus={on | off} | cappingwatt=watt | cappingperc=percentage | savingstatus={on | off} | dsavingstatus={on-norm | on-maxp | off} } | ||||
|   | ||||
|     iDataPlex specific : | ||||
|       renergy noderange [-V] [ { cappingmaxmin | cappingmax | cappingmin } ] [cappingstatus] [cappingvalue] [relhistogram] | ||||
|       renergy noderange [-V] { cappingstatus={on | enable | off | disable} | {cappingwatt|cappingvalue}=watt }", | ||||
|   "updatenode" => | ||||
| "Usage: | ||||
|     updatenode [-h|--help|-v|--version | -g|--genmypost] | ||||
|     or | ||||
|     updatenode <noderange> [-V|--verbose] [-k|--security] [-s|--sn] [-t <timeout>] | ||||
|     or | ||||
|     updatenode <noderange> [-V|--verbose] [-F|--sync | -f|--snsync] [-l|--user[username]] [--fanout=[fanout value]] [-S|--sw] [-t <timeout>] | ||||
|         [-P|--scripts [script1,script2,...]] [-s|--sn]  | ||||
|         [-A|--updateallsw] [-c|--cmdlineonly] [-d alt_source_dir] | ||||
|         [attr=val [attr=val...]] | ||||
|     or | ||||
|     updatenode <noderange> [-V|--verbose] [script1,script2,...] | ||||
|  | ||||
| Options: | ||||
|     <noderange> A list of nodes or groups. | ||||
|  | ||||
|     [-k|--security] Update the security keys and certificates for the  | ||||
|         target nodes. | ||||
|  | ||||
|     [-F|--sync] Perform File Syncing. | ||||
|  | ||||
|     [--fanout]  Allows you to assign the fanout value for the command.  | ||||
|         See xdsh/xdcp fanout parameter in the man page. | ||||
|  | ||||
|     [-f|--snsync] Performs File Syncing to the service nodes that service  | ||||
|         the nodes in the noderange. | ||||
|  | ||||
|     [-g|--genmypost] Will generate a new mypostscript file for the   | ||||
|         the nodes in the noderange, if site precreatemypostscripts is 1 or YES. | ||||
|  | ||||
|     [-l|--user] User name to run the updatenode command.  It overrides the | ||||
|         current user which is the default. | ||||
|  | ||||
|     [-S|--sw] Perform Software Maintenance. | ||||
|  | ||||
|     [-P|--scripts] Execute postscripts listed in the postscripts table or  | ||||
|         parameters. | ||||
|  | ||||
|     [-c|--cmdlineonly] Only use AIX software maintenance information  | ||||
|         provided on the command line. (AIX only) | ||||
|  | ||||
|     [-s|--sn] Set the server information stored on the nodes. | ||||
|  | ||||
|     [-t|--timeout] Time out in seconds to allow the command to run. Default is no timeout, | ||||
|         except for updatenode -k which has a 10 second default timeout. | ||||
|  | ||||
|     [-A|--updateallsw] Install or update all software contained in the source  | ||||
|         directory. (AIX only) | ||||
|  | ||||
|     [-d <alt_source_dir>] Used to indicate a source directory other than | ||||
|         the standard lpp_source directory specified in the xCAT osimage  | ||||
|         definition.  (AIX only) | ||||
|  | ||||
|     [script1,script2,...] A comma separated list of postscript names.  | ||||
|         If omitted, all the post scripts defined for the nodes will be run. | ||||
|  | ||||
|     [attr=val [attr=val...]]  Specifies one or more 'attribute equals value'  | ||||
|         pairs, separated by spaces. (AIX only)", | ||||
|   "lsflexnode" => | ||||
| "Usage: | ||||
|     lsflexnode [-h|--help|-v|--version] | ||||
|     lsflexnode <noderange>", | ||||
|   "mkflexnode" => | ||||
| "Usage: | ||||
|     mkflexnode [-h|--help|-v|--version] | ||||
|     mkflexnode <noderange>", | ||||
|   "nodeset" => | ||||
| "Usage: | ||||
|    Common: | ||||
|       nodeset [-h|--help|-v|--version] | ||||
|       nodeset <noderange> [shell|boot|runcmd=bmcsetup|iscsiboot|osimage[=<imagename>]|offline]", | ||||
|   "rmflexnode" => | ||||
| "Usage: | ||||
|     rmflexnode [-h|--help|-v|--version] | ||||
|     rmflexnode <noderange>", | ||||
|   "lsve" => | ||||
| "Usage: | ||||
|     lsve [-t type] [-m manager] [-o object] | ||||
|       -t: dc - 'Data Center', cl - 'Cluster', sd - 'Storage Domain', nw - 'Network', tpl -'Template' | ||||
|       -m: FQDN (Fully Qualified Domain Name) of the rhev manager | ||||
|       -o: Target object to display", | ||||
|  "cfgve" => | ||||
| "Usage: | ||||
|     cfgve -t dc -m manager -o object [-c -k nfs|localfs | -r] | ||||
|     cfgve -t cl -m manager -o object [-c -p cpu type | -r -f] | ||||
|     cfgve -t sd -m manager -o object [-c | -g | -s | -a | -b | -r -f] | ||||
|       -t: sd - 'Storage Domain', nw - 'Network', tpl -'Template' | ||||
|       -m: FQDN (Fully Qualified Domain Name) of the rhev manager | ||||
|       -o: Target object to configure | ||||
|     cfgve -t nw -m manager -o object [-c -d data center -n vlan ID | -a -l cluster| -b | -r] | ||||
|     cfgve -t tpl -m manager -o object [-r]", | ||||
|  "chhypervisor" => | ||||
| "Usage: | ||||
|     chhypervisor noderange [-a | -n | -p | -e | -d | -h]", | ||||
|  "rmhypervisor" => | ||||
| "Usage: | ||||
|     rmhypervisor noderange [-f | -h]", | ||||
|  "clonevm" => | ||||
| "Usage: | ||||
|     clonevm noderange [-t createmaster -f | -b basemaster -d | -h]", | ||||
| ); | ||||
| my $vers = xCAT::Utils->Version(); | ||||
| my %version = ( | ||||
|     "rnetboot" => "$vers", | ||||
|     "rpower" => "$vers", | ||||
|     "rbeacon" => "$vers", | ||||
|     "rvitals" => "$vers", | ||||
|     "reventlog" => "$vers", | ||||
|     "rinv" => "$vers", | ||||
|     "rsetboot" => "$vers", | ||||
|     "rbootseq" => "$vers", | ||||
|     "rscan" => "$vers", | ||||
|     "rspconfig" => "$vers", | ||||
|     "getmacs" => "$vers", | ||||
|     "mkvm" => "$vers", | ||||
|     "lsvm" => "$vers", | ||||
|     "chvm" => "$vers", | ||||
|     "rmvm" => "$vers", | ||||
|     "lsslp" => "$vers", | ||||
|     "switchdiscover" => "$vers", | ||||
|     "rflash" => "$vers", | ||||
|     "renergy" => "$vers", | ||||
|     "lsflexnode" => "$vers", | ||||
|     "mkflexnode" => "$vers", | ||||
|     "rmflexnode" => "$vers", | ||||
|     "nodeset" => "$vers", | ||||
|     "lsve" => "$vers", | ||||
|     "cfgve" => "$vers", | ||||
|     "chhypervisor" => "$vers", | ||||
|     "rmhypervisor" => "$vers", | ||||
|     "clonevm" => "$vers", | ||||
| ); | ||||
|  | ||||
| #-------------------------------------------------------------------------------- | ||||
| =head3   getUsage | ||||
|       It returns the usage string for the given command. | ||||
|     Arguments: | ||||
|         command | ||||
|     Returns: | ||||
|         the usage string for the command. | ||||
| =cut | ||||
| #------------------------------------------------------------------------------- | ||||
| sub getUsage { | ||||
|   my ($class, $command)=@_; | ||||
|   if (exists($usage{$command})) { return $usage{$command};}   | ||||
|   else { return "Usage for command $command cannot be found\n"; } | ||||
| } | ||||
|  | ||||
| #-------------------------------------------------------------------------------- | ||||
| =head3   getVersion | ||||
|       It returns the version string for the given command. | ||||
|     Arguments: | ||||
|         command | ||||
|     Returns: | ||||
|         the version string for the command. | ||||
| =cut | ||||
| #------------------------------------------------------------------------------- | ||||
| sub getVersion { | ||||
|   my ($class, $command)=@_; | ||||
|   if (exists($version{$command})) { return $version{$command};}   | ||||
|   else { return "Version string for command $command cannot be found\n"; } | ||||
| } | ||||
|  | ||||
| #-------------------------------------------------------------------------------- | ||||
| =head3   parseCommand | ||||
|       This function parses the given command to see if the usage or version string | ||||
|       need to be returned.  | ||||
|     Arguments: | ||||
|         command | ||||
|         arguments | ||||
|     Returns: | ||||
|         the usage or the version string for the command. The caller need to display the | ||||
|            string and then exit. | ||||
|         none, if no usage or version strings are needed. The caller can keep going. | ||||
| =cut | ||||
| #------------------------------------------------------------------------------- | ||||
| sub parseCommand { | ||||
|   my $command=shift; | ||||
|   if ($command =~ /xCAT::Usage/) { $command=shift; } | ||||
|   my @exargs=@_; | ||||
|    | ||||
|   @ARGV=@exargs; | ||||
|  | ||||
|   #print "command=$command, args=@exargs, ARGV=@ARGV\n"; | ||||
|  | ||||
|   Getopt::Long::Configure('pass_through','no_ignore_case'); | ||||
|  | ||||
|   # parse the options | ||||
|   if(!GetOptions( | ||||
|       'h|help'     => \$::HELP, | ||||
|       'v|version'  => \$::VERSION)) { | ||||
|      | ||||
|     return ""; | ||||
|   } | ||||
|  | ||||
|   if ($::HELP) { return xCAT::Usage->getUsage($command); } | ||||
|   if ($::VERSION) { return xCAT::Usage->getVersion($command); } | ||||
|  | ||||
|   return ""; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,454 @@ | ||||
| #!/usr/bin/perl | ||||
| BEGIN | ||||
| { | ||||
|     $::XCATROOT = | ||||
|         $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} | ||||
|       : -d '/opt/xcat'   ? '/opt/xcat' | ||||
|       : '/usr'; | ||||
| } | ||||
| use lib "$::XCATROOT/lib/perl"; | ||||
| use strict; | ||||
|  | ||||
| use Getopt::Long; | ||||
| require xCAT::MsgUtils; | ||||
| require xCAT::DSHCLI; | ||||
| require xCAT::Client; | ||||
|  | ||||
| use xCAT::Utils; | ||||
| use xCAT::TableUtils; | ||||
| use File::Basename; | ||||
|  | ||||
| $::XCATROOT = "/opt/xcat"; | ||||
| my $os = ""; | ||||
| my $profile = ""; | ||||
| my $interface = ""; | ||||
| my $version; | ||||
| my $drivers = ""; | ||||
| my $otherInterfaces = ""; | ||||
| my $kernel = ""; | ||||
| my @oses; # available OSes. | ||||
| my @profiles; # available profiles | ||||
| my $profDir; # root where you do ./genimage from | ||||
| my $help; | ||||
| my $match = 0; | ||||
| my $imagename; | ||||
| my $arch; | ||||
| my $permission; | ||||
| my $rootlimit; | ||||
| my $tmplimit; | ||||
| my $krpmver; | ||||
| my $kerneldir; | ||||
| my $mode; | ||||
| my $interactive; | ||||
| my $onlyinitrd; | ||||
| my $dryrun; | ||||
| my $ignorekernelchk; | ||||
| my $noupdate; | ||||
| #----------------------------------------------------------------------------- | ||||
|  | ||||
| =head3 print_usage   - usage message | ||||
|  | ||||
| =cut | ||||
|  | ||||
| #----------------------------------------------------------------------------- | ||||
| sub print_usage | ||||
| { | ||||
|     print "Usage:\n"; | ||||
|     print "    genimage\n\n"; | ||||
|     print "    genimage --dryrun\n\n"; | ||||
|     print '    genimage [-o <osver>] [-a <arch>] [-p <profile>] [-i <nodebootif>] [-n <nodenetdrivers>] [--onlyinitrd] [-r <otherifaces>] [-k <kernelver>] [-g <krpmver>] [-m statelite] [-l rootlimitsize] [-t tmplimitsize] [--permission <permission>] [--interactive] [--dryrun] [--noupdate] <imagename>'."\n\n"; | ||||
|     print "      --permission is used for statelite only\n"; | ||||
|     print "      -g is used for SLES only\n\n"; | ||||
|     print "      -m is used for urbuntu, debian and fedora12 only\n\n"; | ||||
|     print "Examples:\n"; | ||||
|     print "    genimage\n"; | ||||
|     print "    genimage --interactive\n"; | ||||
|     print "    genimage -i eth0 -n tg3 --interactive myimagename\n"; | ||||
|     print "    genimage myimagename\n"; | ||||
| } | ||||
|  | ||||
| if (!GetOptions( | ||||
| 	 'a=s' => \$arch, | ||||
| 	 'p=s' => \$profile, | ||||
| 	 'o=s' => \$os, | ||||
| 	 'n=s' => \$drivers, | ||||
| 	 'i=s' => \$interface, | ||||
| 	 'r=s' => \$otherInterfaces, | ||||
| 	 'l=s' => \$rootlimit, | ||||
| 	 't=s' => \$tmplimit, | ||||
| 	 'k=s' => \$kernel, | ||||
| 	 'g=s' => \$krpmver, | ||||
| 	 'm=s' => \$mode, | ||||
| 	 'permission=s' => \$permission, | ||||
| 	 'kerneldir=s' => \$kerneldir,  | ||||
|          'interactive' => \$interactive,   | ||||
|          'onlyinitrd' => \$onlyinitrd,  | ||||
|          'dryrun' => \$dryrun, | ||||
| 	 'ignorekernelchk' => \$ignorekernelchk, | ||||
| 	 'noupdate' => \$noupdate, | ||||
| 	 'h|help' => \$help, | ||||
| 	 'v|version' => \$version, | ||||
| )) { | ||||
|    &print_usage; | ||||
|    exit 1; | ||||
| } | ||||
|  | ||||
| if($help){ | ||||
|     &print_usage; | ||||
|     exit 0; | ||||
| } | ||||
|  | ||||
| if ($version){ | ||||
|     my $version = xCAT::Utils->Version(); | ||||
|     xCAT::MsgUtils->message("N", $version); | ||||
|     exit 0; | ||||
|  | ||||
| } | ||||
| if (@ARGV > 0) { | ||||
|     $imagename=$ARGV[0]; | ||||
| } | ||||
|  | ||||
| if ((!$imagename) && (!$profile) && (!$os) && (!$arch)) { | ||||
|     my $tmpimgs=`lsdef -t osimage -w provmethod=~'/statelite|netboot/' |cut -d' ' -f1`; | ||||
|     if ($? == 0) { | ||||
| 	if (($tmpimgs) && ($tmpimgs !~ /^Could/)) { #Could is returned when the osimage table is empty | ||||
| 	    my @images=split('\n', $tmpimgs); | ||||
| 	    print "Do you want to re-generate an existing image from the osimage table? "; | ||||
| 	    print "[y/n] "; | ||||
| 	    my $conf = <stdin>; | ||||
| 	    chomp($conf); | ||||
| 	    if($conf ne "" && $conf !~/N|n|[Nn][Oo]/) { | ||||
| 		$match = 0; | ||||
| 		while(1){ | ||||
| 		    print "Available images: \n"; | ||||
| 		    foreach(sort @images){ | ||||
| 			print  "   $_\n"; | ||||
| 		    }  | ||||
| 		    # default is the first image  | ||||
| 		    print "Which image do you want to re-generate? ["; | ||||
| 		    print $images[0]; | ||||
| 		    print "] "; | ||||
| 		     | ||||
| 		    my $img = <stdin>; | ||||
| 		    chomp($img); | ||||
| 		    if($img eq ""){ | ||||
| 			$imagename = $images[0]; | ||||
| 			last; | ||||
| 		    } | ||||
| 		    foreach(@images){ | ||||
| 			if($img eq $_){ | ||||
| 			    $imagename=$img; | ||||
| 			    $match = 1; | ||||
| 			}	 | ||||
| 		    } | ||||
| 		    if ($match) { | ||||
| 			last; | ||||
| 		    } else { | ||||
| 			print "$img is not found in the osimage table.\n"; | ||||
| 		    } | ||||
| 		} | ||||
| 	    }  | ||||
| 	} | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| # get the install directory | ||||
| my @entries = xCAT::TableUtils->get_site_attribute("installdir"); | ||||
| my $installdir = $entries[0]; | ||||
| chomp($installdir); | ||||
| # lots of error checking to make sure it exists. | ||||
| if($installdir eq ''){ | ||||
|     print "Could not get install directory from site table.  Assuming your OSes are stored in '/install'\n"; | ||||
|     $installdir = "/install"; | ||||
| } | ||||
|      | ||||
| unless(-d $installdir){ | ||||
|     print "The directory where your OS distributions resides: $installdir does not exist.  Please check site table\n"; | ||||
|     exit 1;	 | ||||
| } | ||||
|  | ||||
| if ((!$imagename) && (!$os)){ | ||||
|     my @dircontents = `ls $installdir`; | ||||
|     chomp(@dircontents); | ||||
|     foreach (@dircontents) { | ||||
| 	# SL matches Scientific Linux, sl matches sles amd sled | ||||
| 	if($_ =~ /(rhel|fedora|SL|centos|sl|suse)/){ | ||||
| 	    push @oses,$_; | ||||
| 	} | ||||
|     }  | ||||
|      | ||||
|     if($#oses eq -1){ | ||||
| 	print "There are no OS repositories in $installdir.  Please run copycds for the OS first.\n"; | ||||
| 	exit 1; | ||||
|     } | ||||
|      | ||||
|     # now they have the OSes, make sure they select one that is available | ||||
|     $match = 0; | ||||
|     while(1){ | ||||
| 	print "Available OSes: \n"; | ||||
| 	foreach(@oses){ | ||||
| 	    print  "   $_\n"; | ||||
| 	} | ||||
| 	# default is the first OS cause in many cases, they'll only have 1. | ||||
| 	print "Which OS do you want to build a image for? ["; | ||||
| 	print $oses[0] ; | ||||
| 	print "] "; | ||||
| 	 | ||||
| 	$os = <stdin>; | ||||
| 	chomp($os); | ||||
| 	if($os eq ""){ | ||||
| 	    $os = $oses[0]; | ||||
| 	    last; | ||||
| 	} | ||||
| 	foreach(@oses){ | ||||
| 	    if($os eq $_){ | ||||
| 		$match = 1; | ||||
| 	    }	 | ||||
| 	} | ||||
| 	 | ||||
| 	if($match){ | ||||
| 	    last; | ||||
| 	}else{ | ||||
| 	    print "$os is not found in '$installdir'\n"; | ||||
| 	} | ||||
|     } | ||||
|      | ||||
|     chomp($os); | ||||
| } | ||||
| if ($os) { print "  OS: $os\n"; } | ||||
|  | ||||
|  | ||||
|  | ||||
| ### Get the Profile #### | ||||
| my $osfamily = $os; | ||||
| $osfamily  =~ s/\d+//g; | ||||
| $osfamily  =~ s/\.//g; | ||||
| if($osfamily =~ /rh/){ | ||||
|   $osfamily = "rh"; | ||||
| } | ||||
|  | ||||
| # OS version on s390x can contain 'sp', e.g. sles11sp1 | ||||
| # If the $osfamily contains 'sles' and 'sp', the $osfamily = sles | ||||
| if ($osfamily =~ /sles/ && $osfamily =~ /sp/) { | ||||
|     $osfamily = "sles"; | ||||
| } | ||||
|  | ||||
| #print "OSfamily: $osfamily\n"; | ||||
| $profDir = "$::XCATROOT/share/xcat/netboot/$osfamily"; | ||||
| unless(-d $profDir){ | ||||
|     print "Unable to find genimage script in $profDir\n"; | ||||
|     exit 1; | ||||
| } | ||||
|  | ||||
| if ((!$imagename) && (!$profile)){ | ||||
|     my $profDir2 = "$installdir/custom/netboot/$osfamily"; | ||||
|     my @proList = `ls $profDir/*.pkglist`; | ||||
|     if (-d $profDir2) { | ||||
| 	@proList = (@proList, `ls $profDir2/*.pkglist`); | ||||
|     } | ||||
|     my %seen = (); | ||||
|     foreach (@proList) { | ||||
| 	my $f = basename($_); | ||||
| 	$f =~ s/([^\.]*).*/$1/; | ||||
| 	chomp($f); | ||||
| 	$seen{$f}++; | ||||
|     }  | ||||
|     @profiles = sort keys %seen; | ||||
|     if($#profiles eq -1){ | ||||
| 	print "There are no profiles in $::XCATROOT/share/xcat/netboot/$osfamily.\n"; | ||||
| 	exit 1; | ||||
|     } | ||||
|     $match = 0; | ||||
|     while(1){ | ||||
| 	print "Available Profiles for $os: \n"; | ||||
| 	foreach(@profiles){ | ||||
| 	    print "   $_\n";  | ||||
| 	} | ||||
| 	# default is the first OS cause in many cases, they'll only have 1. | ||||
| 	print "Which profile do you want to use for $os?  ["; | ||||
| 	print "$profiles[0] "; | ||||
| 	print "] "; | ||||
| 	 | ||||
| 	$profile = <stdin>; | ||||
| 	chomp($profile); | ||||
| 	if($profile eq ""){ | ||||
| 	    $profile = $profiles[0]; | ||||
| 	    last; | ||||
| 	} | ||||
| 	foreach(@profiles){ | ||||
| 	    if($profile eq $_){ | ||||
| 		$match = 1; | ||||
| 	    }	 | ||||
| 	} | ||||
| 	if($match eq 1){ | ||||
| 	    last; | ||||
| 	} | ||||
|     } | ||||
| } | ||||
| if ($profile) { print  "  Profile: $profile\n"; } | ||||
|  | ||||
| # get the interface | ||||
| if ((!$imagename) && (!$interface)){ | ||||
|     while(1){ | ||||
| 	print "OPTIONAL: Which specific network interface will the image boot from? [<blank>]"; | ||||
| 	$interface = <stdin>; | ||||
| 	chomp($interface); | ||||
| 	if($interface eq ""){ | ||||
| 	    last; | ||||
| 	}else{ | ||||
| 	    print "You want your stateless machines to boot off of "; | ||||
| 	    print "$interface"; | ||||
| 	    print "? "; | ||||
| 	    print "[Y/n] "; | ||||
| 	    my $conf = <stdin>; | ||||
| 	    chomp($conf); | ||||
| 	    if($conf eq ""){ | ||||
| 		last; | ||||
| 	    } | ||||
| 	    if($conf =~ /Y|y|[Yy][Ee][Ss]/){ | ||||
| 		last; | ||||
| 	    }	 | ||||
| 	} | ||||
|     } | ||||
|     if ($interface) { print "  Interface: $interface\n"; } | ||||
|               else  { print "  No interface specified.  The interface will be determined at network boot time.\n"; } | ||||
| } | ||||
|  | ||||
|      | ||||
|  | ||||
| print "Generating image: \n"; | ||||
| my @arg; | ||||
| if ($imagename) { | ||||
|     push @arg, "$imagename"; | ||||
| } | ||||
|  | ||||
| if ($interface) { | ||||
|     push @arg, "-i"; | ||||
|     push @arg, "$interface"; | ||||
| } | ||||
| if ($drivers) { | ||||
|     push @arg, "-n"; | ||||
|     push @arg, "$drivers"; | ||||
| } | ||||
| if ($os) { | ||||
|     push @arg, "-o"; | ||||
|     push @arg, "$os"; | ||||
| } | ||||
| if ($profile) { | ||||
|     push @arg, "-p"; | ||||
|     push @arg, "$profile"; | ||||
| } | ||||
| if ($arch) { | ||||
|     push @arg, "-a"; | ||||
|     push @arg, "$arch"; | ||||
| } | ||||
|  | ||||
| if ($kernel) { | ||||
|     push @arg, "-k"; | ||||
|     push @arg, "$kernel"; | ||||
| } | ||||
|  | ||||
| if($otherInterfaces){ | ||||
|     push @arg, "-r"; | ||||
|     push @arg, "$otherInterfaces"; | ||||
| } | ||||
|  | ||||
| if ($permission) { | ||||
|     push @arg, "--permission"; | ||||
|     push @arg, "$permission"; | ||||
| } | ||||
|  | ||||
| if ($rootlimit) { | ||||
|     push @arg, "-l"; | ||||
|     push @arg, "$rootlimit"; | ||||
| } | ||||
|  | ||||
| if($tmplimit) { | ||||
|     push @arg, "-t"; | ||||
|     push @arg, "$tmplimit"; | ||||
| } | ||||
|  | ||||
| if ($krpmver) { | ||||
|     push @arg, "-g"; | ||||
|     push @arg, "$krpmver"; | ||||
| } | ||||
|  | ||||
| if ($mode) { | ||||
|     push @arg, "-m"; | ||||
|     push @arg, "$mode"; | ||||
| } | ||||
|  | ||||
| if ($kerneldir) { | ||||
|     push @arg, "--kerneldir"; | ||||
|     push @arg, "$kerneldir"; | ||||
| } | ||||
|  | ||||
| my $tempfile="/tmp/xcat_genimage.$$"; | ||||
| push @arg, "--tempfile"; #this is the file that contains the output | ||||
| push @arg, "$tempfile"; | ||||
|  | ||||
| if ($interactive) { | ||||
|     push @arg, "--interactive"; | ||||
| } | ||||
|  | ||||
|  | ||||
| if ($onlyinitrd) { | ||||
|     push @arg, "--onlyinitrd"; | ||||
| } | ||||
|  | ||||
| if ($dryrun) { | ||||
|     push @arg, "--dryrun"; | ||||
| } | ||||
|  | ||||
| if ($ignorekernelchk) { | ||||
|     push @arg, "--ignorekernelchk"; | ||||
| } | ||||
|  | ||||
| if ($noupdate) { | ||||
|     push @arg, "--noupdate"; | ||||
| } | ||||
|  | ||||
| my $cmdref; | ||||
| push (@{$cmdref->{arg}}, @arg); | ||||
| $cmdref->{command}->[0] = "genimage";    | ||||
|  | ||||
| if (!$interactive) { | ||||
|     xCAT::Client::submit_request($cmdref, \&xCAT::Client::handle_response); | ||||
|     exit $xCAT::Client::EXITCODE; | ||||
| } else { | ||||
|     if ($dryrun) { exit 0; } | ||||
|     #when in interactive mode, first call genimage.pm get info from DB,  | ||||
|     xCAT::Client::submit_request($cmdref, \&xCAT::Client::handle_response); | ||||
|  | ||||
|     #then call the specific genimage under /opt/xcat/share... | ||||
|     if (-f $tempfile) { | ||||
| 	my $cmdname; | ||||
| 	#read the command name | ||||
| 	open(FILE1, "<$tempfile"); | ||||
| 	my @output = <FILE1>; | ||||
|  	if (@output >0) { | ||||
| 	    $cmdname=$output[0]; | ||||
| 	} else { | ||||
| 	    close FILE1; | ||||
| 	    return 1; | ||||
| 	} | ||||
| 	close FILE1; | ||||
|  | ||||
| 	# run the specific genimage command | ||||
| 	#print "cmdname=$cmdname\n"; | ||||
| 	system("$cmdname"); | ||||
|  | ||||
| 	#then call genimage.pm to save the DB | ||||
| 	my @arg1; | ||||
| 	push @arg1, $tempfile; | ||||
| 	my $request; | ||||
| 	push (@{$request->{arg}}, @arg1); | ||||
| 	$request->{command}->[0] = "saveimgdata";   | ||||
| 	xCAT::Client::submit_request($request, \&xCAT::Client::handle_response); | ||||
| 	exit $xCAT::Client::EXITCODE; | ||||
|     } else { | ||||
| 	exit 1; | ||||
|     } | ||||
| } | ||||
|      | ||||
|   | ||||
| @@ -0,0 +1,846 @@ | ||||
| #!/usr/bin/perl | ||||
| # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html | ||||
|  | ||||
| package xCAT_plugin::imgcapture; | ||||
|  | ||||
| BEGIN | ||||
| { | ||||
|     $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; | ||||
| } | ||||
|  | ||||
| use lib "$::XCATROOT/lib/perl"; | ||||
|  | ||||
| use strict; | ||||
|  | ||||
| use Data::Dumper;   # for debug purpose | ||||
| use Getopt::Long; | ||||
| use xCAT::MsgUtils; | ||||
| use xCAT::Utils; | ||||
| use xCAT::TableUtils; | ||||
| use xCAT::SvrUtils; | ||||
| use xCAT::Table; | ||||
| use File::Path qw(mkpath); | ||||
|  | ||||
| Getopt::Long::Configure("bundling"); | ||||
| Getopt::Long::Configure("pass_through"); | ||||
|  | ||||
| my $verbose = 0; | ||||
| my $installroot = "/install"; | ||||
| my $sysclone_home = $installroot . "/sysclone"; | ||||
|  | ||||
| sub handled_commands { | ||||
|     return { "imgcapture" => "imgcapture" }; | ||||
| } | ||||
|  | ||||
| sub process_request { | ||||
|     my $request = shift; | ||||
|     my $callback = shift; | ||||
|     my $doreq = shift; | ||||
|  | ||||
|     my $node; | ||||
|     if (exists $request->{node}) { | ||||
|         $node = $request->{node}->[0]; | ||||
|     } | ||||
|  | ||||
|     $installroot = xCAT::TableUtils->getInstallDir(); | ||||
|     @ARGV = @{$request->{arg}} if (defined $request->{arg}); | ||||
|     my $argc = scalar @ARGV; | ||||
|  | ||||
|     my $usage = "Usage:\n imgcapture <node> -t|--type {diskless|sysclone} -o|--osimage <osimage> [-V | --verbose] \n imgcapture [-h|--help] \n imgcapture [-v|--version]"; | ||||
|  | ||||
|     my $os; | ||||
|     my $arch; | ||||
|     my $device; | ||||
|     my $profile; | ||||
|     my $bootif; | ||||
|     my $netdriver; | ||||
|     my $osimg; | ||||
|     my $help; | ||||
|     my $version; | ||||
|     my $type; | ||||
|  | ||||
|     GetOptions( | ||||
|         "profile|p=s" => \$profile, | ||||
|         "i=s" => \$bootif, | ||||
|         'n=s' => \$netdriver, | ||||
|         'osimage|o=s' => \$osimg, | ||||
|         "device|d=s" => \$device, | ||||
|         "help|h" => \$help, | ||||
|         "version|v" => \$version, | ||||
|         "verbose|V" => \$verbose, | ||||
|         "type|t=s" => \$type | ||||
|     ); | ||||
|  | ||||
|     if ( defined( $ARGV[0] )) { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = "Invalid Argument: $ARGV[0]"; | ||||
|         $rsp->{data}->[1] = $usage; | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|         return 0; | ||||
|     } | ||||
|      | ||||
|     if($version) { | ||||
|         my $version = xCAT::Utils->Version(); | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = $version; | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     if($help) { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = $usage; | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     if( ! $node ) { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = $usage; | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     if(($type =~ /sysclone/) && (!$osimg)){ | ||||
|         my $rsp = {}; | ||||
|         push @{$rsp->{data}}, "You must specify osimage name if you are using \"sysclone\"."; | ||||
|         push @{$rsp->{data}}, $usage; | ||||
|         xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|         return 1;     | ||||
|     } | ||||
|      | ||||
|     my $nodetypetab = xCAT::Table->new("nodetype"); | ||||
|     my $ref_nodetype = $nodetypetab->getNodeAttribs($node, ['os','arch','profile']); | ||||
|     $os = $ref_nodetype->{os}; | ||||
|     $arch = $ref_nodetype->{arch}; | ||||
|     unless($profile) { | ||||
|         $profile = $ref_nodetype->{profile}; | ||||
|     } | ||||
|      | ||||
|     # sysclone | ||||
|     unless($type =~ /diskless/) | ||||
|     { | ||||
|     	# Handle image capture separately for s390x  | ||||
|     	if ($arch eq 's390x') { | ||||
|             eval { require xCAT_plugin::zvm; };  # Load z/VM plugin dynamically | ||||
|             xCAT_plugin::zvm->imageCapture($callback, $node, $os, $arch, $profile, $osimg, $device); | ||||
|             return; | ||||
|         } | ||||
|      | ||||
|         my $shortname = xCAT::InstUtils->myxCATname(); | ||||
|  | ||||
|         my $rc; | ||||
|         $rc  = sysclone_configserver($shortname, $osimg, $callback, $doreq); | ||||
|         if($rc){ | ||||
|             my $rsp = {}; | ||||
|             $rsp->{data}->[0] = qq{Can not configure Imager Server on $shortname.}; | ||||
|             xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|             return 1; | ||||
|         } | ||||
|          | ||||
|         $rc = sysclone_prepclient($node, $shortname, $osimg, $callback, $doreq); | ||||
|         if($rc){ | ||||
|             my $rsp = {}; | ||||
|             $rsp->{data}->[0] = qq{Can not prepare Golden Client on $node.}; | ||||
|             xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|             return 1; | ||||
|         } | ||||
|          | ||||
|         $rc = sysclone_getimg($node, $shortname, $osimg, $callback, $doreq); | ||||
|         if($rc){ | ||||
|             my $rsp = {}; | ||||
|             $rsp->{data}->[0] = qq{Can not get image $osimg from $node.}; | ||||
|             xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|             return 1; | ||||
|         } | ||||
|  | ||||
|         $rc = sysclone_createosimgdef($node, $shortname, $osimg, $callback, $doreq); | ||||
|         if($rc){ | ||||
|             my $rsp = {}; | ||||
|             $rsp->{data}->[0] = qq{Can not create osimage definition for $osimg on $shortname.}; | ||||
|             xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|             return 1; | ||||
|         } | ||||
|  | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     # -i flag is required with sles genimage | ||||
|     if (!$bootif && $os =~ /^sles/) { | ||||
|         $bootif = "eth0"; | ||||
|     } | ||||
|      | ||||
|     # check whether the osimage exists or not | ||||
|     if($osimg) { | ||||
|         my $osimgtab=xCAT::Table->new('osimage', -create=>1); | ||||
|         unless($osimgtab) { | ||||
|             # the osimage table doesn't exist | ||||
|             my $rsp = {}; | ||||
|             $rsp->{data}->[0] = qq{Cannot open the osimage table}; | ||||
|             xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         my $linuximgtab = xCAT::Table->new('linuximage', -create=>1); | ||||
|         unless($linuximgtab) { | ||||
|             # the linuximage table doesn't exist | ||||
|             my $rsp = {}; | ||||
|             $rsp->{data}->[0] = qq{Cannot open the linuximage table}; | ||||
|             xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         my ($ref) = $osimgtab->getAttribs({imagename => $osimg}, 'osvers', 'osarch', 'profile'); | ||||
|         unless($ref) { | ||||
|             my $rsp = {}; | ||||
|             $rsp->{data}->[0] = qq{Cannot find $osimg from the osimage table.}; | ||||
|             xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         my ($ref1) = $linuximgtab->getAttribs({imagename => $osimg}, 'imagename'); | ||||
|         unless($ref1) { | ||||
|             my $rsp = {}; | ||||
|             $rsp->{data}->[0] = qq{Cannot find $osimg from the linuximage table}; | ||||
|             xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         # make sure the "osvers" and "osarch" attributes match the node's attribute | ||||
|         unless($os eq $ref->{'osvers'} and $arch eq $ref->{'osarch'}) { | ||||
|             my $rsp = {}; | ||||
|             $rsp->{data}->[0] = qq{The 'osvers' or 'osarch' attribute of the "$osimg" table doesn't match the node's attribute}; | ||||
|             xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     imgcapture($node, $os, $arch, $profile, $osimg, $bootif, $netdriver, $callback, $doreq); | ||||
| } | ||||
|  | ||||
| sub imgcapture { | ||||
|     my ($node, $os, $arch, $profile, $osimg, $bootif, $netdriver, $callback, $subreq) = @_; | ||||
|     if($verbose) { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = "nodename is $node; os is $os; arch is $arch; profile is $profile"; | ||||
|         $rsp->{data}->[1] = "bootif is $bootif; netdriver is $netdriver"; | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|     } | ||||
|  | ||||
|     # make sure the "/" partion is on the disk,  | ||||
|     my $output = xCAT::Utils->runxcmd({command => ["xdsh"], node => [$node], arg =>["stat / -f |grep Type"]}, $subreq, -1, 1); | ||||
|     if($verbose) { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{the output of "stat / -f |grep Type" on $node is:}; | ||||
|         foreach my $o (@$output) { | ||||
|             push @{$rsp->{data}}, $o; | ||||
|         } | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|     } | ||||
|  | ||||
|     if($::RUNCMD_RC) { #failed | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{The "xdsh" command fails to run on the $node}; | ||||
|         xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     # parse the output of "stat / -f |grep Type",  | ||||
|     $output->[0] =~ m/Type:\s+(.*)$/; | ||||
|     my $fstype =  $1; | ||||
|     if ($verbose) { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{The file type is $fstype}; | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|     } | ||||
|  | ||||
|     # make sure the rootfs type is not nfs or tmpfs | ||||
|     if($fstype eq "nfs" or $fstype eq "tmpfs") { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{This node might not be diskful Linux node, please check it.}; | ||||
|         xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     my $distname = $os; | ||||
|     while ( $distname and ( ! -r "$::XCATROOT/share/xcat/netboot/$distname/") ) { | ||||
|         chop($distname); | ||||
|     } | ||||
|  | ||||
|     unless($distname) { | ||||
|         $callback->({error=>["Unable to find $::XCATROOT/share/xcat/netboot directory for $os"], errorcode => [1]}); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     my $exlistloc = xCAT::SvrUtils->get_imgcapture_exlist_file_name("$installroot/custom/netboot/$distname", $profile, $os, $arch); | ||||
|     unless ($exlistloc) { | ||||
|         $exlistloc = xCAT::SvrUtils->get_imgcapture_exlist_file_name("$::XCATROOT/share/xcat/netboot/$distname", $profile, $os, $arch); | ||||
|     } | ||||
|  | ||||
|     my $xcat_imgcapture_tmpfile = "/tmp/xcat_imgcapture.$$"; | ||||
|  | ||||
|     my $excludestr = "cd /; find ."; | ||||
|  | ||||
|     if($exlistloc) { | ||||
|         my $exlist; | ||||
|         open $exlist, "<", $exlistloc; | ||||
|  | ||||
|         while(<$exlist>) { | ||||
|             $_ =~ s/^\s+//; | ||||
|             chomp $_; | ||||
|             unless($_ =~ m{^#}) { | ||||
|                 $excludestr .= qq{ ! -path "$_"}; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         close $exlist; | ||||
|     } else { | ||||
|         # the following directories must be exluded when capturing the image | ||||
|         my @default_exlist = ("./tmp/*", "./proc/*", "./sys/*", "./dev/*", "./xcatpost/*", "./install/*"); | ||||
|         foreach my $item (@default_exlist) { | ||||
|             $excludestr .= qq{ ! -path "$item"}; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     $excludestr .= " |cpio -H newc -o |gzip -c - >$xcat_imgcapture_tmpfile"; | ||||
|     if($verbose) { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{The excludestr is "$excludestr"}; | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|     } | ||||
|  | ||||
|     # run the command via "xdsh" | ||||
|  | ||||
|     xCAT::Utils->runxcmd({command => ["xdsh"], node => [$node], arg => ["echo -n >$xcat_imgcapture_tmpfile"]}, $subreq, -1, 1); | ||||
|     if($verbose) { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{running "echo -n > $xcat_imgcapture_tmpfile" on $node}; | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|     } | ||||
|  | ||||
|     if($::RUNCMD_RC) { # the xdsh command fails | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{The "xdsh" command fails to run "echo -n > $xcat_imgcapture_tmpfile" on $node}; | ||||
|         xCAT:MsgUtils->message("E", $rsp, $callback); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     my $rsp = {}; | ||||
|     $rsp->{data}->[0] = qq{Capturing image on $node...}; | ||||
|     xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|  | ||||
|     if($verbose) { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{running "$excludestr" on $node via the "xdsh" command}; | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|     } | ||||
|  | ||||
|     xCAT::Utils->runxcmd({command => ["xdsh"], node => [$node], arg => [$excludestr]}, $subreq, -1, 1); | ||||
|  | ||||
|     if($::RUNCMD_RC) { # the xdsh command fails | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{The "xdsh" command fails to run "$excludestr" on $node}; | ||||
|         xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     $rsp = {}; | ||||
|     $rsp->{data}->[0] = qq{Transfering the image captured on $node back...}; | ||||
|     xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|  | ||||
|     # copy the image captured on $node back via the "scp" command | ||||
|     xCAT::Utils->runcmd("scp $node:$xcat_imgcapture_tmpfile $xcat_imgcapture_tmpfile"); | ||||
|     if($verbose) { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{Running "scp $node:$xcat_imgcapture_tmpfile $xcat_imgcapture_tmpfile"}; | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|     } | ||||
|  | ||||
|     if($::RUNCMD_RC) { | ||||
|         my $rsp ={}; | ||||
|         $rsp->{data}->[0] = qq{The scp command fails}; | ||||
|         xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     xCAT::Utils->runxcmd({command => ["xdsh" ], node => [$node], arg => ["rm -f $xcat_imgcapture_tmpfile"]}, $subreq, -1, 1); | ||||
|  | ||||
|     # extract the $xcat_imgcapture_tmpfile file to /install/netboot/$os/$arch/$profile/rootimg | ||||
|     my $rootimgdir = "$installroot/netboot/$os/$arch/$profile/rootimg"; | ||||
|  | ||||
|     # empty the rootimg directory before extracting the image captured on the diskful Linux node | ||||
|     if( -d $rootimgdir ) { | ||||
|         unlink $rootimgdir; | ||||
|     } | ||||
|     mkpath($rootimgdir); | ||||
|  | ||||
|     xCAT::Utils->runcmd("cd $rootimgdir; gzip -cd $xcat_imgcapture_tmpfile|cpio -idum"); | ||||
|     if($verbose) { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{Extracting the image to $rootimgdir}; | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|     } | ||||
|     if($::RUNCMD_RC) { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{fails to run the "gzip -cd xx |cpio -idum" command}; | ||||
|         xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|         return; | ||||
|     } | ||||
|      | ||||
|     if($verbose) { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{Creating the spots exluded when capturing on $node...}; | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|     } | ||||
|  | ||||
|     # the next step is to call "genimage" | ||||
|     my $platform = getplatform($os); | ||||
|     if( -e "$::XCATROOT/share/xcat/netboot/$platform/genimage" ) { | ||||
|         my $cmd; | ||||
|  | ||||
|         if( $osimg ) { | ||||
|             $cmd = "$::XCATROOT/bin/genimage $osimg "; | ||||
|         } else { | ||||
|             $cmd = "$::XCATROOT/share/xcat/netboot/$platform/genimage -o $os -a $arch -p $profile "; | ||||
|         } | ||||
|  | ||||
|         if($bootif) { | ||||
|             $cmd .= "-i $bootif "; | ||||
|         } | ||||
|         if($netdriver) { | ||||
|             $cmd .= "-n $netdriver"; | ||||
|         } | ||||
|  | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{Generating kernel and initial ramdisks...}; | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|  | ||||
|         if($verbose) { | ||||
|             my $rsp = {}; | ||||
|             $rsp->{data}->[0] = qq{"The genimage command is: $cmd"}; | ||||
|             xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|         } | ||||
|         my @cmdoutput = xCAT::Utils->runcmd($cmd, 0); | ||||
|         if($::RUNCMD_RC) { | ||||
|             my $rsp = {}; | ||||
|             foreach (@cmdoutput) { | ||||
|                 push @{$rsp->{data}}, $_; | ||||
|             } | ||||
|             xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|             unlink $xcat_imgcapture_tmpfile; | ||||
|             return; | ||||
|         } | ||||
|     } else { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{Can't run the "genimage" command for $os}; | ||||
|         xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     my $rsp = {}; | ||||
|     $rsp->{data}->[0] = qq{Done.}; | ||||
|     xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|  | ||||
|     unlink $xcat_imgcapture_tmpfile; | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| sub getplatform { | ||||
|     my $os = shift; | ||||
|     my $platform; | ||||
|     if ($os =~ m/rh.*/) { | ||||
|         $platform = "rh"; | ||||
|     } elsif ($os =~ m/centos.*/) { | ||||
|         $platform = "centos"; | ||||
|     } elsif ($os =~ m/fedora.*/) { | ||||
|         $platform = "fedora"; | ||||
|     } elsif ($os =~ m/SL.*/) { | ||||
|         $platform = "SL"; | ||||
|     } elsif ($os =~ m/sles.*/) { | ||||
|         $platform = "sles"; | ||||
|     } elsif ($os =~ m/suse.*/) { | ||||
|         $platform = "suse"; | ||||
|     } | ||||
|  | ||||
|     return $platform; | ||||
| } | ||||
|  | ||||
| sub sysclone_configserver{ | ||||
|     my ($server, $osimage, $callback, $subreq) = @_; | ||||
|      | ||||
|     # check if systemimager is installed on the imager server | ||||
|     my $rsp = {}; | ||||
|     $rsp->{data}->[0] = qq{Checking if systemimager packages are installed on $server.}; | ||||
|     xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|      | ||||
|     my $cmd = "rpm -qa|grep systemimager-server"; | ||||
|     my $output = xCAT::Utils->runcmd("$cmd", -1);     | ||||
|     if($verbose) { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{the output of $cmd on $server is:}; | ||||
|         push @{$rsp->{data}}, $output; | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|     } | ||||
|  | ||||
|     if($::RUNCMD_RC != 0) { #failed | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{systemimager-server is not installed on the $server.}; | ||||
|         xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     # update /etc/systemimager/systemimager.conf | ||||
|     my $rc = `sed -i "s/\\/var\\/lib\\/systemimager/\\/install\\/sysclone/g" /etc/systemimager/systemimager.conf`; | ||||
|     if (!(-e $sysclone_home)) | ||||
|     { | ||||
|         mkpath($sysclone_home); | ||||
|     } | ||||
|  | ||||
|     my $sysclone_images = $sysclone_home . "/images"; | ||||
|     if (!(-e $sysclone_images)) | ||||
|     { | ||||
|         mkpath($sysclone_images); | ||||
|     } | ||||
|  | ||||
|     my $sysclone_scripts = $sysclone_home . "/scripts"; | ||||
|     if (!(-e $sysclone_scripts)) | ||||
|     { | ||||
|         mkpath($sysclone_scripts); | ||||
|     } | ||||
|  | ||||
|     my $sysclone_overrides = $sysclone_home . "/overrides"; | ||||
|     if (!(-e $sysclone_overrides)) | ||||
|     { | ||||
|         mkpath($sysclone_overrides); | ||||
|     } | ||||
| 	 | ||||
|     my $imagedir; | ||||
|     my $osimgtab  = xCAT::Table->new('osimage'); | ||||
|     my $entry = ($osimgtab->getAllAttribsWhere("imagename = '$osimage'", 'ALL' ))[0]; | ||||
|     if(!$entry){ | ||||
|         $imagedir = $sysclone_home . "/images/" . $osimage;   | ||||
|     }else{ | ||||
|         my $osimagetab = xCAT::Table->new('linuximage'); | ||||
|         my $osimageentry  = $osimagetab->getAttribs({imagename => $osimage}, 'rootimgdir'); | ||||
|         if($osimageentry){ | ||||
|             $imagedir = $osimageentry->{rootimgdir}; | ||||
|             if (!(-e $imagedir)){ | ||||
| 		        mkpath($imagedir); | ||||
|             } | ||||
|         }else{ | ||||
|             $imagedir = $sysclone_home . "/images/" . $osimage;    | ||||
|             $cmd = "chdef -t osimage $osimage rootimgdir=$imagedir"; | ||||
|             $rc = `$cmd`; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     $imagedir =~ s/^(\/.*)\/.+\/?$/$1/; | ||||
|     $imagedir =~ s/\//\\\\\//g; | ||||
|     $imagedir = "DEFAULT_IMAGE_DIR = ".$imagedir; | ||||
| 				 | ||||
|     my $olddir = `more /etc/systemimager/systemimager.conf |grep DEFAULT_IMAGE_DIR`; | ||||
|     $olddir =~ s/\//\\\\\//g; | ||||
|     chomp($olddir); | ||||
| 		 | ||||
|     $cmd= "sed -i \"s/$olddir/$imagedir/\"  /etc/systemimager/systemimager.conf"; | ||||
|     $rc = `$cmd`; | ||||
| 	 | ||||
|     # update /etc/systemimager/rsync_stubs/10header to generate new /etc/systemimager/rsyncd.conf | ||||
|     $rc = `sed -i "s/\\/var\\/lib\\/systemimager/\\/install\\/sysclone/g" /etc/systemimager/rsync_stubs/10header`; | ||||
|     $rc = `export PERL5LIB=/usr/lib/perl5/site_perl/;LANG=C si_mkrsyncd_conf`; | ||||
|      | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| sub sysclone_prepclient { | ||||
|     my ($node, $server, $osimage, $callback, $subreq) = @_; | ||||
|      | ||||
|     # check if systemimager is installed on the golden client | ||||
|     my $rsp = {}; | ||||
|     $rsp->{data}->[0] = qq{Checking if systemimager packages are installed on $node.}; | ||||
|     xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|      | ||||
|     my $cmd = "rpm -qa|grep systemimager-client"; | ||||
|     my $output = xCAT::Utils->runxcmd({command => ["xdsh"], node => [$node], arg =>[$cmd]}, $subreq, 0, 1); | ||||
|     if($verbose) { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{the output of $cmd on $node is:}; | ||||
|         foreach my $o (@$output) { | ||||
|             push @{$rsp->{data}}, $o; | ||||
|         } | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|     } | ||||
|  | ||||
|     if($::RUNCMD_RC != 0) { #failed | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{systemimager-client is not installed on the $node.}; | ||||
|         xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     # prepare golden client | ||||
|     my $rsp = {}; | ||||
|     $rsp->{data}->[0] = qq{Preparing osimage $osimage on $node.}; | ||||
|     xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|      | ||||
|     my $cmd = "export PERL5LIB=/usr/lib/perl5/site_perl/;LANG=C si_prepareclient --server $server --no-uyok --yes"; | ||||
|     my $output = xCAT::Utils->runxcmd( | ||||
|                                             { | ||||
|                                             command => ["xdsh"],  | ||||
|                                             node => [$node],  | ||||
|                                             arg =>["-s", $cmd] | ||||
|                                             },  | ||||
|                                             $subreq, 0, 1); | ||||
|     if($verbose) { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{the output of $cmd on $node is:}; | ||||
|         foreach my $o (@$output) { | ||||
|             push @{$rsp->{data}}, $o; | ||||
|         } | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|     } | ||||
|  | ||||
|     if($::RUNCMD_RC != 0) { #failed | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{$cmd failed on the $node.}; | ||||
|         xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     # fix systemimager bug | ||||
|     $cmd  = qq{sed -i 's/p_name=\"(v1)\"/p_name=\"-\"/' /etc/systemimager/autoinstallscript.conf}; | ||||
|     $output = xCAT::Utils->runxcmd( | ||||
|                                             { | ||||
|                                             command => ["xdsh"],  | ||||
|                                             node => [$node],  | ||||
|                                             arg =>[$cmd] | ||||
|                                             },  | ||||
|                                             $subreq, 0, 1); | ||||
|                                              | ||||
|     my @nodes = ($node); | ||||
|     my $nodetypetab = xCAT::Table->new("nodetype"); | ||||
|     my $nthash = $nodetypetab->getNodesAttribs(\@nodes, ['arch']); | ||||
|     my $tmp = $nthash->{$node}->[0]->{arch}; | ||||
|     if ( $tmp eq 'ppc64'){ | ||||
|         $cmd  = qq(if ! cat /etc/systemimager/autoinstallscript.conf |grep 'part  num=\\\"1\\\"' |grep 'id=' >/dev/null ;then sed -i 's:\\(.*<part  num=\\\"1\\\".*\\)\\(/>\\):\\1 id=\\\"41\\\" \\2:' /etc/systemimager/autoinstallscript.conf;fi); | ||||
|         $output = xCAT::Utils->runxcmd( | ||||
|                                             { | ||||
|                                             command => ["xdsh"], | ||||
|                                             node => [$node], | ||||
|                                             arg =>[$cmd] | ||||
|                                             }, | ||||
|                                             $subreq, 0, 1); | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| sub sysclone_getimg{ | ||||
|     my ($node, $server, $osimage, $callback, $subreq) = @_; | ||||
|  | ||||
|     my $rsp = {}; | ||||
|     $rsp->{data}->[0] = qq{Getting osimage "$osimage" from $node to $server.}; | ||||
|     xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|  | ||||
|     my $cmd = "export PERL5LIB=/usr/lib/perl5/site_perl/;"; | ||||
|     $cmd .= "LANG=C si_getimage -golden-client $node -image $osimage -ip-assignment dhcp -post-install reboot -quiet -update-script YES"; | ||||
|     my $output = xCAT::Utils->runcmd($cmd, -1); | ||||
|     if($verbose) { | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{the output of $cmd on $server is:}; | ||||
|         if(ref $output){ | ||||
|             foreach my $o (@$output) { | ||||
|                 push @{$rsp->{data}}, $o; | ||||
|             } | ||||
|         } else { | ||||
|             @{$rsp->{data}} = ($output); | ||||
|         } | ||||
|         xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|     } | ||||
|  | ||||
|     if($::RUNCMD_RC != 0) { #failed | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{$cmd failed on the $server.}; | ||||
|         xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     # use reboot in genesis | ||||
|     my $masterscript = $sysclone_home . "/scripts" . "/$osimage.master"; | ||||
|     my $rc = `sed -i "s/shutdown -r now/reboot -f/g" $masterscript`; | ||||
|  | ||||
|     #on redhat5 and centos5, the fs inode size must be 128 | ||||
|     my $node_osver = getOsVersion($node); | ||||
|     if ( $node_osver =~ /rh.*5.*/ || $node_osver =~ /centos5.*/ ) { | ||||
|         `sed -i "s/mke2fs/mke2fs -I 128/g" $masterscript` | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| sub sysclone_createosimgdef{ | ||||
|     my ($node, $server, $osimage, $callback, $subreq) = @_; | ||||
|     my $createnew = 0; | ||||
|     my %osimgdef; | ||||
|  | ||||
|     my $osimgtab  = xCAT::Table->new('osimage'); | ||||
|     my $entry = ($osimgtab->getAllAttribsWhere("imagename = '$osimage'", 'ALL' ))[0]; | ||||
|      if($entry){ | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{Using the existing osimage "$osimage" defined on $server.}; | ||||
|         xCAT::MsgUtils->message("I", $rsp, $callback); | ||||
|         return 0; | ||||
|      } | ||||
|      | ||||
|     # try to see if we can get the osimage def from golden client. | ||||
|     my $nttab  = xCAT::Table->new('nodetype'); | ||||
|     if (!$nttab){ | ||||
|         my $rsp = {}; | ||||
|         $rsp->{data}->[0] = qq{Can not open nodebype table.}; | ||||
|         xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     my @nodes = ($node); | ||||
|     my $nthash = $nttab->getNodesAttribs(\@nodes, ['node', 'provmethod']); | ||||
|     my $tmp = $nthash->{$node}->[0]; | ||||
|     if (($tmp) && ($tmp->{provmethod})){ | ||||
|  | ||||
|         my %objtype; | ||||
|         my $oldimg = $tmp->{provmethod}; | ||||
|  | ||||
|         # see if osimage exists | ||||
|         $objtype{$oldimg} = 'osimage'; | ||||
|         my %imagedef = xCAT::DBobjUtils->getobjdefs(\%objtype, $callback); | ||||
|         if (!($imagedef{$oldimg}{osvers})){ # just select one attribute for test | ||||
|             # create new one | ||||
|             $createnew = 1; | ||||
|         }else{ | ||||
|             # based on the existing one | ||||
|             $osimgdef{$osimage} = $imagedef{$oldimg}; | ||||
|  | ||||
|             # only update a few attributes which are meanless for sysclone | ||||
|             $osimgdef{$osimage}{provmethod} = "sysclone"; | ||||
|             $osimgdef{$osimage}{template} = ""; | ||||
|             $osimgdef{$osimage}{otherpkglist} = ""; | ||||
|             $osimgdef{$osimage}{pkglist} = ""; | ||||
| 			 | ||||
|             if(!($imagedef{$oldimg}{rootimgdir})){ | ||||
|                 $imagedef{$oldimg}{rootimgdir} = $sysclone_home . "/images/" . $osimage;       | ||||
| 				 | ||||
|                 my $imagedir = $imagedef{$oldimg}{rootimgdir}; | ||||
|                 $imagedir =~ s/^(\/.*)\/.+\/?$/$1/; | ||||
|                 $imagedir =~ s/\//\\\\\//g; | ||||
|                 $imagedir = "DEFAULT_IMAGE_DIR = ".$imagedir; | ||||
| 				 | ||||
|                 my $olddir = `more /etc/systemimager/systemimager.conf |grep DEFAULT_IMAGE_DIR`; | ||||
|                 $olddir =~ s/\//\\\\\//g; | ||||
|                 chomp($olddir); | ||||
| 		 | ||||
|                 my $cmd= "sed -i \"s/$olddir/$imagedir/\"  /etc/systemimager/systemimager.conf"; | ||||
|                 my $rc = `$cmd`; | ||||
|             } | ||||
|         } | ||||
|     } else { | ||||
|         $createnew = 1; | ||||
|     } | ||||
|  | ||||
|     if($createnew){ | ||||
|         my $file = $sysclone_home . "/images/" . $osimage. "/etc/systemimager/boot/ARCH"; | ||||
|         my $cmd = "cat $file"; | ||||
|         my $output = xCAT::Utils->runcmd($cmd, -1); | ||||
|         chomp $output; | ||||
|         my $arch = $output; | ||||
|         my $osver = getOsVersion($node); | ||||
|         my $platform = getplatform($osver); | ||||
|  | ||||
|         # create a baic one | ||||
|         $osimgdef{$osimage}{objtype} = "osimage"; | ||||
|         $osimgdef{$osimage}{provmethod} = "sysclone"; | ||||
|         $osimgdef{$osimage}{profile} = "compute";  # use compute? | ||||
|         $osimgdef{$osimage}{imagetype} = "Linux"; | ||||
|         $osimgdef{$osimage}{osarch} = $arch; | ||||
|         $osimgdef{$osimage}{osname} = "Linux"; | ||||
|         $osimgdef{$osimage}{osvers} =  $osver; | ||||
|         $osimgdef{$osimage}{osdistroname} =  "$osver-$arch"; | ||||
| 		 | ||||
|         $osimgdef{$osimage}{rootimgdir} = $sysclone_home . "/images/" . $osimage; | ||||
|         my $imagedir = $osimgdef{$osimage}{rootimgdir}; | ||||
|         $imagedir =~ s/^(\/.*)\/.+\/?$/$1/; | ||||
|         $imagedir =~ s/\//\\\\\//g; | ||||
|         $imagedir = "DEFAULT_IMAGE_DIR = ".$imagedir; | ||||
|         my $olddir = `more /etc/systemimager/systemimager.conf |grep DEFAULT_IMAGE_DIR`; | ||||
|         $olddir =~ s/\//\\\\\//g; | ||||
|         chomp($olddir); | ||||
|         my $cmd= "sed -i \"s/$olddir/$imagedir/\"  /etc/systemimager/systemimager.conf"; | ||||
|         my $rc = `$cmd`; | ||||
| 		 | ||||
|         #$osimgdef{$osimage}{pkgdir} =  "/install/$osver/$arch"; | ||||
|         #$osimgdef{$osimage}{otherpkgdir} =  "/install/post/otherpkgs/$osver/$arch"; | ||||
|     } | ||||
|  | ||||
|     if (xCAT::DBobjUtils->setobjdefs(\%osimgdef) != 0) | ||||
|     { | ||||
|         my $rsp; | ||||
|         $rsp->{data}->[0] = "Could not create xCAT definition for $osimage.\n"; | ||||
|         xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     my $rsp = {}; | ||||
|     $rsp->{data}->[0] = qq{The osimage definition for $osimage was created.}; | ||||
|     xCAT::MsgUtils->message("D", $rsp, $callback); | ||||
|  | ||||
|     return 0;     | ||||
| } | ||||
|  | ||||
| sub getOsVersion { | ||||
|     my ($node) = @_; | ||||
|  | ||||
|     my $os = ''; | ||||
|     my $version = ''; | ||||
|  | ||||
|     # Get operating system | ||||
|     my $release = `ssh -o ConnectTimeout=2 $node "cat /etc/*release"`; | ||||
|     my @lines = split('\n', $release); | ||||
|     if (grep(/SLES|Enterprise Server/, @lines)) { | ||||
|         $os = 'sles'; | ||||
|         $version = $lines[0]; | ||||
|         $version =~ tr/\.//; | ||||
|         $version =~ s/[^0-9]*([0-9]+).*/$1/; | ||||
|         $os = $os . $version; | ||||
|          | ||||
|         # Append service level | ||||
|         $version = `echo "$release" | grep "LEVEL"`; | ||||
|         $version =~ tr/\.//; | ||||
|         $version =~ s/[^0-9]*([0-9]+).*/$1/; | ||||
|         $os = $os . 'sp' . $version; | ||||
|     } elsif (grep(/Red Hat/, @lines)) { | ||||
|         $os = "rh"; | ||||
|         $version = $lines[0]; | ||||
|         $version =~ s/[^0-9]*([0-9.]+).*/$1/; | ||||
|         if    ($lines[0] =~ /AS/)     { $os = 'rhas' } | ||||
|         elsif ($lines[0] =~ /ES/)     { $os = 'rhes' } | ||||
|         elsif ($lines[0] =~ /WS/)     { $os = 'rhws' } | ||||
|         elsif ($lines[0] =~ /Server/) { $os = 'rhels' } | ||||
|         elsif ($lines[0] =~ /Client/) { $os = 'rhel' } | ||||
|         #elsif (-f "/etc/fedora-release") { $os = 'rhfc' } | ||||
|         $os = $os . $version; | ||||
|     } | ||||
|     elsif (grep (/CentOS/, @lines)) { | ||||
|         $os = "centos"; | ||||
|         $version = $lines[0]; | ||||
|         $version =~ s/[^0-9]*([0-9.]+).*/$1/; | ||||
|         $os = $os . $version; | ||||
|     } | ||||
|     elsif (grep (/Fedora/, @lines)) { | ||||
|         $os = "fedora"; | ||||
|         $version = $lines[0]; | ||||
|         $version =~ s/[^0-9]*([0-9.]+).*/$1/; | ||||
|         $os = $os . $version; | ||||
|     } | ||||
|      | ||||
|  | ||||
|     return $os; | ||||
| } | ||||
| 1; | ||||
|   | ||||
| @@ -0,0 +1,629 @@ | ||||
| package xCAT_plugin::packimage; | ||||
| BEGIN | ||||
| { | ||||
|     $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; | ||||
| } | ||||
| use lib "$::XCATROOT/lib/perl"; | ||||
| use Data::Dumper; | ||||
| use xCAT::Table; | ||||
| use Getopt::Long; | ||||
| use File::Path; | ||||
| use File::Copy; | ||||
| use Cwd; | ||||
| use File::Temp; | ||||
| use File::Basename; | ||||
| use File::Path; | ||||
| #use xCAT::Utils qw(genpassword); | ||||
| use xCAT::Utils; | ||||
| use xCAT::TableUtils; | ||||
| use xCAT::SvrUtils; | ||||
| Getopt::Long::Configure("bundling"); | ||||
| Getopt::Long::Configure("pass_through"); | ||||
|  | ||||
|  | ||||
| my $verbose = 0; | ||||
| #$verbose = 1; | ||||
|  | ||||
| sub handled_commands { | ||||
|      return { | ||||
|             packimage => "packimage", | ||||
|    } | ||||
| } | ||||
|  | ||||
| sub process_request { | ||||
|    my $request = shift; | ||||
|    my $callback = shift; | ||||
|    my $doreq = shift; | ||||
|    my $installroot = xCAT::TableUtils->getInstallDir(); | ||||
|  | ||||
|    @ARGV = @{$request->{arg}}; | ||||
|    my $argc = scalar @ARGV; | ||||
|    if ($argc == 0) { | ||||
|        $callback->({info=>["packimage -h \npackimage -v \npackimage imagename"]}); | ||||
|        return; | ||||
|    } | ||||
|    my $osver; | ||||
|    my $arch; | ||||
|    my $profile; | ||||
|    my $method='cpio'; | ||||
|    my $exlistloc; | ||||
|    my $syncfile; | ||||
|    my $rootimg_dir; | ||||
|    my $destdir; | ||||
|    my $imagename; | ||||
|    my $dotorrent; | ||||
|  | ||||
|    GetOptions( | ||||
|       "profile|p=s" => \$profile, | ||||
|       "arch|a=s" => \$arch, | ||||
|       "osver|o=s" => \$osver, | ||||
|       "method|m=s" => \$method, | ||||
|       "tracker=s" => \$dotorrent, | ||||
|       "help|h" => \$help, | ||||
|       "version|v" => \$version | ||||
|       ); | ||||
|    if ($version) { | ||||
|       my $version = xCAT::Utils->Version();  | ||||
|       $callback->({info=>[$version]}); | ||||
|       return; | ||||
|    } | ||||
|    if ($help) { | ||||
|       $callback->({info=>["packimage -h \npackimage -v \npackimage imagename"]}); | ||||
|       return; | ||||
|    } | ||||
|  | ||||
|    if (@ARGV > 0) { | ||||
|        $imagename=$ARGV[0]; | ||||
|        if ($arch or $osver or $profile) { | ||||
|            $callback->({error=>["-o, -p and -a options are not allowed when a image name is specified."],errorcode=>[1]}); | ||||
|            return; | ||||
|        } | ||||
|        # load the module in memory | ||||
|        eval {require("$::XCATROOT/lib/perl/xCAT/Table.pm")}; | ||||
|        if ($@) { | ||||
|            $callback->({error=>[$@],errorcode=>[1]}); | ||||
|            return; | ||||
|        } | ||||
|     | ||||
|        # get the info from the osimage and linux  | ||||
|        my $osimagetab=xCAT::Table->new('osimage', -create=>1); | ||||
|        unless ($osimagetab) { | ||||
|            $callback->({error=>["The osimage table cannot be opened."],errorcode=>[1]}); | ||||
|            return; | ||||
|        } | ||||
|        my $linuximagetab=xCAT::Table->new('linuximage', -create=>1); | ||||
|        unless ($linuximagetab) { | ||||
|            $callback->({error=>["The linuximage table cannot be opened."],errorcode=>[1]}); | ||||
|            return; | ||||
|        } | ||||
|        (my $ref) = $osimagetab->getAttribs({imagename => $imagename}, 'osvers', 'osarch', 'profile', 'provmethod', 'synclists'); | ||||
|        unless ($ref) { | ||||
|            $callback->({error=>["Cannot find image \'$imagename\' from the osimage table."],errorcode=>[1]}); | ||||
|            return; | ||||
|        } | ||||
|        (my $ref1) = $linuximagetab->getAttribs({imagename => $imagename}, 'exlist', 'rootimgdir'); | ||||
|        unless ($ref1) { | ||||
|            $callback->({error=>["Cannot find $imagename from the linuximage table."],errorcode=>[1]}); | ||||
|            return; | ||||
|        } | ||||
|         | ||||
|        $osver=$ref->{'osvers'}; | ||||
|        $arch=$ref->{'osarch'}; | ||||
|        $profile=$ref->{'profile'}; | ||||
|        $syncfile=$ref->{'synclists'}; | ||||
|        my $provmethod=$ref->{'provmethod'}; | ||||
|         | ||||
|        unless ($osver and $arch and $profile and $provmethod) { | ||||
|            $callback->({error=>["osimage.osvers, osimage.osarch, osimage.profile and osimage.provmethod must be specified for the image $imagename in the database."],errorcode=>[1]}); | ||||
|            return; | ||||
|        } | ||||
|         | ||||
|        if ($provmethod ne 'netboot') { | ||||
|            $callback->({error=>["\'$imagename\' cannot be used to build diskless image. Make sure osimage.provmethod is 'netboot'."],errorcode=>[1]}); | ||||
|            return; | ||||
|        } | ||||
|         | ||||
|        $exlistloc =$ref1->{'exlist'}; | ||||
|        $destdir=$ref1->{'rootimgdir'}; | ||||
|    } else { | ||||
|        $provmethod="netboot"; | ||||
|        unless ($osver) { | ||||
| 	   $callback->({error=>["Please specify a os version with the -o flag"],errorcode=>[1]}); | ||||
|            return; | ||||
|        } | ||||
|        unless ($arch) { | ||||
| 	   $arch = `uname -m`; | ||||
| 	   chomp($arch); | ||||
| 	   $arch = "x86" if ($arch =~ /i.86$/); | ||||
|        } | ||||
|  | ||||
|        unless ($profile) { | ||||
| 	   $callback->({error=>["Please specify a profile name with -p flag"],errorcode=>[1]}); | ||||
|            return; | ||||
|        } | ||||
|    } | ||||
|  | ||||
|    unless ($destdir) { | ||||
|        $destdir="$installroot/netboot/$osver/$arch/$profile"; | ||||
|    } | ||||
|    $rootimg_dir="$destdir/rootimg"; | ||||
|  | ||||
|    my $distname = $osver; | ||||
|    until (-r  "$::XCATROOT/share/xcat/netboot/$distname/" or not $distname) { | ||||
|       chop($distname); | ||||
|    } | ||||
|    unless ($distname) { | ||||
|       $callback->({error=>["Unable to find $::XCATROOT/share/xcat/netboot directory for $osver"],errorcode=>[1]}); | ||||
|       return; | ||||
|    } | ||||
|    unless ($installroot) { | ||||
|        $callback->({error=>["No installdir defined in site table"],errorcode=>[1]}); | ||||
|        return; | ||||
|    } | ||||
|    my $oldpath=cwd(); | ||||
|    unless ($imagename) { | ||||
|        $exlistloc=xCAT::SvrUtils->get_exlist_file_name("$installroot/custom/netboot/$distname", $profile, $osver, $arch); | ||||
|        unless ($exlistloc) {  $exlistloc=xCAT::SvrUtils->get_exlist_file_name("$::XCATROOT/share/xcat/netboot/$distname", $profile, $osver, $arch); } | ||||
|        | ||||
|        #save the settings into DB, it will not update if the image already exist | ||||
|        my @ret = xCAT::SvrUtils->update_tables_with_diskless_image($osver, $arch, $profile, "netboot"); | ||||
|        unless ($ret[0] eq 0) { | ||||
| 	   $callback->({error=>["Error when updating the osimage tables: " . $ret[1]], errorcode=>[1]}); | ||||
| 	   return; | ||||
|        } | ||||
|    } | ||||
|  | ||||
|     #before generating rootimg.gz, copy $installroot/postscripts into the image at /xcatpost | ||||
|     if( -e "$rootimg_dir/xcatpost" ) {   | ||||
|         system("rm -rf $rootimg_dir/xcatpost"); | ||||
|     } | ||||
|  | ||||
|     system("mkdir -p $rootimg_dir/xcatpost"); | ||||
|     system("cp -r $installroot/postscripts/* $rootimg_dir/xcatpost/"); | ||||
|  | ||||
|     #put the image name and timestamp into diskless image when it is packed. | ||||
|     `echo IMAGENAME="'$imagename'" > $rootimg_dir/opt/xcat/xcatinfo`; | ||||
|      | ||||
|     my $timestamp = `date`; | ||||
|     chomp $timestamp; | ||||
|     `echo TIMESTAMP="'$timestamp'" >> $rootimg_dir/opt/xcat/xcatinfo`; | ||||
|  | ||||
|  | ||||
|     # before generating rootimg.gz or rootimg.sfs, need to switch the rootimg to stateless mode if necessary | ||||
|     my $rootimg_status = 0; # 0 means stateless mode, while 1 means statelite mode | ||||
|     $rootimg_status = 1 if (-f "$rootimg_dir/.statelite/litefile.save"); | ||||
|      | ||||
|     my $ref_liteList; # get the litefile entries | ||||
|  | ||||
|     my @ret = xCAT::Utils->runcmd("ilitefile $osver-$arch-statelite-$profile" , 0, 1); | ||||
|     $ref_liteList = $ret[0]; | ||||
|  | ||||
|     my %liteHash;   # create hash table for the entries in @listList | ||||
|     if (parseLiteFiles($ref_liteList, \%liteHash)) { | ||||
|         $callback->({error=>["Failed for parsing litefile table!"], errorcode=>[1]}); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     $verbose && $callback->({data=>["rootimg_status = $rootimg_status at line " . __LINE__ ]}); | ||||
|  | ||||
|     if($rootimg_status) { | ||||
|         xCAT::Utils->runcmd("mkdir $rootimg_dir/.statebackup", 0, 1); | ||||
|         # read through the litefile table to decide which file/directory should be restore | ||||
|         my $defaultloc = "$rootimg_dir/.default"; | ||||
|         foreach my $entry (keys %liteHash) { | ||||
|             my @tmp = split /\s+/, $entry; | ||||
|             my $filename = $tmp[1]; | ||||
|             my $fileopt = $tmp[0]; | ||||
|  | ||||
|             if ($fileopt =~ m/link/) { | ||||
|                 # backup them into .statebackup dirctory | ||||
|                 # restore the files with "link" options | ||||
|                 if ($filename =~ m/\/$/) { | ||||
|                     chop $filename; | ||||
|                 } | ||||
|                 # create the parent directory if $filename's directory is not there,  | ||||
|                 my $parent = dirname $filename; | ||||
|                 unless ( -d "$rootimg_dir/.statebackup$parent" ) { | ||||
|                     unlink "$rootimg_dir/.statebackup$parent"; | ||||
|                     $verbose && $callback->({data=>["mkdir -p $rootimg_dir/.statebackup$parent"]}); | ||||
|                     xCAT::Utils->runcmd("mkdir -p $rootimg_dir/.statebackup$parent", 0, 1); | ||||
|                 } | ||||
|                 $verbose && $callback->({data=>["backing up the file $filename.. at line " . __LINE__ ]}); | ||||
|                 $verbose && print "++ $defaultloc$filename ++ $rootimg_dir$filename ++ at " . __LINE__ . "\n"; | ||||
|                 xCAT::Utils->runcmd("mv $rootimg_dir$filename $rootimg_dir/.statebackup$filename", 0, 1); | ||||
|                 xCAT::Utils->runcmd("cp -r -a $defaultloc$filename $rootimg_dir$filename", 0, 1); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     # TODO: following the old genimage code, to update the stateles-only files/directories | ||||
|     # # another file should be /opt/xcat/xcatdsklspost, but it seems  not necessary | ||||
|     xCAT::Utils->runcmd("mv $rootimg_dir/etc/init.d/statelite $rootimg_dir/.statebackup/statelite ", 0, 1) if ( -e "$rootimg_dir/etc/init.d/statelite"); | ||||
|     if ( -e "$rootimg_dir/usr/share/dracut" ) { | ||||
|         # currently only used for redhat families, not available for SuSE families | ||||
|         if ( -e "$rootimg_dir/etc/rc.sysinit.backup" ) { | ||||
|             xCAT::Utils->runcmd("mv $rootimg_dir/etc/rc.sysinit.backup $rootimg_dir/etc/rc.sysinit", 0, 1); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     #restore the install.netboot of xcat dracut module  | ||||
|     if(-e "$rootimg_dir/usr/lib/dracut/modules.d/97xcat/install"){ | ||||
|          xCAT::Utils->runcmd("mv $rootimg_dir/usr/lib/dracut/modules.d/97xcat/install $rootimg_dir/.statebackup/install", 0, 1); | ||||
|     } | ||||
|     xCAT::Utils->runcmd("cp /opt/xcat/share/xcat/netboot/rh/dracut_033/install.netboot $rootimg_dir/usr/lib/dracut/modules.d/97xcat/install", 0, 1); | ||||
|      | ||||
|  | ||||
|     my $xcat_packimg_tmpfile = "/tmp/xcat_packimg.$$"; | ||||
|     my $excludestr = "find . -xdev "; | ||||
|     my $includestr; | ||||
|     if ($exlistloc) { | ||||
|         my @excludeslist = split ',', $exlistloc; | ||||
|         foreach my $exlistlocname ( @excludeslist ) { | ||||
|             my $exlist; | ||||
|             my $excludetext; | ||||
|             open($exlist,"<",$exlistlocname); | ||||
|             system("echo -n > $xcat_packimg_tmpfile"); | ||||
|             while (<$exlist>) { | ||||
|                 $excludetext .= $_; | ||||
|             }    | ||||
|             close($exlist); | ||||
|        | ||||
|             #handle the #INLCUDE# tag recursively | ||||
|             my $idir = dirname($exlistlocname); | ||||
|             my $doneincludes=0; | ||||
|             while (not $doneincludes) { | ||||
|                 $doneincludes=1; | ||||
|                 if ($excludetext =~ /#INCLUDE:[^#^\n]+#/) { | ||||
|                     $doneincludes=0; | ||||
|                     $excludetext =~ s/#INCLUDE:([^#^\n]+)#/include_file($1,$idir)/eg;                  | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|  | ||||
|             my @tmp=split("\n", $excludetext); | ||||
|             foreach (@tmp) { | ||||
|                 chomp $_; | ||||
|                 s/\s*#.*//;      #-- remove comments  | ||||
|                 next if /^\s*$/; #-- skip empty lines | ||||
|                 if (/^\+/) { | ||||
|                     s/^\+//; #remove '+'	 | ||||
|                     $includestr .= "-path '". $_ ."' -o ";                 | ||||
|                 } else {  | ||||
|                     s/^\-//;  #remove '-' if any | ||||
|                     $excludestr .= "'!' -path '".$_."' -a "; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     # the files specified for statelite should be excluded | ||||
|     my @excludeStatelite = ("./etc/init.d/statelite", "./etc/rc.sysinit.backup", "./.statelite*", "./.default*", "./.statebackup*"); | ||||
|     foreach my $entry (@excludeStatelite) { | ||||
|         $excludestr .= "'!' -path '" . $entry . "' -a "; | ||||
|     } | ||||
|  | ||||
|    $excludestr =~ s/-a $//; | ||||
|    if ($includestr) { | ||||
|        $includestr =~ s/-o $//; | ||||
|        $includestr = "find . -xdev " .  $includestr; | ||||
|    } | ||||
|  | ||||
|   print "\nexcludestr=$excludestr\n\n includestr=$includestr\n\n"; # debug | ||||
|  | ||||
|    # add the xCAT post scripts to the image | ||||
|     unless ( -d "$rootimg_dir") { | ||||
|        $callback->({error=>["$rootimg_dir does not exist, run genimage -o $osver -p $profile on a server with matching architecture"], errorcode=>[1]}); | ||||
|        return; | ||||
|     } | ||||
|  | ||||
|    # some rpms like atftp mount the rootimg/proc to /proc, we need to make sure rootimg/proc is free of junk  | ||||
|    # before packaging the image | ||||
|    system("umount $rootimg_dir/proc"); | ||||
|    copybootscript($installroot, $rootimg_dir, $osver, $arch, $profile, $callback); | ||||
|    my $passtab = xCAT::Table->new('passwd'); | ||||
|    if ($passtab) { | ||||
|        my $pass = 'cluster'; | ||||
|        (my $pent) = $passtab->getAttribs({key=>'system',username=>'root'},'password'); | ||||
|        if ($pent and defined ($pent->{password})) { | ||||
|            $pass = $pent->{password}; | ||||
|        } | ||||
|        my $oldmask=umask(0077); | ||||
|        my $shadow; | ||||
|        open($shadow,"<","$rootimg_dir/etc/shadow"); | ||||
|        my @shadents = <$shadow>; | ||||
|        close($shadow); | ||||
|        open($shadow,">","$rootimg_dir/etc/shadow"); | ||||
|        # 1 - MD5, 5 - SHA256, 6 - SHA512 | ||||
|        unless (($pass =~ /^\$1\$/) || ($pass =~ /^\$5\$/) || ($pass =~ /^\$6\$/)) { | ||||
|           $pass = crypt($pass,'$1$'.xCAT::Utils::genpassword(8)); | ||||
|        } | ||||
|        print $shadow "root:$pass:13880:0:99999:7:::\n"; | ||||
|        foreach (@shadents) { | ||||
|            unless (/^root:/) { | ||||
|                print $shadow "$_"; | ||||
|            } | ||||
|        } | ||||
|        close($shadow); | ||||
|        umask($oldmask); | ||||
|    } | ||||
|  | ||||
|    # sync fils configured in the synclist to the rootimage | ||||
|    $syncfile = xCAT::SvrUtils->getsynclistfile(undef, $osver, $arch, $profile, "netboot", $imagename); | ||||
|    if (defined ($syncfile) && -f $syncfile | ||||
|        && -d $rootimg_dir) { | ||||
|             print "sync files from $syncfile to the $rootimg_dir\n"; | ||||
|            system("$::XCATROOT/bin/xdcp -i $rootimg_dir -F $syncfile"); | ||||
|    } | ||||
|  | ||||
|     my $verb = "Packing"; | ||||
|  | ||||
|     my $temppath; | ||||
|     my $oldmask; | ||||
|     unless ( -d $rootimg_dir) { | ||||
|        $callback->({error=>["$rootimg_dir does not exist, run genimage -o $osver -p $profile on a server with matching architecture"]}); | ||||
|        return; | ||||
|     } | ||||
|     $callback->({data=>["$verb contents of $rootimg_dir"]}); | ||||
|     unlink("$destdir/rootimg.gz"); | ||||
|     unlink("$destdir/rootimg.sfs"); | ||||
|     if ($method =~ /cpio/) { | ||||
|         if ( ! $exlistloc ) { | ||||
|             $excludestr = "find . -xdev |cpio -H newc -o | gzip -c - > ../rootimg.gz"; | ||||
|         }else { | ||||
|             chdir("$rootimg_dir"); | ||||
|             system("$excludestr >> $xcat_packimg_tmpfile");  | ||||
|             if ($includestr) { | ||||
|             	system("$includestr >> $xcat_packimg_tmpfile");  | ||||
|             } | ||||
|             #$excludestr =~ s!-a \z!|cpio -H newc -o | gzip -c - > ../rootimg.gz!; | ||||
|             $excludestr = "cat $xcat_packimg_tmpfile|cpio -H newc -o | gzip -c - > ../rootimg.gz"; | ||||
|         } | ||||
|         $oldmask = umask 0077; | ||||
|     } elsif ($method =~ /squashfs/) { | ||||
|       $temppath = mkdtemp("/tmp/packimage.$$.XXXXXXXX"); | ||||
|       chmod 0755,$temppath; | ||||
|       chdir("$rootimg_dir"); | ||||
|       system("$excludestr >> $xcat_packimg_tmpfile");  | ||||
|       if ($includestr) { | ||||
| 	  system("$includestr >> $xcat_packimg_tmpfile");  | ||||
|       } | ||||
|       $excludestr = "cat $xcat_packimg_tmpfile|cpio -dump $temppath";  | ||||
|     } else { | ||||
|        $callback->({error=>["Invalid method '$method' requested"],errorcode=>[1]}); | ||||
|     } | ||||
|     chdir("$rootimg_dir"); | ||||
|     `$excludestr`; | ||||
|     if ($method =~ /cpio/) { | ||||
|         chmod 0644,"$destdir/rootimg.gz"; | ||||
|         if ($dotorrent) { | ||||
|             my $currdir = getcwd; | ||||
|             chdir($destdir); | ||||
|             unlink("rootimg.gz.metainfo"); | ||||
|             system("ctorrent -t -u $dotorrent -l 1048576 -s rootimg.gz.metainfo rootimg.gz"); | ||||
|             chmod 0644, "rootimg.gz.metainfo"; | ||||
|             chdir($currdir); | ||||
|         } | ||||
|         umask $oldmask; | ||||
|     } elsif ($method =~ /squashfs/) { | ||||
|        my $flags; | ||||
|        if ($arch =~ /x86/) { | ||||
|           $flags="-le"; | ||||
|        } elsif ($arch =~ /ppc/) { | ||||
|           $flags="-be"; | ||||
|        } | ||||
|  | ||||
|        if( $osver =~ /rhels/ && $osver !~ /rhels5/) { | ||||
|            $flags=""; | ||||
|        } | ||||
|         | ||||
|        if (! -x "/sbin/mksquashfs" && ! -x "/usr/bin/mksquashfs" ) { | ||||
|           $callback->({error=>["mksquashfs not found, squashfs-tools rpm should be installed on the management node"],errorcode=>[1]}); | ||||
|           return; | ||||
|        } | ||||
|        my $rc = system("mksquashfs $temppath ../rootimg.sfs $flags"); | ||||
|        if ($rc) { | ||||
|           $callback->({error=>["mksquashfs could not be run successfully"],errorcode=>[1]}); | ||||
|           return; | ||||
|        } | ||||
|        $rc = system("rm -rf $temppath"); | ||||
|        if ($rc) { | ||||
|           $callback->({error=>["Failed to clean up temp space"],errorcode=>[1]}); | ||||
|           return; | ||||
|        } | ||||
|        chmod(0644,"../rootimg.sfs"); | ||||
|     } | ||||
|    system("rm -f $xcat_packimg_tmpfile"); | ||||
|      | ||||
|     # move the files in /.statebackup back to rootimg_dir | ||||
|     if ($rootimg_status) { #  statelite mode | ||||
|         foreach my $entry (keys %liteHash) { | ||||
|             my @tmp = split /\s+/, $entry; | ||||
|             my $filename = $tmp[1]; | ||||
|             my $fileopt = $tmp[0]; | ||||
|             if ($fileopt =~ m/link/) { | ||||
|                 chop $filename if ($filename =~ m/\/$/); | ||||
|                 xCAT::Utils->runcmd("rm -rf $rootimg_dir$filename", 0, 1); | ||||
|                 xCAT::Utils->runcmd("mv $rootimg_dir/.statebackup$filename $rootimg_dir$filename", 0, 1); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|          xCAT::Utils->runcmd("mv $rootimg_dir/.statebackup/install $rootimg_dir/usr/lib/dracut/modules.d/97xcat/install", 0, 1); | ||||
|         xCAT::Utils->runcmd("mv $rootimg_dir/.statebackup/statelite $rootimg_dir/etc/init.d/statelite", 0, 1); | ||||
|         xCAT::Utils->runcmd("rm -rf $rootimg_dir/.statebackup", 0, 1); | ||||
|     } | ||||
|  | ||||
|  | ||||
|    chdir($oldpath); | ||||
| } | ||||
|  | ||||
| ########################################################### | ||||
| # | ||||
| #  copybootscript - copy the xCAT diskless init scripts to the image | ||||
| # | ||||
| ############################################################# | ||||
| sub copybootscript { | ||||
|  | ||||
|     my $installroot  = shift; | ||||
|     my $rootimg_dir = shift; | ||||
|     my $osver  = shift; | ||||
|     my $arch = shift; | ||||
|     my $profile = shift; | ||||
|     my $callback = shift; | ||||
|     my @timezone = xCAT::TableUtils->get_site_attribute("timezone"); | ||||
|  | ||||
|     if ( -f "$installroot/postscripts/xcatdsklspost") { | ||||
|  | ||||
|         # copy the xCAT diskless post script to the image | ||||
|         mkpath("$rootimg_dir/opt/xcat");   | ||||
|  | ||||
|         copy ("$installroot/postscripts/xcatdsklspost", "$rootimg_dir/opt/xcat/xcatdsklspost"); | ||||
|         if($timezone[0]) { | ||||
| 	    copy ("$rootimg_dir/usr/share/zoneinfo/$timezone[0]", "$rootimg_dir/etc/localtime"); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         chmod(0755,"$rootimg_dir/opt/xcat/xcatdsklspost"); | ||||
|  | ||||
|     } else { | ||||
|  | ||||
| 	my $rsp; | ||||
|         push @{$rsp->{data}}, "Could not find the script $installroot/postscripts/xcatdsklspost.\n"; | ||||
|         xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|  | ||||
| 	#if ( -f "$installroot/postscripts/xcatpostinit") { | ||||
|         # copy the linux diskless init script to the image | ||||
|         #   - & set the permissions | ||||
|         #copy ("$installroot/postscripts/xcatpostinit","$rootimg_dir/etc/init.d/xcatpostinit"); | ||||
|  | ||||
|         #chmod(0755,"$rootimg_dir/etc/init.d/xcatpostinit"); | ||||
|  | ||||
|         # run chkconfig | ||||
|         #my $chkcmd = "chroot $rootimg_dir chkconfig --add xcatpostinit"; | ||||
|         #symlink "/etc/init.d/xcatpostinit","$rootimg_dir/etc/rc3.d/S84xcatpostinit"; | ||||
|         #symlink "/etc/init.d/xcatpostinit","$rootimg_dir/etc/rc4.d/S84xcatpostinit"; | ||||
|         #symlink "/etc/init.d/xcatpostinit","$rootimg_dir/etc/rc5.d/S84xcatpostinit"; | ||||
|         #my $rc = system($chkcmd); | ||||
|         #if ($rc) { | ||||
| 		#my $rsp; | ||||
|       #  	push @{$rsp->{data}}, "Could not run the chkconfig command.\n"; | ||||
|       #  	xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|       #      	return 1; | ||||
|       #  } | ||||
|     #} else { | ||||
| 	#my $rsp; | ||||
|     #    push @{$rsp->{data}}, "Could not find the script $installroot/postscripts/xcatpostinit.\n"; | ||||
|     #    xCAT::MsgUtils->message("E", $rsp, $callback); | ||||
|     #    return 1; | ||||
|     #} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| sub include_file | ||||
| { | ||||
|    my $file = shift; | ||||
|    my $idir = shift; | ||||
|    my @text = (); | ||||
|    unless ($file =~ /^\//) { | ||||
|        $file = $idir."/".$file; | ||||
|    } | ||||
|     | ||||
|    open(INCLUDE,$file) || \ | ||||
|        return "#INCLUDEBAD:cannot open $file#"; | ||||
|     | ||||
|    while(<INCLUDE>) { | ||||
|        chomp($_); | ||||
|        s/\s+$//;  #remove trailing spaces | ||||
|        next if /^\s*$/; #-- skip empty lines | ||||
|        push(@text, $_); | ||||
|    } | ||||
|     | ||||
|    close(INCLUDE); | ||||
|     | ||||
|    return join("\n", @text); | ||||
| } | ||||
|  | ||||
| =head3 parseLiteFiles | ||||
| In the liteentry table, one directory and its sub-items (including sub-directory and entries) can co-exist; | ||||
| In order to handle such a scenario, one hash is generated to show the hirarachy relationship | ||||
|  | ||||
| For example, one array with entry names is used as the input: | ||||
| my @entries = ( | ||||
|     "imagename bind,persistent /var/", | ||||
|     "imagename bind /var/tmp/", | ||||
|     "imagename tmpfs,rw /root/", | ||||
|     "imagename tmpfs,rw /root/.bashrc", | ||||
|     "imagename tmpfs,rw /root/test/", | ||||
|     "imagename bind /etc/resolv.conf", | ||||
|     "imagename bind /var/run/" | ||||
| ); | ||||
| Then, one hash will generated as: | ||||
| %hashentries = { | ||||
|           'bind,persistent /var/' => [ | ||||
|                                                  'bind /var/tmp/', | ||||
|                                                  'bind /var/run/' | ||||
|                                                ], | ||||
|           'bind /etc/resolv.conf' => undef, | ||||
|           'tmpfs,rw /root/' => [ | ||||
|                                            'tmpfs,rw /root/.bashrc', | ||||
|                                            'tmpfs,rw /root/test/' | ||||
|                                          ] | ||||
|         }; | ||||
|  | ||||
| Arguments: | ||||
|     one array with entrynames, | ||||
|     one hash to hold the entries parsed | ||||
|  | ||||
| Returns: | ||||
|     0 if sucucess | ||||
|     1 if fail | ||||
|  | ||||
| =cut | ||||
|  | ||||
|  | ||||
|  | ||||
| sub parseLiteFiles { | ||||
|     my ($flref, $dhref) = @_; | ||||
|     my @entries = @{$flref}; | ||||
|  | ||||
|  | ||||
|     foreach (@entries) { | ||||
|         my $entry = $_; | ||||
|         my @str = split /\s+/, $entry; | ||||
|         shift @str; | ||||
|         $entry = join "\t", @str; | ||||
|         my $file = $str[1]; | ||||
|         chop $file if ($file =~ m{/$}); | ||||
|         unless (exists $dhref->{"$entry"}) { | ||||
|             my $parent = dirname($file); | ||||
|             # to see whether $parent exists in @entries or not | ||||
|             unless ($parent =~ m/\/$/) { | ||||
|                 $parent .= "/"; | ||||
|             } | ||||
|             my @res = grep {$_ =~ m/\Q$parent\E$/} @entries; | ||||
|             my $found = scalar @res; | ||||
|  | ||||
|             if($found eq 1) { # $parent is found in @entries | ||||
| 		        # handle $res[0]; | ||||
| 		        my @tmpresentry=split /\s+/, $res[0]; | ||||
| 		        shift @tmpresentry; | ||||
| 		        $res[0] = join "\t", @tmpresentry; | ||||
|                 chop $parent; | ||||
|                 my @keys = keys %{$dhref}; | ||||
|                 my $kfound = grep {$_ =~ m/\Q$res[0]\E$/} @keys; | ||||
|                 if($kfound eq 0) { | ||||
|                     $dhref->{$res[0]} = []; | ||||
|                 } | ||||
|                 push @{$dhref->{"$res[0]"}}, $entry; | ||||
|             }else { | ||||
|                 $dhref->{"$entry"} = (); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| 1; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user