summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authorxiubuzhe <xiubuzhe@sina.com>2023-10-08 20:59:00 +0800
committerxiubuzhe <xiubuzhe@sina.com>2023-10-08 20:59:00 +0800
commit1dac2263372df2b85db5d029a45721fa158a5c9d (patch)
tree0365f9c57df04178a726d7584ca6a6b955a7ce6a /sbin
parentb494be364bb39e1de128ada7dc576a729d99907e (diff)
downloadsunhpc-1dac2263372df2b85db5d029a45721fa158a5c9d.tar.gz
sunhpc-1dac2263372df2b85db5d029a45721fa158a5c9d.tar.bz2
sunhpc-1dac2263372df2b85db5d029a45721fa158a5c9d.zip
first add files
Diffstat (limited to 'sbin')
-rwxr-xr-xsbin/build-sunhpc14
-rwxr-xr-xsbin/calcrollmd549
-rwxr-xr-xsbin/gen_root_pw10
-rwxr-xr-xsbin/insert-ethers742
-rwxr-xr-xsbin/kgen157
-rwxr-xr-xsbin/mksquashfsbin0 -> 211928 bytes
-rwxr-xr-xsbin/mom_gencfg559
-rwxr-xr-xsbin/restart-anaconda34
-rwxr-xr-xsbin/suncli38
-rwxr-xr-xsbin/sunyums178
-rwxr-xr-xsbin/unsquashfsbin0 -> 110544 bytes
11 files changed, 1781 insertions, 0 deletions
diff --git a/sbin/build-sunhpc b/sbin/build-sunhpc
new file mode 100755
index 0000000..ebe0777
--- /dev/null
+++ b/sbin/build-sunhpc
@@ -0,0 +1,14 @@
+#!/bin/bash
+# first : initialize the sunhpc database
+# second : add cluster data to database.
+WHERE=$1
+HERE=`pwd`
+SUNHPC=/opt/sunhpc/bin/sunhpc
+
+# initialize database
+/opt/sunhpc/sbin/init-sunhpcDB
+
+# add fronetend node to database
+MYNAME=`hostname -s`
+$SUNHPC add host $MYNAME rack=0 rank=1 member=server 2> /tmp/sunhpc-initdb.log
+$SUNHPC add catindex $MYNAME category=host 2>> /tmp/sunhpc-initdb.log
diff --git a/sbin/calcrollmd5 b/sbin/calcrollmd5
new file mode 100755
index 0000000..d6bcfe1
--- /dev/null
+++ b/sbin/calcrollmd5
@@ -0,0 +1,49 @@
+#!/usr/bin/python
+#coding:utf-8
+
+import os
+import sys
+import hashlib
+
+def GetFileMD5(filename):
+ myhash = hashlib.md5()
+ with open(filename, 'rb') as f:
+ while True:
+ b = f.read(8096)
+ if not b:
+ break
+ myhash.update(b)
+ return myhash.hexdigest()
+
+def running(path):
+ rpmlist = []
+ for root, dirs,files in os.walk(path):
+ if root.endswith("RedHat"):
+ (roll, version, arch) = root.split(os.path.sep)[-4:-1]
+ rollname = "%s/%s/%s" % (roll, version, arch)
+ rollvers = "%s-%s-%s" % (roll, version, arch)
+
+ baseDirs = os.path.join(rollname, 'RedHat', 'RPMS')
+ for f in os.listdir(baseDirs):
+ rpmname = os.path.join(baseDirs, f)
+ md5sum = GetFileMD5(rpmname)
+ result = "%s %s %s" % (md5sum, rollvers, rpmname)
+ rpmlist.append(result)
+
+ return rpmlist
+
+if __name__ == "__main__":
+ args = sys.argv
+ if len(args) < 2:
+ print " - Must to be supply an path."
+ sys.exit(0)
+
+ path = args[1]
+ if os.path.isdir(path) and path != '/':
+ path = os.path.abspath(path)
+ rpmlist = running(path)
+
+ rfile = os.path.join(path, 'rollslist')
+ with open(rfile, 'w') as f:
+ f.write('\n'.join(rpmlist))
+ f.write('\n')
diff --git a/sbin/gen_root_pw b/sbin/gen_root_pw
new file mode 100755
index 0000000..ec8c378
--- /dev/null
+++ b/sbin/gen_root_pw
@@ -0,0 +1,10 @@
+#!/usr/bin/env python3
+
+import crypt
+import string
+import random
+def get_pw():
+ pw = random.random()
+ return crypt.crypt(str(pw))
+if __name__ == '__main__':
+ print (get_pw())
diff --git a/sbin/insert-ethers b/sbin/insert-ethers
new file mode 100755
index 0000000..b15aad1
--- /dev/null
+++ b/sbin/insert-ethers
@@ -0,0 +1,742 @@
+#!/opt/sunpy3/bin/python3
+#coding:utf-8
+import os
+import sys
+import time
+import snack
+import getopt
+import syslog
+import sunhpc
+import signal
+import sqlite3
+import logging
+import sunhpc.invoke
+from sunhpc.core.utils import InsertError
+from sunhpc.core.utils import InsertDone
+from sunhpc.core.utils import DumpError
+
+logging.basicConfig(filename="/tmp/sunhpc.log", level=logging.INFO)
+log = logging.getLogger("Insertnodes ")
+
+try:
+ from rhpl.translate import _, N_
+ import rhpl.translate as translate
+ translate.textdomain('insert-ethers')
+except:
+ from gettext import gettext as _
+
+class ServiceController(object):
+ """Handler system services functions"""
+
+ def __init__(self):
+ self.services = {}
+ self.ignoreList = []
+
+ self.plugins = []
+ self.plugindir = os.path.abspath(
+ '/opt/sunhpc/var/plugins')
+
+ def igore(self, service):
+ if service not in self.ignoreList:
+ self.ignoreList.append(service)
+
+ def isIgnored(self, service):
+ return service in self.ignoreList
+
+ def restart(self, service):
+ for name in self.services[service]:
+ if service not in self.ignoreList:
+ eval('self.restart_%s()' % name)
+
+ def loadPlugins(self, app):
+ # load plug in /opt/sunhpc/var/plugins dirctorys
+ if not os.path.exists(self.plugindir):
+ return
+
+ # 将plugin目录添加到模块自动导入.
+ if self.plugindir not in sys.path:
+ sys.path.append(self.plugindir)
+
+ info = _("insert-ethers loading plugins: ")
+
+ # 只载入insertnodes相关的模块.
+ modlist = os.listdir(self.plugindir + '/insertnodes')
+ modlist.sort()
+ for f in modlist:
+ modname, ext = os.path.splitext(f)
+ if modname == '__init__' or \
+ modname == '__pycache__' or ext != '.py':
+ continue
+
+ info += "%s " % modname
+ mods = __import__('insertnodes.%s' % modname)
+ mod = getattr(mods, modname)
+ try:
+ # 导入这个模块中的Plugin类.
+ plugin_class = getattr(mod, 'Plugin')
+ # 将app类以参数形式传入这个类使用.
+ # p是这个Plugin类,包含其方法和函数.
+ p = plugin_class(app)
+ self.plugins.append(p)
+ except:
+ info += _("(invalid, skipping) ")
+
+ # 将模块导入信息输出到系统日志.
+ log.info('Load KS Plugins: %s' % info)
+ syslog.syslog(info)
+
+ def logError(self, o=''):
+ "Logs the last execption to syslog"
+ oops = "%s threw exception '%s'" % (o, sys.exc_info())
+ syslog.syslog(oops)
+
+ def added(self, nodename):
+ """Tell all plugins this node has been added"""
+ for p in self.plugins:
+ try:
+ p.added(nodename)
+ except:
+ self.logError(p)
+
+ def removed(self, nodename):
+ """Tell all plugins this node has been removed"""
+ for p in self.plugins:
+ try:
+ p.removed(nodename)
+ except:
+ self.logError(p)
+
+ def done(self):
+ """Tell all plugins we are finished"""
+ for p in self.plugins:
+ try:
+ p.done()
+ except:
+ self.logError(p)
+
+ def update(self):
+ """Tell all plugins we to reload"""
+ for p in self.plugins:
+ try:
+ p.update()
+ except:
+ self.logError(p)
+
+class GUI(object):
+ """Use the snack gui class"""
+
+ def __init__(self):
+ self.screen = None
+
+ def startGUI(self):
+ self.screen = snack.SnackScreen()
+
+ def endGUI(self):
+ self.screen.finish()
+
+ def errorGUI(self, message, l1=_("Quit"), l2=None):
+ return self.modalGUI(str(message), _("Error"), l1, l2)
+
+ def warningGUI(self, message, l1=_("OK"), l2=None):
+ return self.modalGUI(str(message), _("Warning"), l1, l2)
+
+ def infoGUI(self, message, l1=_("OK"), l2=None):
+ return self.modalGUI(str(message), _("Information"), l1, l2)
+
+ def modalGUI(self, message, title, l1, l2):
+ form = snack.GridForm(self.screen, title, 2, 2)
+
+ textbox = snack.TextboxReflowed(40, message)
+ form.add(textbox, 0, 0)
+ if not l2:
+ b1 = snack.Button(l1)
+ form.add(b1, 0, 1)
+ else:
+ b1 = snack.Button(l1)
+ b2 = snack.Button(l2)
+ form.add(b1, 0, 1)
+ form.add(b2, 1, 1)
+
+ if form.runOnce() == b1:
+ return 0
+ else:
+ return 1
+
+
+class InsertEthers(GUI):
+
+ def __init__(self, app):
+ super(InsertEthers, self).__init__()
+
+ self.sql = app
+ self.cmd = None
+ self.controller = ServiceController()
+ self.cabinet = 0
+ self.rank = -1
+ self.replace = ''
+ self.maxNew = -1
+ self.remove = 0
+ self.membership = None
+ self.basename = None
+ self.restart_srvs = 0
+ self.inserted = []
+ self.kickstarted = {}
+ self.excludeMacList = []
+ self.dist_lockFile = '/var/lock/sunhpc-dist'
+ self.osname = 'linux'
+
+
+ self.doRestart = 1
+ # 排除的mac地址
+ self.subnet = 'private' # Internal Network
+ self.hostname = None
+ self.kickstartable = True
+
+ def setMembershipName(self, membership_name):
+ self.membership = membership_name
+
+ def setRemove(self, host):
+ self.replace = host
+ self.remove = 1
+
+ def startGUI(self):
+
+ GUI.startGUI(self)
+ self.form = snack.GridForm(self.screen, _("Install the system using pxelinux"), 1, 1)
+
+ self.textbox = snack.Textbox(50, 4, "", scroll=1)
+ self.form.add(self.textbox, 0, 0)
+
+ self.screen.drawRootText(0, 0, _("SunHPC(%s) -- version %s") %
+ (self.sql.usage_name,
+ self.sql.usage_version))
+
+ self.screen.drawRootText(0, 1, _("Opened kickstart access to %s network") %
+ self.sql.getPrivateNet())
+
+ self.screen.pushHelpLine(' ')
+
+ def statusGUI(self):
+ """Updates the list of nodes in 'Inserted Appliances' windows"""
+ macs_n_names = ''
+ ks = ''
+ for (mac, name) in self.inserted:
+ if name not in self.kickstarted:
+ ks = ''
+ elif self.kickstarted[name] == 0:
+ ks = '( )'
+ elif self.kickstarted[name] == 200:
+ ks = '(*)'
+ else: # An error
+ ks = '(%s)' % self.kickstarted[name]
+ macs_n_names += '%s\t%s\t%s\n' % (mac, name, ks)
+
+ self.textbox.setText(_(macs_n_names))
+
+ self.form.draw()
+ self.screen.refresh()
+
+ def waitGUI(self):
+
+ not_done = ''
+ hosts = list(self.kickstarted.keys())
+ hosts.sort()
+ for name in hosts:
+ status = self.kickstarted[name]
+ if status != 200:
+ ks = '( )'
+ if status:
+ ks = '(%s)' % status
+ not_done += '%s \t %s\n' % (name, ks)
+
+ form = snack.GridForm(self.screen,
+ _("Not kickstarted, please wait..."), 1, 1)
+ textbox = snack.Textbox(35, 4, not_done, scroll=1)
+ form.add(textbox, 0,0)
+
+ form.draw()
+ self.screen.refresh()
+ time.sleep(1)
+ self.screen.popWindow()
+
+ def membershipGUI(self):
+ self.kickstartable = True
+ self.basename = 'compute'
+ self.setMembershipName(self.basename)
+
+ def initializeRank(self):
+ query = 'select rank,max(rank) from nodes where rack = %d group by rack' % (self.cabinet)
+
+ if self.sql.search(query) > 0:
+ (rank, max_rank) = self.sql.fetchone()
+ self.rank = max_rank + 1
+ else:
+ self.rank = 0
+
+ def getnextIP(self, subnet):
+
+ args = [ subnet ]
+ if self.sql.ipIncrement != -1:
+ args.append('increment=%d' % self.sql.ipIncrement)
+
+ text = self.cmd.command('report.nextip', args)
+ if len(text) == 0:
+ raise Exception("Unable to get next IP address")
+
+ return text.strip()
+
+ def addit(self, mac, nodename, ip):
+
+ self.cmd.command('add.host', [nodename, 'os=' + self.osname,
+ 'rack=' + str(self.cabinet), 'rank=' + str(self.rank)])
+
+ self.cmd.command('add.host.interface', [nodename, 'eth0',
+ 'ip=' + ip, 'mac=' + mac, 'subnet=' + self.subnet])
+
+ self.sql.commit()
+
+ self.controller.added(nodename)
+ self.restart_srvs = 1
+
+ self.sql.commit()
+
+ list = [(mac, nodename)]
+ list.extend(self.inserted)
+ self.inserted = list
+ self.kickstarted[nodename] = 0
+
+ def discover(self, mac, dev):
+ """如果存在数据库中返回真"""
+ retval = False
+ query = 'select mac from networks where mac="%s"' % (mac)
+ if not self.sql.search(query):
+ nodename = self.getNodename()
+ log.info('GetNodename: %s' % nodename)
+
+ ipaddr = self.getnextIP(self.subnet)
+ self.addit(mac, nodename, ipaddr)
+ log.info('Addit Host: %s/%s/%s' % (nodename, ipaddr, mac))
+ self.printDiscovered(mac)
+
+ retval = True
+ return retval
+
+ def printDiscovered(self, mac):
+
+ form = snack.GridForm(self.screen,
+ _("Discovered New Appliance"), 1, 1)
+
+ new_app = _("Discovered a new appliance with MAC (%s)") % (mac)
+ textbox = snack.Textbox(len(new_app), 1, new_app)
+ form.add(textbox, 0, 0)
+
+ form.draw()
+ self.screen.refresh()
+ time.sleep(2)
+ self.screen.popWindow()
+
+ def getNodename(self):
+ if self.hostname is not None:
+ return self.hostname
+ else:
+ return '%s-%d-%d' % (self.basename, self.cabinet, self.rank)
+
+ def listenDHCP(self, line):
+
+ tokens = line.split()[:-1]
+ if len(tokens) > 9 and tokens[4] == 'dhcpd:' and \
+ (tokens[5] in ['DHCPDISCOVER', 'BOOTREQUEST']):
+
+ Dev = tokens[9].replace(':','').strip()
+ Mac = tokens[7].strip()
+
+ # 在DHCPDISCOVER from macaddr via eth0,这里面的eth0
+ # 是指主节点开启了dhcpd的网卡名称,也是private网卡名称.
+ # 但这并非是计算节点的网卡名称.
+ self.sql.execute("""select networks.device from
+ networks, subnets, nodes where
+ subnets.name='%s' and nodes.name='%s' and
+ networks.subnet=subnets.id and networks.node=nodes.id""" % (
+ self.subnet, self.sql.newdb.getFrontendName()))
+
+ # 如果有需要排除的Mac地址则在这里配置.
+ if Mac in self.excludeMacList: return
+
+ # 如果不匹配主节点DHCP服务的网卡名称,
+ subnet_dev = self.sql.fetchone()[0]
+ if Dev != subnet_dev: return
+
+ # 如果已经完成添加的mac地址,放弃这次请求.
+ if not self.discover(Mac, Dev): return
+
+ log.info('Discover New MAC: %s' % Mac)
+ self.statusGUI()
+
+ if self.maxNew > 0:
+ self.maxNew -= 1
+ if self.maxNew == 0:
+ raise InsertDone(_("Suggest Done"))
+
+ # 自动增加主机名称的Rank号.
+ self.rank = self.rank + 1
+
+ elif len(tokens) > 6 and tokens[4] == 'last' and \
+ tokens[5] == 'message' and tokens[6] == 'repeated':
+
+ shortname = os.uname()[1].split('.')[0]
+ if tokens[3] == shortname:
+ os.system('/usr/bin/systemctl restart syslog >/dev/null 2>&1')
+
+ def monitoring(self):
+ # 监控日志
+ mslog = open('/var/log/messages', 'r')
+ mslog.seek(0, 2)
+
+ kslog = open('/var/log/httpd/access_log', 'r')
+ kslog.seek(0, 2)
+
+ self.screen.pushHelpLine(
+ _(" Press <F8> to quit, press <F9> to force quit"))
+ self.form.addHotKey('F8')
+ self.form.addHotKey('F9')
+ self.form.setTimer(1000)
+
+ self.statusGUI()
+
+ result = self.form.run()
+ suggest_done = 0
+ done = 0
+ log.info('Monitoring Log: OK')
+ while not done:
+
+ # 监控系统日志中的dhcpd信息.
+ syslog_line = mslog.readline()
+ if syslog_line and not suggest_done:
+ try:
+ self.listenDHCP(syslog_line)
+ except InsertDone:
+ suggest_done = 1
+
+ except (sunhpc.core.utils.CommandError, InsertError) as msg:
+ self.warningGUI(msg)
+ continue
+
+ # 监控日志中的pxelinux信息.
+ access_line = kslog.readline()
+ if access_line:
+ try:
+ self.listenKS(access_line)
+ except InsertError as msg:
+ self.warningGUI(msg)
+ continue
+ #
+ result = self.form.run()
+ done = self.checkDone(result, suggest_done)
+
+ log.info('Restarting services status: %s' % self.restart_srvs)
+ if self.restart_srvs:
+ log.info('Start restart services ...')
+ form = snack.GridForm(self.screen, _("Restarting Services"), 1, 1)
+ message = _("Restarting Services...")
+ textbox = snack.Textbox(len(message), 1, message)
+ form.add(textbox, 0, 0)
+ form.draw()
+
+ self.screen.refresh()
+ self.controller.done()
+ self.screen.popWindow()
+
+ mslog.close()
+ self.endGUI()
+
+ def listenKS(self, line):
+ """Look in log line for a kickstart request."""
+
+ # Track accesses both with and without local certs.
+ interesting = line.count('install/sbin/kickstart.cgi') \
+ or line.count('install/sbin/public/kickstart.cgi') \
+ or line.count('install/sbin/public/jumpstart.cgi')
+ if not interesting:
+ return
+
+ fields = line.split()
+ try:
+ status = int(fields[8])
+ log.info('Kickstart Code: %s' % status)
+ except:
+ raise InsertError(_("Apache log file not well formed!"))
+
+ nodeid = int(self.sql.getNodeId(fields[0]))
+ self.sql.execute('select name from nodes where id=%d' % nodeid)
+ try:
+ name, = self.sql.fetchone()
+ except:
+ if status == 200:
+ raise InsertError( _("Unknown node %s got a kickstart file!") % fields[0])
+ return
+
+ log.info('Kickstart NodeID %s->%s' % (name, nodeid))
+ if name not in self.kickstarted:
+ return
+
+ log.info('Change KS Status %s->%s' % (name, status))
+ self.kickstarted[name] = status
+ self.statusGUI()
+
+ def checkDone(self, result, suggest_done):
+
+ if result == 'TIMER' and not suggest_done:
+ return 0
+
+ if result == 'F9': return 1
+
+ if not self.kickstartable: return 1
+
+ ok = 1
+ for status in self.kickstarted.values():
+ if status != 200:
+ ok = 0
+ break
+
+ if not ok:
+ if result == 'F8':
+ self.waitGUI()
+ else:
+ if suggest_done or result == 'F8':
+ return 1
+ return 0
+
+ def distDone(self):
+ if os.path.exists(self.dist_lockFile):
+ self.warningGUI(_("Sunhpc distribution is not ready\n\n")
+ + _("Please wait for 'sunhpc create distro' to complete\n"))
+ return 0
+ return 1
+
+ def run(self):
+
+ self.cmd = sunhpc.commands.Command(self.sql.newdb)
+ try:
+ self.cmd.command('check.services', [])
+ log.info('Check services: OK')
+ except sunhpc.core.utils.CommandError as err:
+ sys.stderr.write('error - ' + str(err) + '\n')
+ return
+
+ # 开始启动界面
+ self.startGUI()
+ log.info('Start Daemon GUI: OK')
+
+ # make sure 'sunhpc create distro' is build finished.
+ if not self.distDone():
+ self.endGUI()
+ return
+
+ self.controller.loadPlugins(self.sql)
+ try:
+ if self.remove:
+ self.endGUI()
+ self.controller.done()
+ print ('Removed node %s' % self.replace)
+ return
+
+ # 初始化Member界面信息
+ self.membershipGUI()
+ # 初始化Rank信息
+ self.initializeRank()
+
+ if self.hostname:
+ # 检查给与的主机名是否有效.
+ self.checkHostNameValidity(self.hostname)
+
+ except (sunhpc.core.utils.CommandError, InsertError) as msg:
+ self.errorGUI(msg)
+ self.endGUI()
+ sys.stderr.write(_("%s\n") % str(msg))
+ return
+
+ log.info('Start Monitoring ...')
+ self.monitoring()
+
+class App(sunhpc.core.sql.Application):
+
+ def __init__(self, argv=None):
+ sunhpc.core.sql.Application.__init__(self, argv)
+
+ if not argv:
+ argv = sys.argv
+
+ self.args = []
+ self.caller_args = argv[1:]
+ self.usage_name = 'Kamaitachi'
+ self.usage_version = '1.0.0'
+ self.usage_command = os.path.basename(argv[0])
+
+ self.getopt = sunhpc.core.utils.Struct()
+ # 短参数
+ self.getopt.s = []
+ # 长参数
+ self.getopt.l = [ ('help', 'display the command help infomation'),
+ ('version', 'Display the sunhpc version')
+ ]
+
+ try:
+ # unset our locale
+ del os.environ['LANG']
+ except KeyError:
+ pass
+
+ self.dist = None
+ self.doUpdate = 0
+ self.lockFile = '/var/lock/insert-ethers'
+ self.insertor = InsertEthers(self)
+ self.controller = ServiceController()
+ self.ipIncrement = -1
+ self.doPublicMode = 0
+
+ self.getopt.l.extend([
+ ('remove=', 'remove an hostname')
+ ])
+
+ def getArgs(self):
+ return self.args
+
+ def setArgs(self, list):
+ self.args = list
+
+ def getPrivateNet(self):
+ net = self.getHostAttr('localhost', 'Kickstart_PrivateNetwork')
+ mask = self.getHostAttr('localhost', 'Kickstart_PrivateNetmask')
+ return "%s/%s" % (net, mask)
+
+ def parseArgs(self, rcbase=None):
+ """解析参数"""
+
+ args = self.getArgs()
+
+ # 设置参数
+ self.setArgs(self.caller_args)
+
+ # 开始解析参数
+ self.parseCommandLine()
+
+ def parseCommandLine(self):
+
+ # 使用 getopt 类中的 parse函数解析命令行
+
+ # 解析短参数形式
+ short = ''
+ for e in self.getopt.s:
+ if type(e) == type(()):
+ # 取参数左值
+ short = short + e[0]
+ else:
+ short = short + e
+
+ # 解析长参数形式
+ long = []
+ for e in self.getopt.l:
+ if type(e) == type(()):
+ # 取参数左值
+ long.append(e[0])
+ else:
+ long.append(e)
+
+ try:
+ opts, args = getopt.getopt(self.args, short, long)
+ except getopt.GetoptError as msg:
+ sys.stderr.write('error - %s\n' % msg)
+ self.usage()
+ sys.exit(1)
+
+ for c in opts:
+ self.parseArg(c)
+
+ def parseArg(self, c):
+
+ if c[0] in ('-h', '--help'):
+ self.usage()
+ sys.exit(0)
+
+ elif c[0] in ('version', '--version'):
+ print (self.getClusterVersion())
+ elif c[0] == '--remove':
+ self.insertor.setRemove(c[1])
+ return 0
+
+ def getClusterVersion(self):
+ return "SunhpcOS (%s) for version - %s" % (
+ self.cmd.release, self.cmd.version)
+
+ def usage(self):
+ argDict = {}
+ for e in self.getopt.s:
+ if type(e) == type(()):
+ argDict['-%s' % e[0]] = e[1]
+ else:
+ argDict['-%s' % e] = ''
+
+ for l in self.getopt.l:
+ if type(l) == type(()):
+ argDict['--%s' % l[0]] = l[1]
+ else:
+ argDict['--%s' % l] = ''
+
+ if not argDict: return
+ maxlen = max(map(len, argDict.keys()))
+ print ('\nUsage: %s [options] command infomations' % self.usage_command)
+ for k in argDict:
+ keys = k.ljust(maxlen)
+ vals = argDict[k]
+ print (' %s\t%s' % (keys, vals))
+ print ('If you have any questions, please contact info@sunhpc.com')
+
+ def run(self):
+ self.connect()
+
+ if os.path.isfile(self.lockFile):
+ self.cmd.abort('lock file %s exists.' % self.lockFile)
+ else:
+ os.system('touch %s' % self.lockFile)
+
+ if self.doPublicMode:
+ self.insertor.runPublicOnly()
+ else:
+ self.insertor.run()
+
+ self.cleanup()
+
+ def cleanup(self):
+ try:
+ os.unlink(self.lockFile)
+ except:
+ pass
+
+if __name__ == "__main__":
+
+ try:
+ (width, heigh) = shutil.get_terminal_size()
+ except:
+ width = 80
+ os.environ['COLUMNS'] = str(width)
+ log.info('starting insert-node ...')
+
+ app = App(sys.argv)
+ app.parseArgs()
+ try:
+ app.run()
+ except Exception as msg:
+ app.cleanup()
+ if app.insertor and app.insertor.screen:
+ app.insertor.endGUI()
+ sys.stderr.write('error - ' + str(msg) + '\n')
+ import traceback
+ traceback.print_exc()
+ sys.exit(1)
+
+ finally:
+ if os.path.exists(app.lockFile):
+ os.unlink(app.lockFile)
+
+
+
diff --git a/sbin/kgen b/sbin/kgen
new file mode 100755
index 0000000..fa01d54
--- /dev/null
+++ b/sbin/kgen
@@ -0,0 +1,157 @@
+#!/opt/sunpy3/bin/python3
+#coding:utf-8
+import os,sys
+import getopt
+import sunhpc.invoke
+from xml.sax._exceptions import SAXParseException
+class App(sunhpc.core.database.ApplicationSQL):
+
+ def __init__(self, argv=None):
+ sunhpc.core.database.ApplicationSQL.__init__(self)
+
+ if not argv:
+ argv = sys.argv
+
+ self.args = []
+ self.caller_args = argv[1:]
+ self.usage_name = 'Kickstart Generator'
+ self.usage_version = '1.0'
+ self.usage_command = os.path.basename(argv[0])
+ self.sections = []
+
+ self.os = os.uname()[0].lower()
+ self.arch = os.uname()[4]
+ osGenerator = getattr(sunhpc.core.xmlgen, 'Generator_%s' % self.os)
+ self.generator = osGenerator()
+ self.generator.setArch(self.arch)
+ self.generator.setOS(self.os)
+
+ self.getopt = sunhpc.core.utils.Struct()
+ self.getopt.s = [('h', 'help infomation'), ('a', 'architecture')]
+ self.getopt.l = [('arch=', 'architecture'),
+ ('section=', 'name'),
+ ('postonly', 'show post'),
+ ]
+ def usage(self):
+ argDict = {}
+ for e in self.getopt.s:
+ if type(e) == type(()):
+ argDict['-%s' % e[0]] = e[1]
+ else:
+ argDict['-%s' % e] = ''
+
+ for l in self.getopt.l:
+ if type(l) == type(()):
+ argDict['--%s' % l[0]] = l[1]
+ else:
+ argDict['--%s' % l] = ''
+
+ if not argDict: return
+ maxlen = max(map(len, argDict.keys()))
+ print ('\nUsage: %s [options] command infomations' % self.usage_command)
+ for k in argDict:
+ keys = k.ljust(maxlen)
+ vals = argDict[k]
+ print (' %s\t%s' % (keys, vals))
+ print ('If you have any questions, please contact info@sunhpc.com')
+
+ def parseArg(self, c):
+ if c[0] in ('-h', '--help'):
+ self.usage()
+ sys.exit(-1)
+ elif c[0] in ('-a', '--arch'):
+ self.generator.setArch(c[1])
+ elif c[0] == '--section':
+ self.sections += c[1].split()
+ elif c[0] == '--postonly':
+ self.sections.append('post')
+ else:
+ return 0
+ return 1
+
+ def parseArgs(self):
+ self.parseCommandLine()
+
+ def parseCommandLine(self):
+ # 解析短参数形式
+ short = ''
+ for e in self.getopt.s:
+ if type(e) == type(()):
+ # 取参数左值
+ short = short + e[0]
+ else:
+ short = short + e
+
+ # 解析长参数形式
+ long = []
+ for e in self.getopt.l:
+ if type(e) == type(()):
+ # 取参数左值
+ long.append(e[0])
+ else:
+ long.append(e)
+ try:
+ opts, args = getopt.getopt(self.caller_args, short, long)
+ except getopt.GetoptError as msg:
+ sys.stderr.write('error - %s\n' % msg)
+ self.usage()
+ sys.exit(1)
+
+ for c in opts:
+ self.parseArg(c)
+
+ def run(self):
+
+ if self.args:
+ fe = open(self.args[0], 'r')
+ else:
+ fe = sys.stdin
+
+ self.generator.parse(fe.read())
+ print ('#')
+ print ('# %s version %s' % (self.usage_name, self.usage_version))
+ print ('#')
+
+ sections = self.sections
+ if not sections:
+ sections = ['order', 'debug', 'main', 'packages', 'pre', 'post']
+
+ plist = []
+ for s in sections:
+ plist += self.generator.generate(s)
+
+ for line in plist:
+ print (line.rstrip())
+
+if __name__ == "__main__":
+ app = App(sys.argv)
+ app.parseArgs()
+ try:
+ app.run()
+ except sunhpc.core.exceptions.KickstartError as msg:
+ sys.stderr.write("kgen error - %s\n" % msg)
+ sys.exit(-1)
+
+ except SAXParseException as msg:
+ sys.stderr.write("kgen XML parse exception: %s\n" % msg)
+ sys.exit(-1)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sbin/mksquashfs b/sbin/mksquashfs
new file mode 100755
index 0000000..109ea23
--- /dev/null
+++ b/sbin/mksquashfs
Binary files differ
diff --git a/sbin/mom_gencfg b/sbin/mom_gencfg
new file mode 100755
index 0000000..f676b59
--- /dev/null
+++ b/sbin/mom_gencfg
@@ -0,0 +1,559 @@
+#!/usr/bin/perl
+# *****************************************************************************
+#
+# Copyright 2011 Zuse Institute Berlin
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+#
+# Please send comments to kallies@zib.de
+#
+# *****************************************************************************
+# Purpose: - called from /etc/init.d/pbs_mom during start actions.
+# - creates /var/spool/torque/mom_priv/mom.layout
+# - creates/modifies /dev/cpuset/torque
+# Prereq: - hwloc >= 1.1, http://www.open-mpi.org/projects/hwloc/
+# - Sys::Hwloc >= 0.09, http://search.cpan.org/~bka/
+# Install: Install this script on each UV rack
+# /opt/torque/Scripts/mom_gencfg root:root -rwxr-xr-x
+# Config: Set MOM_GENCFG=/opt/torque/Scripts/mom_gencfg
+# in /etc/init.d/pbs_mom for UV, execute $MOM_GENCFG before
+# starting the pbs_mom daemon.
+# MOM_GENCFG can be overridden in /etc/sysconfig/pbs_mom.
+# *****************************************************************************
+# $Id: mom_gencfg,v 1.1.2.1 2011/01/17 10:12:46 acountin Exp $
+# *****************************************************************************
+
+#
+# *** Instructions for use ***
+#
+# 1. Install hwloc - see contrib/hwloc_install.sh. This should already be done since
+# TORQUE needs hwloc for its cpuset implementation starting in 4.0
+# 2. Install Sys::Hwloc from CPAN
+# 3. Set $PBS_HOME to the proper value if not already set
+# 4. Update the variables in the section 'Config Definitions' Especially update firstNodeId
+# and nodesPerBoard if desired.
+# firstNodeId should be set above 0 if you have a root cpuset that you wish to exclude
+# nodesPerBoard is the number of numa nodes per board. Each node is defined in the
+# directory /sys/devices/system/node, in a subdirectory node<node index>
+# 5. Backup your current file, just in case a variable is set incorrectly or neglected
+# 6. Run this script and enjoy the layout file
+#
+#
+
+
+use strict;
+
+use lib qw(
+ /usr/lib/perl5
+ /usr/lib/perl5/site_perl
+ );
+
+use Sys::Hostname;
+use File::Basename;
+use Getopt::Long qw(:config no_ignore_case);
+use autouse 'Pod::Usage' => qw(pod2usage);
+use Sys::Hwloc 0.09;
+
+my $progName = basename($0);
+my $hostName = hostname();
+
+$SIG{__DIE__} = \&xDie;
+
+# ==============================================================================
+# Setup needed before init
+# ==============================================================================
+
+BEGIN: {
+ die "This script needs at least hwloc-1.1\n" unless HWLOC_XSAPI_VERSION() >= 0x00010100;
+}
+
+# ==============================================================================
+# Config definitions
+# ==============================================================================
+
+my $hostNames = undef; # hostname pattern to be run on, undef to skip test
+my $cpusetFsName = '/dev/cpuset'; # the name of the cpuset file system
+my $cpusetBaseName = '/torque'; # the name of the parent cpuset of a job's cpuset
+my $mkdirCmd = '/bin/mkdir'; # the path to the mkdir command
+my $catCmd = '/bin/cat'; # the path to the cat command
+my $echoCmd = '/bin/echo'; # the path to the echo command
+my $momCfgDir = 'mom_priv'; # the directory where MOM configs are stored
+my $momLayoutFile = 'mom.layout'; # the name of the MOM layout file
+my $firstNodeId = 0; # ID of 1st NUMA node to be used by Torque (start with 0)
+my $lastNodeId = undef; # ID of last NUMA node to be used (undef means last available)
+my $nodesPerBoard = 1; # number of NUMA nodes per nodeboard
+my %cpusetConf = (
+ cpus => undef, # undef means auto-generate
+ mems => undef, # undef means auto-generate
+ cpu_exclusive => 1, #
+ mem_exclusive => 1, #
+ );
+my %options = (
+ -doLayout => 1, # generate mom.layout
+ -withCpus => 1, # include cpus in mom.layout
+ -withMems => 1, # include mems in mom.layout
+ -doCpuset => 1, # generate/modify /torque cpuset
+ -withSmt => 1, # include logical processors running on the same core
+ -verbose => undef, # be verbose to STDERR
+ -dryRun => undef, # no actions, just tell what would be done
+ );
+
+# ==============================================================================
+# Command line options
+# ==============================================================================
+
+GetOptions(
+ "layout!" => \$options{-doLayout},
+ "cpus!" => \$options{-withCpus},
+ "mems!" => \$options{-withMems},
+ "smt!" => \$options{-withSmt},
+ "cpuset!" => \$options{-doCpuset},
+ "dry-run!" => \$options{-dryRun},
+ "verbose!" => \$options{-verbose},
+ "help|?" => sub { usage(0) },
+ "man" => sub { manPage() },
+ ) or usage(2);
+
+if($options{-dryRun}) {
+ $options{-verbose} = 1 unless defined $options{-verbose};
+ xDebug(">>> DryRunDryRunDryRunDryRunDryRun <<<");
+}
+
+# ==============================================================================
+# Quick exit if not wanted on this host, or if no work to do
+# ==============================================================================
+
+#if(defined $hostNames) {
+# unless($hostName =~ /$hostNames/) {
+# xDebug("--- Don't run on $hostName ---");
+# exit 0;
+# }
+#}
+
+exit 0 unless ($options{-doLayout} || $options{-doCpuset});
+
+# ==============================================================================
+# See if PBS_HOME is set, and if $PBS_HOME/mom_priv exists.
+# If not, we are probably not called correctly, thus die.
+# See if cpusets are configured. If not, die.
+# ==============================================================================
+
+die "\$PBS_HOME not set\n" unless (exists $ENV{PBS_HOME} && $ENV{PBS_HOME});
+die "PBS_HOME=$ENV{PBS_HOME} does not exist\n" unless -d $ENV{PBS_HOME};
+$momCfgDir = "$ENV{PBS_HOME}/${momCfgDir}";
+die "MOM config dir $momCfgDir does not exist\n" unless -d $momCfgDir;
+$momLayoutFile = "${momCfgDir}/${momLayoutFile}";
+die "this system does not support cpusets\n" unless -d $cpusetFsName;
+
+# ==============================================================================
+# Figure out system topology, collect wanted node objects
+# ==============================================================================
+
+my $topology = Sys::Hwloc::Topology->init;
+die "Failed to init topology\n" unless defined $topology;
+$topology->set_flags(HWLOC_TOPOLOGY_FLAG_WHOLE_SYSTEM);
+die("Failed to load topology\n") if $topology->load;
+
+# ==============================================================================
+# Collect nodesets of wanted NUMA nodes per nodeBoard
+# ==============================================================================
+
+my @nodeBoards = ();
+my $nodeObj = undef;
+my $nNodes = 0;
+while($nodeObj = $topology->get_next_obj_by_type(HWLOC_OBJ_NODE, $nodeObj)) {
+ my $nodeId = $nodeObj->logical_index;
+ next if $nodeId < $firstNodeId;
+ last if (defined $lastNodeId && $nodeId > $lastNodeId);
+ if($nNodes) {
+ $nodeBoards[$#nodeBoards]->{nodeset}->or($nodeObj->nodeset);
+ } else {
+ push @nodeBoards, {
+ cpuset => Sys::Hwloc::Bitmap->new,
+ nodeset => $nodeObj->nodeset->dup,
+ };
+ }
+ $nNodes++;
+ $nNodes = 0 if $nNodes >= $nodesPerBoard;
+}
+
+# ==============================================================================
+# Assemble cpusets per nodeBoard
+# ==============================================================================
+
+foreach my $nodeBoard (@nodeBoards) {
+ $topology->cpuset_from_nodeset_strict($nodeBoard->{cpuset}, $nodeBoard->{nodeset});
+ next if $options{-withSmt};
+ my $core = undef;
+ while($core = $topology->get_next_obj_inside_cpuset_by_type($nodeBoard->{cpuset}, HWLOC_OBJ_CORE, $core)) {
+ my $j = 1;
+ while (my $pu = $topology->get_obj_inside_cpuset_by_type($core->cpuset, HWLOC_OBJ_PU, $j++)) {
+ $nodeBoard->{cpuset}->andnot($pu->cpuset);
+ }
+ }
+}
+
+# ==============================================================================
+# Generate mom.layout
+# ==============================================================================
+
+if($options{-doLayout}) {
+
+ xDebug("--- Generating $momLayoutFile ---");
+ if(! $options{-dryRun}) {
+ open(FILE, "> $momLayoutFile") or die "failed to open $momLayoutFile: $!\n";
+ }
+ foreach my $nodeBoard (@nodeBoards) {
+ my $line = sprintf("nodes=%s", $nodeBoard->{nodeset}->sprintf_list);
+ $line .= sprintf(" cpus=%s", $nodeBoard->{cpuset}->sprintf_list) if $options{-withCpus};
+ $line .= sprintf(" mems=%s", $nodeBoard->{nodeset}->sprintf_list) if $options{-withMems};
+ xDebug(" $line");
+ print FILE "$line\n" unless $options{-dryRun};
+ }
+ close(FILE) unless $options{-dryRun};
+
+}
+
+# ==============================================================================
+# Create/modify torque cpuset
+# ==============================================================================
+
+if($options{-doCpuset}) {
+
+ # Create it if it is not there
+ my $cpusetPath = "${cpusetFsName}${cpusetBaseName}";
+ if(! -d $cpusetPath) {
+ xDebug("--- Creating $cpusetPath ---");
+ my $rc = execCmd($mkdirCmd,1,$cpusetPath);
+ die "Failed to create $cpusetPath\n" unless defined $rc;
+ }
+
+ # Read content
+ xDebug("--- Reading $cpusetPath ---");
+ my $cpusetData = readCpuset($cpusetPath);
+ die "Failed to read $cpusetPath\n" unless defined $cpusetData;
+
+ # Assemble changes
+ my %cpusetMod = ();
+ foreach my $key (keys %cpusetConf) {
+ next unless exists $cpusetData->{$key};
+ my $val = $cpusetConf{$key};
+ CASE: {
+ $key eq 'cpus' && do {
+ if(! defined $val) {
+ my $cpuset = Sys::Hwloc::Bitmap->new;
+ foreach my $nodeBoard (@nodeBoards) {
+ $cpuset->or($nodeBoard->{cpuset});
+ }
+ $val = $cpuset->sprintf_list;
+ $cpuset->free;
+ }
+ last CASE;
+ };
+ $key eq 'mems' && do {
+ if(! defined $val) {
+ my $nodeset = Sys::Hwloc::Bitmap->new;
+ foreach my $nodeBoard (@nodeBoards) {
+ $nodeset->or($nodeBoard->{nodeset});
+ }
+ $val = $nodeset->sprintf_list;
+ $nodeset->free;
+ }
+ last CASE;
+ };
+ }
+ next unless defined $val;
+ if(
+ (! defined $cpusetData->{$key}) ||
+ (defined $cpusetData->{$key} && $cpusetData->{$key} ne $val)
+ ) {
+ $cpusetMod{$key} = $val;
+ }
+ }
+
+ # Write changes, if any. Don't abort on error, but warn if changes not done
+ if(%cpusetMod) {
+ xDebug("--- Modifying $cpusetPath ---");
+ if($options{-dryRun}) {
+ while(my ($key, $val) = each %cpusetMod) {
+ xDebug(sprintf(" = cpuset %s: %-25s %s", $cpusetPath, $key, $val));
+ }
+ } else {
+ while(my ($key, $val) = each %cpusetMod) {
+ my $out = execCmd($echoCmd, 0, "$val > ${cpusetPath}/$key");
+ }
+ if($options{-verbose}) {
+ $cpusetData = readCpuset($cpusetPath);
+ die "Failed to read $cpusetPath\n" unless defined $cpusetData;
+ while(my ($key, $val) = each %cpusetMod) {
+ xDebug(sprintf(" %s cpuset %s: %-25s %s", $val eq $cpusetData->{$key} ? '=' : '-', $cpusetPath, $key, $val));
+ }
+ }
+ }
+ }
+}
+
+# ==============================================================================
+# All done
+# ==============================================================================
+
+$topology->destroy;
+
+exit 0;
+
+# #############################################################################
+
+# ==============================================================================
+# Read cpuset data into a hash, return 0 on error, 1 on success
+# ==============================================================================
+
+sub readCpuset {
+ my $cpusetPath = shift;
+ my $cpusetData = {};
+
+ # Check if cpuset exists
+ unless(-d $cpusetPath) {
+ xDebug("ERROR: Cpuset $cpusetPath does not exist.");
+ return undef;
+ }
+
+ # Read content of cpuset
+ foreach my $key (qw(
+ cpu_exclusive
+ cpus
+ mem_exclusive
+ mem_hardwall
+ memory_migrate
+ memory_pressure
+ memory_spread_page
+ memory_spread_slab
+ mems
+ notify_on_release
+ sched_load_balance
+ sched_relax_domain_level
+ )) {
+ my $f = "${cpusetPath}/$key";
+ next unless -e $f;
+ my $rc = execCmd($catCmd,0,$f);
+ return undef unless defined $rc; # Command failed
+ my $val = undef;
+ if(@{$rc}) {
+ CASE: {
+ $key eq 'tasks' && do { $val = join(",", @{$rc}); last CASE };
+ $val = $rc->[0];
+ }
+ }
+ xDebug(sprintf(" cpuset %s: %-25s %s", $cpusetPath, $key, defined $val ? $val : "NO DATA"));
+ $cpusetData->{$key} = $val;
+ }
+
+ return $cpusetData;
+
+}
+
+# ==============================================================================
+# Execute a command with args.
+# Returns arrayref with chomped output on success.
+# On command failure, print error msg and return undef.
+# ==============================================================================
+
+sub execCmd {
+ my $cmdBase = shift;
+ my $verbose = shift;
+ my @cmdArgs = @_;
+
+ if(! $cmdBase) {
+ xDebug("ERROR execCmd: need \$cmdBase.");
+ return undef;
+ }
+
+ # --
+ # Check if cmdBase is executable
+ # --
+
+ if(! -x $cmdBase) {
+ xDebug("ERROR: File \"$cmdBase\" does not exist or is not executable.");
+ return undef;
+ }
+
+ # --
+ # Execute
+ # --
+
+ my $cmd = $cmdBase;
+ $cmd .= (" " . join(" ", @cmdArgs)) if @cmdArgs;
+ xDebug(" About to execute \"$cmd\"") if $verbose;
+ open(CMD, "$cmd 2>&1 |") or do {
+ xDebug("ERROR: Failed to execute \"$cmd\": $!");
+ return undef;
+ };
+
+ my @cmdOut = (<CMD>);
+ chomp @cmdOut;
+
+ close(CMD);
+ my $rc = $? >> 8;
+ if($rc) {
+ xDebug("ERROR: Command \"$cmd\" returned rc = $rc");
+ if(@cmdOut) {
+ xDebug(join("\n", map { " $_" } grep { /\S/ } $#cmdOut < 3 ? @cmdOut : (@cmdOut[0..2], "...")));
+ }
+ return undef;
+ }
+
+ # --
+ # Return output
+ # --
+
+ return \@cmdOut;
+
+}
+
+# ==============================================================================
+# Usage message
+# ==============================================================================
+
+sub usage {
+ my $code = shift || 0;
+ pod2usage(
+ -verbose => 0,
+ -exitval => "NOEXIT",
+ );
+ exit $code;
+}
+
+# ==============================================================================
+# Man page
+# ==============================================================================
+
+sub manPage {
+ if ($< == 0) { # Cannot invoke perldoc as root
+ my $id = eval { getpwnam("nobody") };
+ $id = eval { getpwnam("nouser") } unless defined $id;
+ $id = -2 unless defined $id;
+ $< = $id;
+ }
+ $> = $<; # Disengage setuid
+ $ENV{PATH} = "/bin:/usr/bin"; # Untaint PATH
+ delete @ENV{ 'IFS', 'CDPATH', 'ENV', 'BASH_ENV' };
+ if ($0 =~ /^([-\/\w\.]+)$/) {
+ $0 = $1; # Untaint $0
+ } else {
+ die "Illegal characters were found in \$0 ($0)\n";
+ }
+ pod2usage(
+ -verbose => 2,
+ -exitval => 0,
+ );
+}
+
+# ==============================================================================
+# Verbose printing
+# ==============================================================================
+
+sub xDebug {
+ return unless $options{-verbose};
+ my $msg = join("", @_);
+ if($msg) {
+ foreach(split("\n", $msg)) {
+ print STDERR "$progName - $_\n"
+ }
+ } else {
+ print STDERR "$progName - something to debug\n";
+ }
+}
+
+sub xDie {
+ die "$progName - ", @_;
+}
+
+__END__
+
+=head1 NAME
+
+mom_gencfg - Create mom.layout and /dev/cpuset/torque, designed to be called from /etc/init.d/pbs_mom
+
+=head1 SYNOPSIS
+
+mom_gencfg --help|-?|--man
+
+mom_gencfg -(no)layout -(no)cpus -(no)mems -(no)cpuset -(no)smt -(no)dry-run -(no)verbose
+
+=head1 DESCRIPTION
+
+This script creates /var/spool/torque/mom_priv/mom.layout and creates/modifies /dev/cpuset/torque
+for a pbs_mom that is compiled with --enable-numa-support.
+
+The basic configuration like number and offset of NUMA node IDs per nodeboard,
+cpuset settings, and defaults of command line options is hardcoded in the script.
+
+The script checks if I<PBS_HOME> is set in the environment. Usually this should point to
+/var/spool/torque.
+
+=head1 OPTIONS
+
+=over 4
+
+=item B<-(no)layout>
+
+Create the mom.layout file or not.
+
+=item B<-(no)cpus>
+
+mom.layout contains cpu IDs per nodeboard or not.
+
+=item B<-(no)mems>
+
+mom.layout contains memory node IDs per nodeboard or not.
+
+=item B<-(no)cpuset>
+
+Create/modify /dev/cpuset/torque or not.
+
+=item B<-(no)smt>
+
+The I<cpus> entry in mom.layout and in /dev/cpuset/torque contain additional
+logical processors running on the same core or not.
+
+=item B<-(no)dry-run>
+
+If B<-dry-run> is given, show what would have been done. Switches B<-verbose> on, unless B<-noverbose> was given.
+
+=item B<-(no)verbose>
+
+Verbose printing to STDERR.
+
+=item B<-man>
+
+Prints this man page.
+
+=item B<-help|-?>
+
+Prints synopsis.
+
+=back
+
+=head1 AUTHOR
+
+Bernd Kallies, E<lt>kallies@zib.deE<gt>
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2011 Zuse Institute Berlin
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation.
+
+=cut
diff --git a/sbin/restart-anaconda b/sbin/restart-anaconda
new file mode 100755
index 0000000..5e654ef
--- /dev/null
+++ b/sbin/restart-anaconda
@@ -0,0 +1,34 @@
+#! /bin/bash
+#
+# restart-anaconda: Debugging tool to restart stage2 Anaconda.
+#
+# Copyright (C) 2010
+# Red Hat, Inc. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+rm -rf /tmp/updates || echo "Error removing /tmp/updates. Updates won't be re-downloaded." >&2
+
+if [[ -f /var/run/iscsid.pid ]]; then
+ # iscsid must die else it will cause us troubles on the next run
+ # log out of all nodes
+ /sbin/iscsiadm -m node --logoutall=all
+fi
+
+# This will kill all programs in the anaconda group and restart the
+# service.
+systemctl stop anaconda.service
+anaconda-cleanup
+systemctl start --no-block anaconda.service
diff --git a/sbin/suncli b/sbin/suncli
new file mode 100755
index 0000000..221932c
--- /dev/null
+++ b/sbin/suncli
@@ -0,0 +1,38 @@
+#!/opt/sunpy3/bin/python3
+import os
+import sys
+import sunhpc
+import sunhpc.invoke
+import logging.handlers
+
+if sys.version_info.major < 3:
+ print("Sunhpc cluster supports only Python3. Rerun application in Python3 environment.")
+ exit(0)
+
+from sunhpc.console import SunhpcConsole
+
+sunhpc_home = os.environ.get('SUNHPCHOME')
+if sunhpc_home:
+ log_file = os.path.join(sunhpc_home, 'logs', 'runSunhpc.log')
+else:
+ log_file = os.path.join('/opt/sunhpc', 'logs', 'runSunhpc.log')
+
+log_handler = logging.handlers.RotatingFileHandler(filename=log_file, maxBytes=500000)
+log_formatter = logging.Formatter("%(asctime)s %(levelname)s %(name)s %(message)s")
+log_handler.setFormatter(log_formatter)
+LOGGER = logging.getLogger()
+LOGGER.setLevel(logging.DEBUG)
+LOGGER.addHandler(log_handler)
+
+def sunhpcApplication(argv):
+ hpc = SunhpcConsole()
+ if len(argv[1:]):
+ hpc.nonInteractive(argv)
+ else:
+ hpc.start()
+
+if __name__ == "__main__":
+ try:
+ sunhpcApplication(sys.argv)
+ except (KeyboardInterrupt, SystemExit):
+ pass
diff --git a/sbin/sunyums b/sbin/sunyums
new file mode 100755
index 0000000..fc4eab8
--- /dev/null
+++ b/sbin/sunyums
@@ -0,0 +1,178 @@
+#!/usr/bin/python
+#coding:utf-8
+import os, sys
+import yum, pickle
+import tempfile
+usages = \
+"""
+Usage: sunyums [OPTION]... [FILE]...
+ Output and match all dependent installation packages
+
+Example:
+ sunyums packname1 packname2
+ sunyums packname1 packname2 --config=file --comps=comps.xml
+ sunyums packname1 packname2 --mandatory=1 --default=1 --options=0
+
+Options:
+ --config=file.conf supply an yum config file, default: optional
+ --comps=comps.xml supply an parsed comps.xml default: optional
+ --mandatory=True include mandatory packages default: True
+ --default=True include mandatory packages default: True
+ --options=False include mandatory packages default: False
+"""
+class Application(object):
+
+ def __init__(self, args):
+ self.args = args[1:]
+ self.yums = yum.YumBase()
+ self.comps = None
+ self.config = None
+ self.groups = []
+ self.mandatory = True
+ self.default = True
+ self.options = False
+
+ self.basePacks = []
+ self.origPacks = []
+ self.packages = []
+
+ def str2bool(self, s):
+ """Converts an on/off, yes/no, true/false string to 1/0."""
+ if s and s.upper() in [ 'ON', 'YES', 'Y', 'TRUE', '1', 'ENABLED', 'ENABLE']:
+ return True
+ else:
+ return False
+
+ def usages(self):
+ print usages
+ sys.exit(0)
+
+ def parseArgs(self):
+
+ if not self.args:
+ self.usages()
+
+ for arg in self.args:
+ if arg in [ '-h', '--help']:
+ self.usages()
+
+ elif arg.startswith('--comps='):
+ self.comps = arg.split('=')[1]
+
+ elif arg.startswith('--config='):
+ self.config = arg.split('=')[1]
+
+ elif arg.startswith('--mandatory='):
+ self.mandatory = self.str2bool(arg.split('=')[1])
+
+ elif arg.startswith('--default='):
+ self.default = self.str2bool(arg.split('=')[1])
+
+ elif arg.startswith('--options='):
+ self.options = self.str2bool(arg.split('=')[1])
+
+ else:
+ self.groups.append(arg)
+
+ def depends(self):
+ pkgs = []
+ avail = self.yums.pkgSack.returnNewestByNameArch()
+ for p in avail:
+ if p.name in self.basePacks:
+ pkgs.append(p)
+
+ done = 0
+ while not done:
+ done = 1
+ results = self.yums.findDeps(pkgs)
+ for pkg in results.keys():
+ for req in results[pkg].keys():
+ reqlist = results[pkg][req]
+ for r in reqlist:
+ if r.name not in self.basePacks:
+ self.basePacks.append(r.name)
+ pkgs.append(r)
+ done = 0
+
+ def allgroups(self):
+ for grp in self.yums.comps.groups:
+ self.packages.extend(grp.packages)
+
+ def handerPackages(self, name):
+ if not self.packages:
+ self.allgroups()
+
+ if name in self.packages and \
+ name not in self.basePacks:
+ self.basePacks.append(name)
+
+ if name not in self.origPacks:
+ self.origPacks.append(name)
+
+ def handerGroups(self, name):
+ groups = []
+ if not self.yums.comps.has_group(name):
+ return
+
+ valid_groups = self.yums.comps.return_group(name.encode('utf-8'))
+ if self.mandatory:
+ groups.extend(valid_groups.mandatory_packages.keys())
+ if self.default:
+ groups.extend(valid_groups.default_packages.keys())
+ if self.options:
+ groups.extend(valid_groups.options_packages.keys())
+
+ for package in groups:
+ self.handerPackages(package)
+
+ def handerEnviron(self, name):
+ groups = []
+ if not self.yums.comps.has_environment(name):
+ return
+
+ valid_environ = self.yums.comps.return_environment(name)
+ for grp in valid_environ.groups:
+ self.handerGroups(grp)
+
+ def run(self):
+
+ if self.comps and os.path.exists(self.comps):
+ self.yums.comps.add(self.comps)
+
+ if self.config and os.path.exists(self.config):
+ self.yums.doConfigSetup(fn=self.config, init_plugins=False)
+
+ self.yums.conf.cache = 0
+ for rpm in self.groups:
+ if rpm[0] == '@':
+ self.handerGroups(rpm[1:])
+
+ elif rpm[0] == '^':
+ self.handerEnviron(rpm[1:])
+
+ else:
+ self.handerPackages(rpm)
+
+ self.depends()
+
+ for o in self.origPacks:
+ if o not in self.basePacks:
+ print '#%s' % o
+
+ for p in self.basePacks:
+ print p
+
+if __name__ == "__main__":
+ app = Application(sys.argv)
+ app.parseArgs()
+ app.allgroups()
+ app.run()
+
+
+
+
+
+
+
+
+
diff --git a/sbin/unsquashfs b/sbin/unsquashfs
new file mode 100755
index 0000000..36c3773
--- /dev/null
+++ b/sbin/unsquashfs
Binary files differ