add init pxe cmd

This commit is contained in:
2026-05-05 02:12:33 +08:00
parent 9ec1cf4fdd
commit 2cc70998d1
24 changed files with 30461 additions and 101 deletions

View File

@@ -8,10 +8,13 @@ import types
import syslog
import inspect
import argparse
import subprocess
import sunhpc.util
import sunhpc.utils
from io import StringIO
from typing import Dict
from pathlib import Path
from typing import Dict, Optional, Tuple, List, Union
from sunhpc.logs import Logs
from sunhpc.disks import DiskInfo
@@ -19,6 +22,9 @@ from sunhpc.configs import Config
from sunhpc.network import Network
from sunhpc.memory import MemoryInfo
from sunhpc.output import Output
from sunhpc.firewalld import FWManager
from sunhpc.utils.shells import ShellExecutor
from xml.sax import saxutils
from xml.sax import handler
@@ -335,12 +341,15 @@ class Command:
self.mem = MemoryInfo()
self.disk = DiskInfo()
self.fmt = Output()
self.sh = ShellExecutor()
self.fw = FWManager('sunhpc')
self.os = os.uname()[0].lower()
self.arch = os.uname()[4]
self.user = pwd.getpwuid(os.getuid()).pw_name
self.parser = argparse.ArgumentParser()
self.parserArgs = []
self.subcommand = 'Sub Command'
self.subdesc = None
self.epilog = None
@@ -392,6 +401,77 @@ class Command:
else:
return 'no'
def rsync_copy(
self,
src: str,
dst: str,
options: str = '-ah --info=progress2'
) -> bool:
"""
简化版本的rsync拷贝、专注于进度显示
Args:
src: 源路径
dst: 目标路径
Returns:
bool: 是否成功
"""
options = options.split()
cmd = ["rsync"]
cmd.extend(options)
cmd.append(src)
cmd.append(dst)
self.log.info(f"执行命令: {' '.join(cmd)}")
try:
# 使用Popen实时显示输出
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
text=True,
bufsize=1
)
# 实时打印输出
for line in process.stdout:
# 去除末尾换行符
line = line.rstrip('\n\r')
if line:
# 计算需要覆盖的长度(使用退格符或直接回车)
# 方法1使用 \r 回车覆盖(推荐)
print(f'\r{line}', end='', flush=True)
last_line = line
else:
# 空行,换行
print()
# 输出完成后换行,避免下一行输出覆盖进度信息
if last_line:
print()
return_code = process.wait()
if return_code == 0:
self.log.info("\n✓ 拷贝成功完成")
return True
else:
self.log.error(f"\n✗ 拷贝失败,返回码: {return_code}")
return False
except Exception as e:
print(f"✗ 执行失败: {e}")
return False
def is_remote_path(self, path: str) -> bool:
"""判断是否为远程路径"""
return '@' in path and ':' in path and not path.startswith(':')
def dtons(self, data: dict) -> types.SimpleNamespace:
'''递归将字典转换为 SimpleNamespace'''
if isinstance(data, dict):
@@ -544,6 +624,13 @@ class Command:
else:
return ' '.join(plist)
def output_dict(self, data={}):
if not data: return
max_key_len = max(len(str(key)) for key in data.keys())
for key, value in data.items():
print(f"{str(key):<{max_key_len}} : {value}")
def command(self, command, args=[]):
'''Import and run a Sunhpc command.
Returns and output string.
@@ -599,13 +686,14 @@ class Command:
rlist = []
for (key, default) in dlist:
if 'key' in params:
if key in params:
rlist.append(params[key])
else:
rlist.append(default)
return rlist
def fillPositionalArgs(self, names, params=None, args=None):
def fillPostArgs(self, names, params=None, args=None):
'''
The helper function will allow named parameters
to be used in lieu of positional arguments
@@ -632,7 +720,7 @@ class Command:
Returns:
remaining args, Filled parameters
Example::
hostlist, iface, mac = self.fillPositionalArgs(
hostlist, iface, mac = self.fillPostArgs(
('iface','mac'), params, args)
'''
@@ -690,9 +778,14 @@ class Command:
plist = [] # arguments
nparams = 0
flagpattern = re.compile(r'^-[a-zA-Z0-9-_+]+=')
flagpattern = re.compile(r'^[a-zA-Z0-9-_+]+=')
for arg in args:
# 检查 - 或 -- 开头
if arg.startswith('--') or arg.startswith('-'):
self.parserArgs.append(arg)
continue
tokens = arg.split()
if tokens[0] == 'select':
plist.append(arg)

View File

@@ -12,106 +12,107 @@ class Command(sunhpc.commands.init.command):
提供一个内网的接口、例如: eth1
</arg>
<arg type='string' name='mnt'>
提供一个系统ISO文件、或者挂载路径、例如: /mnt/cdrom
</arg>
<param type='string' name='iface'>
提供一个内网的接口、例如: eth1
</param>
<param type='string' name='mnt'>
提供一个系统ISO文件、或者挂载路径、例如: /mnt/cdrom
</param>
<arguments>
-h --help 显示帮助信息
-d --debug 开启调试模式
-v --verbose 显示详细信息
</arguments>
<example cmd='init config eth1 /mnt/cdrom'>
使用eth1网络接口、和 /mnt/cdrom 挂载路径
<example cmd='init config eth1 '>
使用eth1网络接口
</example>
<example cmd='init config iface=eth1 mnt=/mnt/cdrom'>
使用eth1网络接口、和 /mnt/cdrom 挂载路径
<example cmd='init config iface=eth1'>
使用eth1网络接口
</example>
"""
def run(self, params, args):
self.parser_cmd_init()
self.parser.add_argument('-i', '--iface', action='store', help='Interface name')
self.parser.add_argument('-d', '--debug', action='store_true', help='Debug mode')
self.parser.add_argument('-f', '--file', action='store_true', help='Configuration file')
(args, iface) = self.fillPostArgs(('iface',))
self.parser.add_argument(
'iface',
help='Network interface (required, e.g., eth0, eth1)'
)
if not iface:
self.abort('must supply an interface')
self.parser.add_argument(
'mnt',
nargs='?',
default='/mnt/cdrom',
help='Mount point (optional, default: /mnt/cdrom)'
)
self.net.setiface(iface)
parsed_params = self.parser_cmd_args(args)
ipaddr = self.net.getip()
if ipaddr is None:
self.abort('interface "%s" has no ip address' % iface)
self.log.info('File "/opt/sunhpc/lib/sunhpc/sunhpc/commands/init/config/__init__.py", line 63, in run File "/opt/sunhpc/lib/sunhpc/sunhpc/commands/init/config/__init__.py", line 63, in run')
#print (parsed_params)
iface = parsed_params.get('iface', 'eth0')
'''
config = Config()
config.iface = 'eth1'
config.mnt = '/mnt/cdrom'
config.network = '1.1.1.1'
config.netmask = '255.255.255.0'
config.gateway = '1.1.1.1'
config.dhcp = Config()
config.dhcp.enabled = True
config.dhcp.server = '1.1.1.1'
config.dhcp.options = ['domain-name', 'domain-name-servers']
config.http = Config()
config.http.enabled = True
config.http.server = '1.1.1.1'
config.api = Config()
config.api.enabled = True
config.api.server = '1.1.1.1'
config.save('/tmp/sunhpc.yaml')
self.net.setiface('eth0')
print (f'Interface: {self.net.iface}')
print (f'IP : {self.net.getip()}')
print (f'Network: {self.net.getnetwork()}')
print (f'Netmask: {self.net.getnetmask()}')
print (f'Gateway: {self.net.getgateway()}')
print (f'MAC : {self.net.getmac()}')
print (f'CIDR : {self.net.getcidr()}')
print (f'IPv6 : {self.net.getipv6()}')
rx, tx = self.net.get_transfer_human()
print (f'RX : {rx}')
print (f'TX : {tx}')
#print (self.disk.get_disk_info('sda'))
#print (self.mem.get_memory_summary())
#print (self.mem.get_memory_info())
#self.fmt.add_header(['Interface', 'IP', 'Network', 'Netmask', 'Gateway', 'MAC', 'CIDR', 'IPv6'])
d1 = {
'name', 'alice',
'age', 18,
'city', 'beijing',
'occupation', 'student'
config_file = self.conf.getConfFile()
config_dict = {
'iface': iface,
'ipaddr': ipaddr,
'netmask': self.net.getnetmask(),
'network': self.net.getnetwork(),
'mac': self.net.getmac(),
'cidr': self.net.getcidr(),
'dnsmasq': {
'enabled': True,
'config': '/etc/dnsmasq.d/sunhpc.conf',
'server': self.net.getip(),
'start_ip': '.'.join(ipaddr.split('.')[:-1]) + '.100',
'end_ip': '.'.join(ipaddr.split('.')[:-1]) + '.200',
'dns': '223.5.5.5',
'systemd_name': 'dnsmasq',
},
'http': {
'enabled': True,
'wwwroot': '/var/www/html',
'config': '/etc/httpd/conf.d/sunhpc.conf',
'httpaddr': 'http://%s' % ipaddr,
'systemd_name': 'httpd',
},
'tftp': {
'enabled': False,
'tftpboot': '/srv/pxelinux/tftpboot',
'systemd_name': 'tftp-server',
},
'nfs': {
'enabled': True,
'paths': [
{
'path': '/home',
'options': 'rw,sync'
},
{
'path': '/opt',
'options': 'rw,sync,no_root_squash'
},
],
'systemd_name': 'nfs-server',
},
'ssh': {
'key_types': [
'ssh-rsa',
'ssh-dss',
'ssh-ed25519',
]
},
'firewall': {
'enabled': True,
'backend': 'firewalld',
},
'osinfo': {
'basename': 'sunhpc',
'os': 'rocky',
'version': '9.7',
},
'pxe':{
'bios': 'boot/undionly.kpxe',
'uefi': 'boot/bootx64.efi',
'ipxe': 'boot/ipxe.efi',
'ksfile': 'scripts/rhel.ks',
'ipxeboot': 'scripts/ipxe.sh',
'repo': 'sunhpc/rockylinux/9.7',
'initrd': 'images/pxeboot/initrd.img',
'vmlinuz': 'images/pxeboot/vmlinuz',
},
'paths': {
'bin': '/opt/sunhpc/bin',
'etc': '/opt/sunhpc/etc',
'lib': '/opt/sunhpc/lib',
'var': '/opt/sunhpc/var',
'pkgs': '/srv/repos/pkgs',
'repo': '/srv/repos/rockylinux/9.7',
}
}
self.fmt.dict_output(d1)
'''
self.conf.save(config_dict=config_dict)

View File

@@ -0,0 +1,264 @@
import os
import re
import sys
import textwrap
import sunhpc.commands
from sunhpc.configs import Config
from sunhpc.paths import ipxe_path, scripts_path
class Command(sunhpc.commands.init.command):
"""
这个命令是初始化系统Pxe引导配置服务.
<arg type='string' name='ISOFile'>
提供一个系统ISO挂载点、例如: /mnt/cdrom
或者提供一个ISO文件路径、例如: /path/to/linux.iso
或者提供一个ISO文件URL、例如: http://example.com/linux.iso
</arg>
<example cmd='init pxe /mnt/cdrom'>
初始化Pxe引导配置服务
</example>
"""
def run(self, params, args):
(args, mnt_src) = self.fillPostArgs(('mntPath', ))
if not mnt_src:
mnt_src = '/mnt/cdrom'
if not os.path.exists(mnt_src):
self.log.error(f"挂载点不存在: {mnt_src}")
self.abort("请挂载一下受支持的Linux系统ISO文件.")
# sunhpc
base_nm = self.conf.osinfo.basename
# /srv/repos/sunhpc
mnt_dst = os.path.join('/srv/repos', base_nm)
iface = self.conf.iface
ipaddr = self.conf.ipaddr
treeinfo = os.path.join(mnt_src, '.treeinfo')
if not os.path.exists(treeinfo):
self.log.error(f"不是一个有效或不受支持的Linux系统ISO挂载路径: {mnt_src}")
self.abort("重新挂载一下受支持的Linux系统ISO文件.")
info = {}
with open(treeinfo, 'r') as f:
for i in f.readlines():
tmp = i.strip().split('=', 1)
if len(tmp) == 2:
info[tmp[0].strip()] = tmp[1].strip()
osname = info.get('family', 'unknown').split()[0].lower()
if osname not in ['rocky', 'rhel', 'centos']:
self.log.error(f"不支持的系统类型: {osname}")
self.abort("请提供一个受支持的Linux系统ISO文件. 只支持Rocky, RHEL, CentOS系统.")
kernel = info.get('kernel', None)
if kernel is None:
self.log.error(f"没有找到内核文件: {kernel}")
self.abort("请提供一个支持 Pxe 的 vmlinuz 文件位置.")
initrd = info.get('initrd', None)
if initrd is None:
self.log.error(f"没有找到初始化文件: {initrd}")
self.abort("请提供一个支持 Pxe 的 initrd 文件位置.")
osvers = info.get('version', 'unknown')
http_head = self.conf.http.httpaddr
http_root = f"{http_head}/{base_nm}/{osname}/{osvers}"
http_ksfile = f"{http_root}/{base_nm}/{self.conf.pxe.ksfile}"
http_init = f"{http_root}/{base_nm}/{self.conf.pxe.initfile}"
lrepo_src = os.path.join(mnt_dst, osname, osvers)
if not os.path.exists(lrepo_src):
os.makedirs(lrepo_src)
# 复制 ISO 文件到目标目录
if not mnt_src.endswith('/'):
mnt_src = mnt_src + os.sep
if not lrepo_src.endswith('/'):
lrepo_src = lrepo_src + os.sep
self.rsync_copy(mnt_src, lrepo_src)
# 拷贝scripts目录到目标目录.
scripts_dst = mnt_dst + os.sep
self.rsync_copy(scripts_path, scripts_dst)
# 安装 httpd、dnsmasq 服务
#result = self.sh.execute("dnf install -y httpd dnsmasq")
wwwroot = self.conf.http.wwwroot
tftpboot = self.conf.tftp.tftpboot
vmlinuz = os.path.join(lrepo_src, kernel)
initrd = os.path.join(lrepo_src, initrd)
hostname = self.sh.execute("hostname", quiet=True).output().strip()
# 创建软连接
self.sh.execute(f"ln -s {mnt_dst} {wwwroot}", quiet=True)
# 创建tftpboot目录
pxe_boot_src = ipxe_path + os.sep
pxe_boot_dst = os.path.join(tftpboot, 'boot') + os.sep
self.sh.execute(f"mkdir -p {pxe_boot_dst}", quiet=True)
# 拷贝pxe引导文件到tftpboot目录
self.rsync_copy(pxe_boot_src, pxe_boot_dst)
# 配置 httpd 服务
httpd_conf = self.conf.http.config
self.create_httpd(hostname, base_nm, wwwroot, httpd_conf)
# 配置 dnsmasq 服务
start_ip = self.conf.dnsmasq.start_ip
end_ip = self.conf.dnsmasq.end_ip
addr_dns = self.conf.dnsmasq.dns
bios = self.conf.pxe.bios
ipxe = self.conf.pxe.ipxe
ipxe_sh = self.conf.pxe.ipxeboot
ipxe_http = f"{http_head}/{base_nm}/{ipxe_sh}"
dnsmasq_conf = self.conf.dnsmasq.config
self.create_dnsmasq(iface,
ipaddr, tftpboot, dnsmasq_conf,
start_ip, end_ip, addr_dns, bios, ipxe, ipxe_http)
# kickstart
ksfile_src = self.conf.pxe.ksfile
ksfile_dst = os.path.join(scripts_dst, ksfile_src)
self.create_ksfile(hostname, osvers, http_root, http_init, ksfile_dst)
# 配置 firewalld 服务
self.fw.load()
self.fw.add_port('80', 'tcp')
self.fw.add_port('443', 'tcp')
self.fw.save()
def create_ksfile(self, hostname, osvers, http_root, http_init, ksfile_dst):
ksfile_cnf = f"""
# Kickstart file for {hostname}
# Created by sunhpc
# Version: {osvers}
graphical
timezone Asia/Shanghai --utc
keyboard --xlayouts="us"
lang en_US.UTF-8
selinux --disabled
url --url='{http_root}'
network --bootproto=dhcp --device=link --ipv6=auto --activate
# autopart --type=lvm
# autopart --type=plain
# autopart --nohome
# autopart --noswap
%include /tmp/diskinfo
%packages
@^minimal-environment
@development
@standard
vim
wget
curl
autofs
nfs-utils
nfs4-acl-tools
sssd-nfs-idmap
%end
rootpw --plaintext "admin_b101"
user --name=dell --plaintext --password="admin_b101" --gecos="dell"
reboot
%pre --interpreter=/bin/bash
if [ -d /sys/firmware/efi ]; then
cat > /tmp/diskinfo <<EOF
clearpart --all --initlabel
part /boot/efi --fstype=efi --size=600 --fsoptions="umask=0077,shortname=uefi"
part /boot --fstype=xfs --size=1024
part pv.01 --size=1 --grow
volgroup vg_sys pv.01
logvol / --fstype=xfs --name=root --vgname=vg_sys --size=51200
logvol swap --fstype=swap --name=swap --vgname=vg_sys --size=4096
logvol /data --fstype=xfs --name=data --vgname=vg_sys --size=1 --grow
EOF
else
cat > /tmp/diskinfo <<EOF
clearpart --all --initlabel
part /boot --fstype=xfs --size=1024 --asprimary
part pv.01 --size=1 --grow
volgroup vg_sys pv.01
logvol / --fstype=xfs --name=root --vgname=vg_sys --size=51200
logvol swap --fstype=swap --name=swap --vgname=vg_sys --size=4096
logvol /data --fstype=xfs --name=data --vgname=vg_sys --size=1 --grow
EOF
fi
%end
%post
curl -s -o /tmp/init.sh {http_init}
chmod +x /tmp/init.sh
/tmp/init.sh
%end
%addon com_redhat_kdump --disable
%end
"""
with open(ksfile_dst, 'w') as f:
f.write(textwrap.dedent(ksfile_cnf))
def create_dnsmasq(self,
iface, ipaddr, tftpboot, dnsmasq_conf,
start_ip, end_ip, addr_dns, bios, ipxe, ipxe_http):
dnsmasq_tmpl = f"""
interface={iface}
bind-interfaces
port=0
enable-tftp
tftp-root={tftpboot}
# Gateway:3, DNS:6
dhcp-range={start_ip},{end_ip},12h
dhcp-option=3,{ipaddr}
dhcp-option=6,{addr_dns}
dhcp-match=set:ipxe,175
dhcp-match=set:bios,option:client-arch,0
dhcp-match=set:uefi,option:client-arch,7
dhcp-match=set:uefi,option:client-arch,9
dhcp-match=set:ipxe,option:user-class,ipxe
dhcp-boot=tag:bios,tag:!ipxe,{bios}
dhcp-boot=tag:uefi,tag:!ipxe,{ipxe}
dhcp-boot=tag:ipxe,{ipxe_http}
"""
with open(dnsmasq_conf, 'w') as f:
f.write(textwrap.dedent(dnsmasq_tmpl))
def create_httpd(self, hostname, base_nm, wwwroot, httpd_conf):
httpd_tmpl = f"""
Alias /{base_nm} {wwwroot}/{base_nm}
UseCanonicalName Off
ServerName {hostname}
<Directory "{wwwroot}/{base_nm}">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
EnableSendfile on
</Directory>
"""
with open(httpd_conf, 'w') as f:
f.write(textwrap.dedent(httpd_tmpl))

View File

@@ -31,6 +31,9 @@ class Config:
self._build_attributes()
self._initialized = True
def getConfFile(self):
return self._config_path
def _build_attributes(self):
"""构建属性访问"""
self._build_from_dict(self._data)
@@ -98,17 +101,26 @@ class Config:
# 如果属性不存在,返回 None可选行为
return None
def save(self, path: Optional[str] = None):
def save(self, path: Optional[str] = None, config_dict: Optional[Dict] = None):
"""保存配置到文件"""
save_path = path or self._config_path
if not save_path:
raise ValueError("未指定保存路径")
data = self.to_dict()
if config_dict:
data = config_dict
# 确保目录存在
Path(save_path).parent.mkdir(parents=True, exist_ok=True)
with open(save_path, 'w', encoding='utf-8') as f:
yaml.dump(self.to_dict(), f, default_flow_style=False, indent=2, allow_unicode=True)
yaml.dump(data, f,
indent=4,
sort_keys=False,
allow_unicode=True,
default_flow_style=False,
)
print(f"配置已保存到: {save_path}")

View File

@@ -0,0 +1,328 @@
"""
Firewalld 自定义服务管理工具
用于创建和修改 /etc/firewalld/services/ 目录下的自定义服务 XML 文件
"""
import os
from pathlib import Path
from xml.dom import minidom
import xml.etree.ElementTree as ET
from sunhpc.logs import Logs
slog = Logs(name="Firewd", show_time=True)
class FWManager:
"""Firewalld 服务文件管理器"""
# firewalld 服务目录路径
SYSTEM_SERVICES_DIR = Path('/usr/lib/firewalld/services')
CUSTOM_SERVICES_DIR = Path('/etc/firewalld/services')
def __init__(self, service_name):
"""
初始化服务管理器
Args:
service_name: 服务名称(不含 .xml 后缀)
"""
self.service_name = service_name
self.service_file = self.CUSTOM_SERVICES_DIR / f"{service_name}.xml"
self.xml_tree = None
self.root = None
def _ensure_custom_dir(self):
"""确保自定义服务目录存在"""
self.CUSTOM_SERVICES_DIR.mkdir(parents=True, exist_ok=True)
def _create_xml_structure(self):
"""创建基本的 XML 结构"""
# 创建根元素
self.root = ET.Element('service')
# 添加 short 元素
short = ET.SubElement(self.root, 'short')
short.text = self.service_name.capitalize()
# 添加 description 元素
description = ET.SubElement(self.root, 'description')
description.text = f"Custom service: {self.service_name}"
# 添加 port 元素(稍后添加)
# 添加 protocol 元素(稍后添加)
self.xml_tree = ET.ElementTree(self.root)
def _prettify_xml(self, elem):
"""
格式化 XML 输出
Args:
elem: XML 元素
Returns:
str: 格式化后的 XML 字符串
"""
rough_string = ET.tostring(elem, 'utf-8')
reparsed = minidom.parseString(rough_string)
return reparsed.toprettyxml(indent=' ')
def _save_xml(self):
"""保存 XML 文件到自定义服务目录"""
self._ensure_custom_dir()
# 格式化 XML
xml_str = self._prettify_xml(self.root)
# 写入文件
with open(self.service_file, 'w', encoding='utf-8') as f:
# 移除多余的 XML 声明firewalld 不需要)
if xml_str.startswith('<?xml'):
xml_str = xml_str.split('\n', 1)[1]
f.write(xml_str)
# 设置正确的权限644
os.chmod(self.service_file, 0o644)
def load(self):
"""
加载现有服务文件或创建新文件
Returns:
bool: 是否成功加载/创建
"""
if self.service_file.exists():
# 加载现有文件
try:
self.xml_tree = ET.parse(self.service_file)
self.root = self.xml_tree.getroot()
slog.info(f"✓ 已加载现有服务: {self.service_file}")
return True
except ET.ParseError as e:
slog.error(f"✗ 解析 XML 文件失败: {e}")
return False
else:
# 创建新文件
slog.info(f"服务不存在,将创建新服务: {self.service_name}")
self._create_xml_structure()
return True
def set_short_description(self, short_text):
"""
设置服务简短描述
Args:
short_text: 简短描述文本
"""
short_elem = self.root.find('short')
if short_elem is None:
short_elem = ET.SubElement(self.root, 'short')
short_elem.text = short_text
slog.info(f"✓ 设置简短描述: {short_text}")
def set_description(self, desc_text):
"""
设置服务详细描述
Args:
desc_text: 详细描述文本
"""
desc_elem = self.root.find('description')
if desc_elem is None:
desc_elem = ET.SubElement(self.root, 'description')
desc_elem.text = desc_text
slog.info(f"✓ 设置详细描述: {desc_text}")
def add_port(self, port, protocol='tcp'):
"""
添加端口规则
Args:
port: 端口号或端口范围(例如:'8080''3000-3010'
protocol: 协议类型tcp/udp/sctp/dccp
"""
# 查找是否已存在相同的端口规则
for port_elem in self.root.findall('port'):
if port_elem.get('port') == str(port) and port_elem.get('protocol') == protocol:
slog.info(f"⚠ 跳过,已存在, 端口 {port}/{protocol}")
return
# 添加新端口
port_elem = ET.SubElement(self.root, 'port')
port_elem.set('port', str(port))
port_elem.set('protocol', protocol)
slog.info(f"✓ 添加端口: {port}/{protocol}")
def remove_port(self, port, protocol='tcp'):
"""
移除端口规则
Args:
port: 端口号或端口范围
protocol: 协议类型
"""
for port_elem in self.root.findall('port'):
if port_elem.get('port') == str(port) and port_elem.get('protocol') == protocol:
self.root.remove(port_elem)
slog.info(f"✓ 移除端口: {port}/{protocol}")
return
slog.info(f"⚠ 未找到端口: {port}/{protocol}")
def add_protocol(self, protocol_name):
"""
添加协议规则IP 协议,不是传输层协议)
Args:
protocol_name: 协议名称(如 ipv6-icmp, icmp, igmp 等)
"""
for proto_elem in self.root.findall('protocol'):
if proto_elem.get('name') == protocol_name:
slog.info(f"⚠ 协议 {protocol_name} 已存在,跳过")
return
proto_elem = ET.SubElement(self.root, 'protocol')
proto_elem.set('name', protocol_name)
slog.info(f"✓ 添加协议: {protocol_name}")
def remove_protocol(self, protocol_name):
"""
移除协议规则
Args:
protocol_name: 协议名称
"""
for proto_elem in self.root.findall('protocol'):
if proto_elem.get('name') == protocol_name:
self.root.remove(proto_elem)
slog.info(f"✓ 移除协议: {protocol_name}")
return
slog.info(f"⚠ 未找到协议: {protocol_name}")
def add_module(self, module_name):
"""
添加内核模块依赖
Args:
module_name: 模块名称(如 nf_conntrack_ftp
"""
for module_elem in self.root.findall('module'):
if module_elem.get('name') == module_name:
slog.info(f"⚠ 模块 {module_name} 已存在,跳过")
return
module_elem = ET.SubElement(self.root, 'module')
module_elem.set('name', module_name)
slog.info(f"✓ 添加模块: {module_name}")
def remove_module(self, module_name):
"""
移除内核模块依赖
Args:
module_name: 模块名称
"""
for module_elem in self.root.findall('module'):
if module_elem.get('name') == module_name:
self.root.remove(module_elem)
slog.info(f"✓ 移除模块: {module_name}")
return
slog.info(f"⚠ 未找到模块: {module_name}")
def get_ports(self):
"""获取所有端口配置"""
ports = []
for port_elem in self.root.findall('port'):
ports.append({
'port': port_elem.get('port'),
'protocol': port_elem.get('protocol')
})
return ports
def get_protocols(self):
"""获取所有协议配置"""
protocols = []
for proto_elem in self.root.findall('protocol'):
protocols.append(proto_elem.get('name'))
return protocols
def display_info(self):
"""显示服务信息"""
slog.info("\n" + "="*50)
slog.info(f"服务名称: {self.service_name}")
slog.info(f"配置文件: {self.service_file}")
short = self.root.find('short')
if short is not None and short.text:
slog.info(f"简短描述: {short.text}")
desc = self.root.find('description')
if desc is not None and desc.text:
slog.info(f"详细描述: {desc.text}")
ports = self.get_ports()
if ports:
slog.info("\n端口规则:")
for port in ports:
slog.info(f" - {port['port']}/{port['protocol']}")
protocols = self.get_protocols()
if protocols:
print("\n协议规则:")
for proto in protocols:
print(f" - {proto}")
modules = [m.get('name') for m in self.root.findall('module')]
if modules:
slog.info("\n内核模块:")
for module in modules:
slog.info(f" - {module}")
slog.info("="*50 + "\n")
def save(self):
"""保存修改"""
self._save_xml()
def main():
"""示例用法"""
# 创建或修改名为 'myapp' 的服务
manager = FWManager('myapp')
# 加载或创建服务文件
if not manager.load():
return
# 设置描述信息
manager.set_short_description('My Application Service')
manager.set_description('Custom service for my web application with API and admin ports')
# 添加端口
manager.add_port(8080, 'tcp') # Web 服务端口
manager.add_port(8443, 'tcp') # HTTPS 替代端口
manager.add_port(9090, 'tcp') # API 端口
manager.add_port(3000, 'tcp') # 管理界面端口
manager.add_port(5000-5010, 'tcp') # 端口范围示例
manager.add_port(9000, 'udp') # UDP 端口
# 添加协议(如果需要)
# manager.add_protocol('icmp')
# 添加内核模块(如果需要,例如 FTP 辅助模块)
# manager.add_module('nf_conntrack_ftp')
# 显示当前配置
manager.display_info()
# 保存修改
manager.save()
# 示例:移除端口
# manager.remove_port(5000-5010, 'tcp')
# manager.save()
slog.info("\n✅ 操作完成!")
slog.info("提示:")
slog.info("1. 运行 'sudo firewall-cmd --reload' 重新加载防火墙")
slog.info("2. 使用 'sudo firewall-cmd --get-services' 查看所有服务")
slog.info("3. 使用 'sudo firewall-cmd --info-service=myapp' 查看服务详情")
slog.info(f"4. 使用 'sudo firewall-cmd --add-service={manager.service_name}' 启用服务")
if __name__ == '__main__':
main()

View File

@@ -5,6 +5,7 @@ import yaml
import sunhpc
import signal
import syslog
import traceback
import sunhpc.util
import sunhpc.error as error
@@ -70,7 +71,6 @@ def _main(argv=None):
command.isRootUser() or command.isApacheUser()):
os.system('sudo %s' % ' '.join(sys.argv))
else:
#import sunhpc
try:
command.runWrapper(name, args[i:])
text = command.getText()
@@ -81,8 +81,10 @@ def _main(argv=None):
print (text)
print ()
except CommandError as e:
print ('Error: ', e)
print (command.usage())
print ('Error: ', e)
#slog.info(command.usage())
#slog.error(str(e))
return 1
config_file = '/etc/sunhpc/sunhpc.yaml'
@@ -107,9 +109,9 @@ def main(argv=None):
tty.error("Keyboard interrupt.")
return signal.SIGINT.value
except AttributeError:
except AttributeError as e:
sys.stderr.write("\n")
tty.error("Attribute error.")
slog.error(str(e))
return 1
except SystemExit as e:

View File

@@ -22,8 +22,20 @@ sunhpc_root = prefix
#: bin directory in the sunhpc prefix
bin_path = os.path.join(prefix, "bin")
#: var directory in the sunhpc
var_path = os.path.join(prefix, "var")
#: pkgs directory in the sunhpc
pkgs_path = os.path.join(var_path, "pkgs")
#: ipxe directory in the sunhpc
ipxe_path = os.path.join(pkgs_path, "ipxe")
#: scripts directory in the sunhpc
scripts_path = os.path.join(pkgs_path, "scripts")
#: The sunhpc script itself
sunhpc_script = os.path.join(bin_path, "sunhpc")
sunhpc_command = os.path.join(bin_path, "sunhpc")
#: The sbang script in the sunhpc installation
sbang_script = os.path.join(bin_path, "sbang")

View File

@@ -0,0 +1,611 @@
import sys
import time
import shlex
import threading
import subprocess
from collections import deque
from typing import Optional, Union, List, Dict, Any, Callable
class ShellResult:
"""封装命令执行结果的类,支持布尔判断、输出获取、错误获取和返回码获取"""
def __init__(self,
returncode: int,
stdout: str,
stderr: str,
metadata: Optional[Dict[str, Any]] = None):
self._returncode = returncode
self._stdout = stdout
self._stderr = stderr
self._metadata = metadata or {} # 存储额外信息,如包名、版本等
def __bool__(self):
"""支持 if result: 直接判断命令是否成功"""
return self._returncode == 0
def output(self) -> str:
"""获取命令的标准输出"""
return self._stdout
def error(self) -> str:
"""获取命令的标准错误"""
return self._stderr
def code(self) -> int:
"""获取命令的返回码"""
return self._returncode
def output_lines(self) -> List[str]:
"""返回输出行列表,过滤空行"""
return [line for line in self._stdout.splitlines() if line]
def error_lines(self) -> List[str]:
return [line for line in self._stderr.splitlines() if line]
def get_metadata(self, key: str, default=None):
"""获取元数据"""
return self._metadata.get(key, default)
def set_metadata(self, key: str, value: Any):
"""设置元数据"""
self._metadata[key] = value
class ShellExecutor:
"""
Shell命令执行器基类,提供通用的命令执行功能
子类可重写方法以实现特定命令的定制行为
"""
def __init__(self,
show_animation: bool = True,
animation_chars: str = '|/-\\',
show_last_line: bool = True,
max_display_lines: int = 1
):
"""
初始化执行器
参数:
show_animation : 是否显示动态动画
animation_chars : 动画字符集
show_last_line : 是否显示最后一行
max_display_lines : 最大显示行数,超过则省略号显示
"""
self.show_animation = show_animation
self.animation_chars = animation_chars
self.show_last_line = show_last_line
self.max_display_lines = max_display_lines
self._line_count = 0
self._last_lines = deque(maxlen=max_display_lines)
def pre_execute_hook(self, cmd: Union[str, List[str]]) -> Union[str, List[str]]:
"""
执行前的钩子函数,可以修改命令或做预处理
子类可重写此方法
"""
return cmd
def post_execute_hook(self, result: ShellResult, cmd: Union[str, List[str]]) -> ShellResult:
"""
执行后的钩子函数,可以处理结果、提取信息等
子类可重写此方法
"""
return result
def get_display_message(self, cmd: Union[str, List[str]]) -> str:
"""
获取执行时显示的消息
子类可重写以显示不同的提示信息
"""
return "Running..."
def get_completion_message(self, cmd: Union[str, List[str]], result: ShellResult) -> str:
"""
获取完成时显示的消息
子类可重写以显示不同的完成信息
"""
if self._line_count > 0:
return f"Completed! (lines: {self._line_count})"
else:
return "Completed!"
def get_realtime_info(self, line: str) -> str:
"""
获取实时显示的信息(可被子类重写以显示不同的信息格式)
参数:
line: 最新读取的一行输出
返回:
要显示的附加信息字符串
"""
# 默认显示最后一行内容(截断过长内容)
if self.show_last_line and line:
# 限制行长度,避免显示过长
max_length = 80
if len(line) > max_length:
line = line[:max_length-3] + "..."
return f" [{line}]"
return ""
def update_realtime_output(self, line: str):
"""
更新实时输出信息(可被子类重写以处理特殊输出)
参数:
line: 最新读取的一行输出
"""
self._last_lines.append(line.rstrip('\n\r'))
def parse_output_for_metadata(self,
result: ShellResult,
cmd: Union[str, List[str]]) -> Dict[str, Any]:
"""
解析输出提取元数据
子类可重写此方法
"""
return {}
def _RRread_output_thread(self, process):
"""读取输出的线程函数"""
for line in iter(process.stdout.readline, ''):
if line:
self._line_count += 1
process.stdout.close()
def _read_output_thread(self, process, is_stderr=False):
"""读取输出的线程函数"""
if is_stderr:
# 错误输出只读取,不显示在动画中
for line in iter(process.stderr.readline, ''):
if line:
pass # 可以在这里处理stderr
process.stderr.close()
else:
# 标准输出需要计数和显示
for line in iter(process.stdout.readline, ''):
if line:
self._line_count += 1
# 更新实时输出
self.update_realtime_output(line)
# 可以添加一个回调,让子类实时处理每一行
self.on_output_line(line)
process.stdout.close()
def _display_animation(self, process):
"""显示动画的函数"""
if not self.show_animation:
return
idx = 0
while process.poll() is None:
spin_char = self.animation_chars[idx % len(self.animation_chars)]
if self._line_count > 0:
display = f"\r{spin_char} {self.get_display_message(process.args)} (lines: {self._line_count})"
else:
display = f"\r{spin_char} {self.get_display_message(process.args)}"
sys.stdout.write(display)
sys.stdout.flush()
idx += 1
time.sleep(0.1)
# 清除当前行并显示完成信息
completion_msg = self.get_completion_message(process.args, ShellResult(0, "", ""))
sys.stdout.write(f"\r{completion_msg} \n")
sys.stdout.flush()
def on_output_line(self, line: str):
"""
当有新的输出行时的回调函数(可被子类重写)
参数:
line: 新输出的行
"""
pass
def execute(self,
cmd: Union[str, List[str]],
t_cmd: Optional[Union[str, List[str]]] = None,
quiet: bool = False,
timeout: Optional[int] = None,
show_animation: bool = True,
show_real_time: bool = True,
) -> ShellResult:
"""
执行shell命令
参数:
cmd : 要执行的字符串或列表
t_cmd : 可选,执行完成后的测试命令
timeout : 超时时间(秒)
show_real_time : 是否显示实时输出(仅当show_animation为True时有效)
返回:
ShellResult 实例
"""
# 执行预处理钩子
processed_cmd = self.pre_execute_hook(cmd)
# 转换命令为列表形式
if isinstance(processed_cmd, str):
cmd_list = shlex.split(processed_cmd)
else:
cmd_list = processed_cmd
# 重置计数器
self._line_count = 0
self._last_lines.clear()
# 启动子进程
process = subprocess.Popen(
cmd_list,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
bufsize=1
)
# 用于存储输出
stdout_lines = []
stderr_lines = []
# 创建读取线程
def collect_stdout():
for line in iter(process.stdout.readline, ''):
if line:
stdout_lines.append(line)
self._line_count += 1
self.update_realtime_output(line)
self.on_output_line(line)
process.stdout.close()
def collect_stderr():
for line in iter(process.stderr.readline, ''):
if line:
stderr_lines.append(line)
process.stderr.close()
stdout_thread = threading.Thread(target=collect_stdout)
stderr_thread = threading.Thread(target=collect_stderr)
stdout_thread.daemon = True
stderr_thread.daemon = True
stdout_thread.start()
stderr_thread.start()
# 显示动画
if self.show_animation:
idx = 0
last_display = ""
while process.poll() is None:
spin_char = self.animation_chars[idx % len(self.animation_chars)]
# 构建显示内容
if self._line_count > 0:
base_display = f"{spin_char} {self.get_display_message(cmd_list)} (lines: {self._line_count})"
# 添加实时输出信息
if show_real_time and self._last_lines:
# 显示最后一行内容
last_line = list(self._last_lines)[-1]
realtime_info = self.get_realtime_info(last_line)
display = f"\r{base_display}{realtime_info}"
else:
display = f"\r{base_display}"
else:
display = f"\r{spin_char} {self.get_display_message(cmd_list)}"
# 只在内容变化时更新,减少闪烁
if display != last_display or self._line_count != last_line_count:
sys.stdout.write(f'\r{display}\033[K')
sys.stdout.flush()
last_display = display
last_line_count = self._line_count
idx += 1
time.sleep(0.1)
# 等待线程结束
stdout_thread.join(timeout=1)
stderr_thread.join(timeout=1)
# 清除当前行
self._clear_line()
# 显示完成信息
if not quiet:
completion_msg = self.get_completion_message(cmd_list, ShellResult(0, "", ""))
# 清除当前行并显示完成信息
sys.stdout.write(f"\r{completion_msg}\n")
sys.stdout.flush()
else:
# 不显示动画时,直接等待进程结束
process.wait()
stdout_thread.join()
stderr_thread.join()
# 合并输出
stdout = ''.join(stdout_lines)
stderr = ''.join(stderr_lines)
# 如果有测试命令,执行测试命令
if t_cmd is not None:
if isinstance(t_cmd, str):
test_cmd_list = shlex.split(t_cmd)
else:
test_cmd_list = t_cmd
test_process = subprocess.run(
test_cmd_list,
input=stdout,
capture_output=True,
text=True
)
final_returncode = 0 if test_process.returncode == 0 else 1
final_stderr = stderr + test_process.stderr
else:
final_returncode = process.returncode
final_stderr = stderr
# 创建结果对象
result = ShellResult(final_returncode, stdout, final_stderr)
# 解析元数据(如果子类需要)
metadata = self.parse_output_for_metadata(result, processed_cmd)
for key, value in metadata.items():
result.set_metadata(key, value)
# 执行后置钩子
result = self.post_execute_hook(result, processed_cmd)
return result
def _clear_line(self):
"""彻底清除当前行"""
# 先移动到行首,然后清除到行尾
sys.stdout.write('\r\033[K') # \033[K 清除从光标到行尾的内容
sys.stdout.flush()
class DnfExecutor(ShellExecutor):
"""针对dnf命令的专用执行器"""
def get_display_message(self, cmd: Union[str, List[str]]) -> str:
"""显示dnf特定消息"""
cmd_str = ' '.join(cmd) if isinstance(cmd, list) else cmd
if 'install' in cmd_str:
return "Installing packages..."
elif 'remove' in cmd_str or 'erase' in cmd_str:
return "Removing packages..."
elif 'update' in cmd_str:
return "Updating packages..."
elif 'search' in cmd_str:
return "Searching packages..."
else:
return "DNF Running..."
def parse_output_for_metadata(self, result: ShellResult, cmd: Union[str, List[str]]) -> Dict[str, Any]:
"""从dnf输出中提取包信息"""
metadata = {}
cmd_str = ' '.join(cmd) if isinstance(cmd, list) else cmd
# 提取安装的包名
if 'install' in cmd_str or 'remove' in cmd_str:
packages = []
for line in result.output_lines():
if 'Installing:' in line or 'Removing:' in line:
# 提取包名
parts = line.split()
for part in parts:
if '.x86_64' in part or '.noarch' in part:
packages.append(part)
if packages:
metadata['packages'] = packages
metadata['package_count'] = len(packages)
return metadata
def post_execute_hook(self, result: ShellResult, cmd: Union[str, List[str]]) -> ShellResult:
"""dnf执行后的额外处理"""
if result and 'install' in str(cmd):
# 如果安装成功,提取安装的包列表
packages = result.get_metadata('packeds', [])
if packages:
result.set_metadata('installed_packages', packages)
return result
class RpmExecutor(ShellExecutor):
"""针对rpm命令的专用执行器"""
def __init__(self, query_format: Optional[str] = None, **kwargs):
"""
初始化rpm执行器
参数:
query_format: 查询格式,如 "%{NAME} %{VERSION}"
"""
super().__init__(**kwargs)
self.query_format = query_format
def pre_execute_hook(self, cmd: Union[str, List[str]]) -> Union[str, List[str]]:
"""预处理rpm命令"""
if isinstance(cmd, str):
cmd_parts = shlex.split(cmd)
else:
cmd_parts = cmd.copy()
# 如果是查询命令且指定了格式,添加--qf参数
if self.query_format and len(cmd_parts) > 1 and cmd_parts[0] == 'rpm':
if cmd_parts[1] in ['-q', '--query', '-qa', '--query', '-qi']:
# 插入格式参数
if '--qf' not in cmd_parts and '--queryformat' not in cmd_parts:
cmd_parts.insert(2, '--qf')
cmd_parts.insert(3, self.query_format)
return cmd_parts
def get_display_message(self, cmd: Union[str, List[str]]) -> str:
"""显示rpm特定消息"""
cmd_str = ' '.join(cmd) if isinstance(cmd, list) else cmd
if '-i' in cmd_str and 'install' in cmd_str:
return "Installing RPM packages..."
elif '-e' in cmd_str:
return "Erasing RPM packages..."
elif '-q' in cmd_str:
return "Querying RPM database..."
elif '-U' in cmd_str or '-F' in cmd_str:
return "Upgrading RPM packages..."
else:
return "RPM Running..."
def parse_output_for_metadata(self, result: ShellResult, cmd: Union[str, List[str]]) -> Dict[str, Any]:
"""从rpm输出中提取包信息"""
metadata = {}
cmd_str = ' '.join(cmd) if isinstance(cmd, list) else cmd
# 提取查询结果的包名和版本
if '-q' in cmd_str and result and result.output():
packages = []
for line in result.output_lines():
if line.strip():
parts = line.split()
if len(parts) >= 2:
packages.append({
'name': parts[0],
'version': parts[1] if len(parts) > 1 else ''
})
if packages:
metadata['packages'] = packages
metadata['package_count'] = len(packages)
return metadata
class SystemdExecutor(ShellExecutor):
"""针对systemctl命令的专用执行器"""
def get_display_message(self, cmd: Union[str, List[str]]) -> str:
"""显示systemctl特定消息"""
cmd_str = ' '.join(cmd) if isinstance(cmd, list) else cmd
if 'start' in cmd_str:
return "Starting service..."
elif 'stop' in cmd_str:
return "Stopping service..."
elif 'restart' in cmd_str:
return "Restarting service..."
elif 'status' in cmd_str:
return "Checking service status..."
elif 'enable' in cmd_str:
return "Enabling service..."
elif 'disable' in cmd_str:
return "Disabling service..."
else:
return "Systemctl Running..."
def parse_output_for_metadata(self, result: ShellResult, cmd: Union[str, List[str]]) -> Dict[str, Any]:
"""从systemctl输出中提取服务状态"""
metadata = {}
cmd_str = ' '.join(cmd) if isinstance(cmd, list) else cmd
# 提取服务状态
if 'status' in cmd_str and result:
for line in result.output_lines():
if 'Active:' in line:
status = line.split('Active:')[1].strip()
metadata['service_status'] = status
if 'active' in status:
metadata['is_active'] = True
else:
metadata['is_active'] = False
return metadata
# ========== 使用示例 ==========
if __name__ == "__main__":
# 示例1使用基础执行器
print("=== 基础执行器 ===")
executor = ShellExecutor()
result = executor.execute("ls -la")
print(f"命令成功: {bool(result)}")
print(f"输出行数: {len(result.output_lines())}")
print(f"前3行输出:\n{chr(10).join(result.output_lines()[:3])}")
print("-" * 50)
# 示例2使用dnf执行器如果有dnf命令
print("=== DNF执行器 ===")
dnf = DnfExecutor()
# 搜索命令示例(不会实际修改系统)
result = dnf.execute("dnf search python3", show_animation=False) # 测试时关闭动画
print(f"搜索完成: {bool(result)}")
if result.get_metadata('package_count', 0) > 0:
print(f"找到 {result.get_metadata('package_count')} 个包")
# 示例3使用rpm执行器
print("=== RPM执行器 ===")
rpm = RpmExecutor(query_format="%{NAME} %{VERSION}")
# 查询已安装的包前5个
result = rpm.execute("rpm -qa | head -5", show_animation=False)
print(f"查询完成: {bool(result)}")
print("前5个包:")
for line in result.output_lines()[:5]:
print(f" {line}")
# 示例4使用systemd执行器
print("=== Systemd执行器 ===")
systemd = SystemdExecutor()
result = systemd.execute("systemctl status sshd", show_animation=False)
print(f"服务状态: {result.get_metadata('service_status', 'unknown')}")
print(f"服务活跃: {result.get_metadata('is_active', False)}")
# 示例5带测试命令的示例
print("=== 带测试命令 ===")
executor = ShellExecutor()
result = executor.execute("ls -la", t_cmd="grep README")
print(f"包含README文件: {bool(result)}")
if not result:
print(f"未找到README文件")
# 示例6如何扩展自己的专用执行器
print("=== 自定义扩展示例 ===")
class GitExecutor(ShellExecutor):
"""Git命令专用执行器"""
def get_display_message(self, cmd: Union[str, List[str]]) -> str:
cmd_str = ' '.join(cmd) if isinstance(cmd, list) else cmd
if 'status' in cmd_str:
return "Checking git status..."
elif 'pull' in cmd_str:
return "Pulling from remote..."
elif 'push' in cmd_str:
return "Pushing to remote..."
elif 'commit' in cmd_str:
return "Committing changes..."
else:
return "Git Running..."
def parse_output_for_metadata(self, result: ShellResult, cmd: Union[str, List[str]]) -> Dict[str, Any]:
"""提取git信息"""
metadata = {}
cmd_str = ' '.join(cmd) if isinstance(cmd, list) else cmd
if 'status' in cmd_str:
# 统计未跟踪、修改、新增的文件
untracked = 0
modified = 0
for line in result.output_lines():
if 'Untracked files:' in line:
untracked = 1
elif 'modified:' in line:
modified += 1
metadata['untracked'] = untracked > 0
metadata['modified_count'] = modified
return metadata
git = GitExecutor()
result = git.execute("git status", show_animation=False)
if result:
print(f"有未跟踪文件: {result.get_metadata('untracked', False)}")
print(f"修改文件数: {result.get_metadata('modified_count', 0)}")

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@@ -0,0 +1,504 @@
/*! @page KnownIssues Known issues in the current version of NVML library
*
* This is a list of known NVML issues in the current driver:
* - NVML Field Values from #251 - #273 (Power Smoothing, Clock Event Reason, and Sync Power Balancing related field values) have changed between 13.0 and 13.0U1/v580TRD2.
* - Any application that is using these field IDs must be recompiled using the NVML header file from CUDA 13.0 Update 1 in order to continue working correctly with NVIDIA drivers v580 TRD2 and beyond.
* - On systems where GPUs are NUMA nodes, the accuracy of FB memory utilization provided by NVML depends on the memory accounting of the operating system.
* This is because FB memory is managed by the operating system instead of the NVIDIA GPU driver.
* Typically, pages allocated from FB memory are not released even after the process terminates to enhance performance. In scenarios where
* the operating system is under memory pressure, it may resort to utilizing FB memory. Such actions can result in discrepancies in the accuracy of memory reporting.
* - On Linux GPU Reset can't be triggered when there is pending GPU Operation Mode (GOM) change
* - On Linux GPU Reset may not successfully change pending ECC mode. A full reboot may be required to enable the mode change.
* - \ref nvmlAccountingStats supports only one process per GPU at a time (CUDA proxy server counts as one process).
* - \ref nvmlAccountingStats_t.time reports time and utilization values starting from cuInit till process termination. Next driver versions might change this behavior slightly and account process only from cuCtxCreate till cuCtxDestroy.
* - On GPUs from Fermi family current P0 clocks (reported by \ref nvmlDeviceGetClockInfo) can differ from max clocks by few MHz.
*/
/*! @page Changelog Change log of NVML library
* This chapter list changes in API and bug fixes that were introduced to the library
* \section changelog32 Changes between NVML v575 and v580 ===
* - Fixed bug with NVML_FI_PWR_SMOOTHING_* Field Value numbering, which was different than the v570 values.
* - Adjusted NVML_FI_DEV_CLOCKS_EVENT_REASON_* and NVML_FI_DEV_POWER_SYNC_BALANCING_* field value numbering to resolve overlap with NVML_FI_PWR_SMOOTHING_* field values.
*
* - Added \ref nvmlDeviceGetSramUniqueUncorrectedEccErrorCounts to get the counts of SRAM unique uncorrected ECC errors.
* - Deprecated Applications Clocks APIs, which will be removed in CUDA 14.0:
* - \ref nvmlDeviceSetApplicationsClocks
* - \ref nvmlDeviceGetApplicationsClock
* - \ref nvmlDeviceGetDefaultApplicationsClock
* - \ref nvmlDeviceResetApplicationsClocks
* - Deprecated \ref nvmlDeviceGetViolationStatus, which will be removed in CUDA 14.0
* - Added \ref nvmlDeviceGetNvLinkInfo to query device NVLINK info.
* - Added \ref nvmlDeviceGetPdi to retrieve the device GPU PDI.
* - Added Multi-GPU mode NVLINK Encryption \ref NVML_CC_SYSTEM_MULTIGPU_NVLE
* - Added V2 struct to \ref nvmlDeviceGetNvLinkInfo to query NVLINK Firmware info.
* - Added \ref nvmlDeviceReadWritePRM_v1 to retrieve GPU PRM register contents
* - Added \ref nvmlDeviceGetAddressingMode to retrieve the addressing mode for the device.
* - Added \ref nvmlDeviceGetRepairStatus to get ECC status info.
* - Added \ref nvmlDeviceGetGpuInstanceProfileInfoByIdV which allows for MIG GPU instance profile info to be queried with profileId instead of profile name.
* - Updated nvmlGpuFabricInfoV_t to v3 to include a new Health Summary field, and new Incorrect Configuration statuses.
- nvmlGpuFabricInfo_v2_t is deprecated and will be removed in a future release
* - Added \ref nvmlDeviceGetPowerMizerMode_v1 to query the current and supported power mizer modes on Maxwell and newer gpus. Power mizer mode provides a hint to the driver as to how to manage the performance of the GPU.
* - Added \ref nvmlDeviceSetPowerMizerMode_v1 to set the power mizer mode on Maxwell and newer gpus.
* - Added new Incorrect Configuration Statuses to nvmlGpuFabricInfoV_t
* - NVML_GPU_FABRIC_HEALTH_MASK_INCORRECT_CONFIGURATION_INCOMPATIBLE_GPU_FW
* - NVML_GPU_FABRIC_HEALTH_MASK_INCORRECT_CONFIGURATION_INVALID_LOCATION
* - Added \ref nvmlDeviceSetHostname_v1 and \ref nvmlDeviceGetHostname_v1 to allow custom GPU hostname configuration.
* \section changelog31 Changes between NVML v570 and v575 ===
*
* - Added \ref nvmlSystemEventSetCreate to create a system event set.
* - Added \ref nvmlSystemEventSetFree to free a system event set.
* - Added \ref nvmlSystemRegisterEvents to register system events on a system event set.
* - Added \ref nvmlSystemEventSetWait to wait for system event notification and obtain system event data.
* - Added \ref nvmlGpuInstanceGetCreatableVgpus to query the currently creatable vGPU types on the user provided GPU Instance
* - Added \ref nvmlVgpuTypeGetMaxInstancesPerGpuInstance to query the maximum number of vGPU instances per GPU Instance for the given vGPU type
* - Added \ref nvmlGpuInstanceSetVgpuSchedulerState to set the vGPU scheduler state for the given GPU Instance
* - Added \ref nvmlGpuInstanceGetActiveVgpus to query the currently active vGPU instances on the user provided GPU Instance
* - Added \ref nvmlGpuInstanceGetVgpuSchedulerState to query the vGPU software scheduler state for the given GPU Instance.
* - Added \ref nvmlGpuInstanceGetVgpuSchedulerLog to query the vGPU software scheduler logs for the given GPU Instance.
* - Added \ref nvmlGpuInstanceGetVgpuTypeCreatablePlacements to query the creatable vGPU placement IDs of the vGPU type within a GPU instance
* - Added \ref nvmlGpuInstanceSetVgpuHeterogeneousMode to enable or disable vGPU heterogenous mode for the GPU Instance.
* - Added \ref nvmlGpuInstanceGetVgpuHeterogeneousMode to query the vGPU heterogenous mode for the GPU Instance.
* - Updated \ref nvmlDeviceGetVgpuCapabilities to report whether GPU supports timesliced vGPU on MIG and whether MIG timesliced mode is enabled or not vGPU capabilities.
* - Updated \ref nvmlDeviceSetVgpuCapabilities to set the MIG timesliced mode vGPU capability of a device.
* - Updated \ref nvmlDeviceSetVgpuHeterogeneousMode to return \ref NVML_ERROR_NOT_SUPPORTED when in MIG mode.
* - Updated \ref nvmlDeviceGetVgpuHeterogeneousMode to return \ref NVML_ERROR_NOT_SUPPORTED when in MIG mode.
* - Updated \ref nvmlDeviceGetVgpuTypeCreatablePlacements to return \ref NVML_ERROR_NOT_SUPPORTED when in MIG mode.
* - Updated \ref nvmlDeviceGetVgpuSchedulerLog to return \ref NVML_ERROR_NOT_SUPPORTED when in MIG mode.
* - Updated \ref nvmlDeviceSetVgpuSchedulerState to return \ref NVML_ERROR_NOT_SUPPORTED when in MIG mode.
* - Updated \ref nvmlDeviceGetVgpuSchedulerState to return \ref NVML_ERROR_NOT_SUPPORTED when in MIG mode.
* - Added 3 new NVML_FI_DEV_C2C_LINK_ERROR fieldIds
* - \ref NVML_FI_DEV_C2C_LINK_ERROR_INTR
* - \ref NVML_FI_DEV_C2C_LINK_ERROR_REPLAY
* - \ref NVML_FI_DEV_C2C_LINK_ERROR_REPLAY_B2B
* - Added new NVML_FI_DEV_C2C_LINK_POWER_STATE fieldId
* - Added new CTXSW GPM Metrics
* - Added \ref nvmlDeviceGetHandleByUUIDV that supports both the ASCII and binary format UUID to retrieve the device handle.
* - Added 2 new NVML_FI_DEV_POWER_SYNC_BALANCING fieldIds
* - \ref NVML_FI_DEV_POWER_SYNC_BALANCING_FREQ
* - \ref NVML_FI_DEV_POWER_SYNC_BALANCING_AF
* - Added 5 new Clock Event Reason Counters fieldIds
* - \ref NVML_FI_DEV_CLOCKS_EVENT_REASON_SW_POWER_CAP
* - \ref NVML_FI_DEV_CLOCKS_EVENT_REASON_SYNC_BOOST
* - \ref NVML_FI_DEV_CLOCKS_EVENT_REASON_SW_THERM_SLOWDOWN
* - \ref NVML_FI_DEV_CLOCKS_EVENT_REASON_HW_THERM_SLOWDOWN
* - \ref NVML_FI_DEV_CLOCKS_EVENT_REASON_HW_POWER_BRAKE_SLOWDOWN
* - Updated \ref nvmlDeviceGetMemoryErrorCounter to better account for transient vs. permanent errors
* - Added MIG profiles that can allocate all or none of Decoder, Encoder, JPEG and OFA engines.
*
* \section changelog30 Changes between NVML v565 Update and v570 ===
* - Revert the fix for the issue where PCIe throughput (reported via \ref nvmlDeviceGetPcieThroughput and nvidia-smi -q) is 1000 times bigger than its actual value
* - Added field values for data related to Power Smoothing
* - Added \ref nvmlDevicePowerSmoothingActivatePresetProfile to activate a specific Preset Profile for Power Smoothing
* - Added \ref nvmlDevicePowerSmoothingSetState to enable/disable the Power Smoothing feature
* - Added \ref nvmlDevicePowerSmoothingUpdatePresetProfileParam to update parameters to preset profiles for Power Smoothing
* - Added new enums for fieldId NVML_FI_DEV_NVLINK_GET_STATE to expose INACTIVE, ACTIVE, and SLEEP state for a link
* - Added \ref nvmlDeviceGetMarginTemperature to retrieve the thermal margin temperature (distance to nearest slowdown threshold).
* - Added \ref nvmlDeviceGetNvlinkSupportedBwModes to get all supported Nvlink Bandwidth modes
* - Added \ref nvmlDeviceGetNvlinkBwMode to get the current Nvlink Bandwidth mode
* - Added \ref nvmlDeviceSetNvlinkBwMode to set the Nvlink Bandwidth mode
* - Added MIG profiles with support for graphics.
* - Added support for new recovery action - NVML_GPU_RECOVERY_ACTION_DRAIN_AND_RESET
* - Deprecated nvml fieldIds NVML_FI_DEV_RESET_STATUS and NVML_FI_DEV_DRAIN_AND_RESET_STATUS. Usee NVML_FI_DEV_GET_GPU_RECOVERY_ACTION instead
* - Added \ref nvmlDeviceGetDramEncryptionMode and \ref nvmlDeviceSetDramEncryptionMode to query and configure DRAM Encryption Mode
* - Added 3 new flags to GPU Fabric Health Mask
* - NVML_GPU_FABRIC_HEALTH_MASK_SHIFT_ROUTE_RECOVERY
* - NVML_GPU_FABRIC_HEALTH_MASK_SHIFT_ROUTE_UNHEALTHY
* - NVML_GPU_FABRIC_HEALTH_MASK_SHIFT_ACCESS_TIMEOUT_RECOVERY
* - Added 4 new GPM metrics
* - NVML_GPM_METRIC_NVENC_0_UTIL
* - NVML_GPM_METRIC_NVENC_1_UTIL
* - NVML_GPM_METRIC_NVENC_2_UTIL
* - NVML_GPM_METRIC_NVENC_3_UTIL
* - Added new counters for Nvlink5
* - \ref NVML_FI_DEV_NVLINK_COUNT_EFFECTIVE_ERRORS to get sum of the number of errors in each Nvlink packet
* - \ref NVML_FI_DEV_NVLINK_COUNT_EFFECTIVE_BER to get Effective BER for effective errors
* - \ref NVML_FI_DEV_NVLINK_COUNT_FEC_HISTORY_0 to 15 to get count of symbol errors that are corrected
* - Swapped the values of field IDs \ref NVML_FI_DEV_IS_MIG_MODE_INDEPENDENT_MIG_QUERY_CAPABLE and \ref NVML_FI_DEV_NVLINK_GET_POWER_THRESHOLD_MAX to fix backwards compatibility with v550.
* - New revision of nvmlPlatformInfo_t -- nvmlPlatformInfo_v2 has been added. In this version the following fields from v1 have been renamed
* - rackGuid to chassisSerialNumber
* - chassisPhysicalSlotNumber to slotNumber
* - computeSlotIndex to trayIndex
* - nodeIndex to hostId
* - nvmlPlatformInfo_v1 is deprecated and will be removed in subsequent releases
*
* \section changelog29 Changes between NVML v560 Update and v565 ===
* - Fixed the ECC error count mismatch between nvidia-smi query output and NVML APIs, \ref nvmlDeviceGetMemoryErrorCounter and \ref nvmlDeviceGetFieldValues.
* - Added new value NVML_CC_SYSTEM_CPU_CAPS_AMD_SNP_VTOM for CC CPU capability reporting
* - Added \ref nvmlDeviceGetCoolerInfo to retrieve a cooler's control signal characteristics and target that cooler cools.
* - Added new value NVML_CC_SYSTEM_CPU_CAPS_AMD_SEV_SNP for CC CPU capability reporting
* - Added \ref nvmlDeviceGetFanSpeedRPM to report the intended operating speed in rotations per minute (RPM) of the device's specified fan.
* - Added \ref nvmlDeviceGetPerformanceModes to retrieve a performance modes string with all the performance modes defined for this device along with their associated GPU Clock and Memory Clock values.
* - Added \ref nvmlDeviceGetCurrentClockFreqs to retrieve a string with the associated GPU Clock and Memory Clock values for the current pstate.
* - Added \ref nvmlNvlinkVersion_t enum to define NvLink Version
* - Added \ref nvmlDeviceGetPlatformInfo to retrieve the platform information of a device
* - Added new event type nvmlEventTypeGpuUnavailableError
* - Removed support for \p nvmlDeviceGetNvLinkCrcLaneErrorCounter \p nvmlDeviceGetNvLinkEccLaneErrorCounter \p nvmlDeviceGetNvLinkErrorCounter on Blackwell
* - Removed support for fieldIds \ref NVML_FI_DEV_NVLINK_ERROR_DL_REPLAY \ref NVML_FI_DEV_NVLINK_ERROR_DL_RECOVERY \ref NVML_FI_DEV_NVLINK_ERROR_DL_CRC on Blackwell
* - Added \ref nvmlVgpuInstanceGetRuntimeStateSize to get the vGPU runtime state size
* - Updated nvmlDeviceGetVgpuTypeSupportedPlacements function to report both Heterogeneous and Homogeneous vGPU placements.
* - Updated nvmlDeviceGetVgpuCapabilities to report the Homogeneous vGPU capability.
* - Added \ref nvmlDeviceWorkloadPowerProfileGetProfilesInfo to retrieve Workload Power Profile Info
* - Added \ref nvmlDeviceWorkloadPowerProfileGetCurrentProfiles to retrieve current Requested and Enforced Workload Power Profiles
* - Added \ref nvmlDeviceWorkloadPowerProfileSetRequestedProfiles to set Requested Workload Power Profiles
* - Added \ref nvmlDeviceWorkloadPowerProfileClearRequestedProfiles to clear Requested Performance Profiles
* - Added new event type nvmlEventTypeGpuRecoveryAction
* - Added new fieldId to query gpu recovery action NVML_FI_DEV_GET_GPU_RECOVERY_ACTION
* - Deprecated fieldIds
* - \ref NVML_FI_DEV_NVLINK_COUNT_VL15_DROPPED to get Number of VL15 MADs dropped on a link in NVLink5
* - \ref NVML_FI_DEV_NVLINK_COUNT_RAW_BER_LANE0 to get BER per lane for lane 0
* - \ref NVML_FI_DEV_NVLINK_COUNT_RAW_BER_LANE1 to get BER per lane for lane 1
* - \ref NVML_FI_DEV_NVLINK_COUNT_RAW_BER to get BER per link. Sum of all the raw errors per lane/Bits received per link
* - \ref NVML_FI_DEV_NVLINK_COUNT_EFFECTIVE_ERRORS to get Sum of the number of errors in each Nvlink packet
* - \ref NVML_FI_DEV_NVLINK_COUNT_EFFECTIVE_BER to get Effective BER for effective errors
*
* \section changelog28 Changes between NVML v555 Update and v560 ===
*
* - Added field values NVML_FI_DEV_PCIE_OUTBOUND_ATOMICS_MASK and NVML_FI_DEV_PCIE_INBOUND_ATOMICS_MASK for nvmlDeviceGetFieldValues.
* - Added field ids NVML_FI_DEV_RESET_STATUS and NVML_FI_DEV_DRAIN_AND_RESET_STATUS which correspond to the nvidia-smi output.
* - Added NVML_DEVICE_ARCH_T23X architecture type.
* - Added \ref nvmlVgpuTypeGetBAR1Info to query the BAR1 information of a vGPU type.
* - Added new event types, nvmlEventTypeSingleBitEccErrorStorm, nvmlEventTypeDramRetirementEvent, nvmlEventTypeDramRetirementFailure, nvmlEventTypeNonFatalPoisonError and nvmlEventTypeFatalPoisonError.
* - Added \ref nvmlSystemGetDriverBranch to query the driver branch information.
*
* \section changelog27 Changes between NVML v550 Update and v555 ===
*
* - Added \ref nvmlDeviceGetClockOffsets to query min, max and current clock offset value on a Maxwell and later GPU for a specified clock.
* - Added \ref nvmlDeviceSetClockOffsets to control clock offset value on a Maxwell and later GPU for a specified clock.
* - Added new fieldIds for Nvlink5 telemetry on Blackwell
* - \ref NVML_FI_DEV_NVLINK_COUNT_XMIT_PACKETS to get Total Tx packets on the link in NVLink5
* - \ref NVML_FI_DEV_NVLINK_COUNT_XMIT_BYTES to get Total Tx bytes on the link in NVLink5
* - \ref NVML_FI_DEV_NVLINK_COUNT_RCV_PACKETS to get Total Rx packets on the link in NVLink5
* - \ref NVML_FI_DEV_NVLINK_COUNT_RCV_BYTES to get Total Rx bytes on the link in NVLink5
* - \ref NVML_FI_DEV_NVLINK_COUNT_VL15_DROPPED to get Number of VL15 MADs dropped on a link in NVLink5
* - \ref NVML_FI_DEV_NVLINK_COUNT_MALFORMED_PACKET_ERRORS to get Number of packets Rx on a link where packets are malformed
* - \ref NVML_FI_DEV_NVLINK_COUNT_BUFFER_OVERRUN_ERRORS to get Number of packets that were discarded on Rx due to buffer overrun
* - \ref NVML_FI_DEV_NVLINK_COUNT_RCV_ERRORS to get Total number of packets with errors Rx on a link
* - \ref NVML_FI_DEV_NVLINK_COUNT_RCV_REMOTE_ERRORS to get Total number of packets Rx - stomp/EBP marker
* - \ref NVML_FI_DEV_NVLINK_COUNT_RCV_GENERAL_ERRORS to get Total number of packets Rx with header mismatch
* - \ref NVML_FI_DEV_NVLINK_COUNT_LOCAL_LINK_INTEGRITY_ERRORS to get Total number of times that the count of local errors exceeded a threshold
* - \ref NVML_FI_DEV_NVLINK_COUNT_XMIT_DISCARDS to get Total number of tx error packets that were discarded
* - \ref NVML_FI_DEV_NVLINK_COUNT_LINK_RECOVERY_SUCCESSFUL_EVENTS to get Number of times link went from Up to recovery, succeeded and link came back up
* - \ref NVML_FI_DEV_NVLINK_COUNT_LINK_RECOVERY_FAILED_EVENTS to get Number of times link went from Up to recovery, failed and link was declared down
* - \ref NVML_FI_DEV_NVLINK_COUNT_LINK_RECOVERY_EVENTS to get Number of times link went from Up to recovery, irrespective of the result
* - \ref NVML_FI_DEV_NVLINK_COUNT_RAW_BER_LANE0 to get BER per lane for lane 0
* - \ref NVML_FI_DEV_NVLINK_COUNT_RAW_BER_LANE1 to get BER per lane for lane 1
* - \ref NVML_FI_DEV_NVLINK_COUNT_RAW_BER to get BER per link. Sum of all the raw errors per lane/Bits received per link
* - \ref NVML_FI_DEV_NVLINK_COUNT_EFFECTIVE_ERRORS to get Sum of the number of errors in each Nvlink packet
* - \ref NVML_FI_DEV_NVLINK_COUNT_EFFECTIVE_BER to get Effective BER for effective errors
* - \ref NVML_FI_DEV_NVLINK_COUNT_SYMBOL_ERRORS to get Number of errors in rx symbols
* - \ref NVML_FI_DEV_NVLINK_COUNT_SYMBOL_BER to get BER for symbol errors
* - Added two new field ids NVML_FI_DEV_PCIE_COUNT_TX_BYTES and NVML_FI_DEV_PCIE_COUNT_RX_BYTES for nvmlDeviceGetFieldValues.
* - Added new API nvmlDeviceGetCapabilities with the first capability bit NVML_DEV_CAP_EGM for Extended GPU Memory (EGM) capability.
* - Added multiGpuMode display on CC enabled system via new API nvmlSystemGetConfComputeSettings or "nvidia-smi conf-compute --get-multigpu-mode" or "nvidia-smi conf-compute -mgm".
* - Added new field ID \ref NVML_FI_DEV_NVLINK_GET_POWER_THRESHOLD_MAX to get the Max Nvlink Power Threshold for a device.
* - Deprecated \ref nvmlDeviceGetTemperature and replaced with a new API \ref nvmlDeviceGetTemperatureV to retrieve device temperature.
* - Added new field ID \ref NVML_VGPU_DRIVER_CAP_WARM_UPDATE and NVML_DEVICE_VGPU_CAP_WARM_UPDATE to query whether the driver and the device supports FSR and warm update of vGPU host driver without terminating the running guest VM respectively.
* - Added new field ID \ref NVML_FI_DEV_NVLINK_GET_POWER_THRESHOLD_MIN to get the Min Nvlink Power Threshold for a device.
* - Added new field ID \ref NVML_FI_DEV_NVLINK_GET_POWER_THRESHOLD_UNITS to get the Units of the Nvlink Power Threshold for a device.
* - Added new field ID \ref NVML_FI_DEV_NVLINK_GET_POWER_THRESHOLD_SUPPORTED to get if Nvlink Power Threshold is supported for a device.
*
*
* \section changelog26 Changes between NVML v545 Update and v550 ===
*
* - Added \ref nvmlDeviceGetNumaNodeId to query the NUMA node of a GPU.
* - Fix the issue where PCIe throughput (reported via nvmlDeviceGetPcieThroughput and nvidia-smi -q) is 1000 times bigger than its actual value.
* - Added new GPM metric Id NVML_GPM_METRIC_NVOFA_1_UTIL to \ref nvmlGpmMetricId_t.
* - Added new field ID \ref NVML_FI_DEV_IS_MIG_MODE_INDEPENDENT_MIG_QUERY_CAPABLE, to check MIG query capable device irrespective of MIG mode.
* - Deprecated NVML_P2P_CAPS_INDEX_PROP and added NVML_P2P_CAPS_INDEX_PCI to reflect the same P2P capability.
* - Added \ref nvmlDeviceGetProcessesUtilizationInfo to retrieve the recent utilization and process ID for all running processes.
* - Added new struct \ref nvmlProcessesUtilizationInfo_v1_t, which includes the new utilization of NVJPG and NVOFA.
* - Added \ref nvmlDeviceGetVgpuInstancesUtilizationInfo to retrieve the recent utilization for vGPU instances running on a physical GPU.
* - Added \ref nvmlDeviceGetVgpuProcessesUtilizationInfo to retrieve the recent utilization for processes running on vGPU instances on a physical GPU.
* - Added \ref nvmlDeviceSetVgpuHeterogeneousMode to enable or disable vGPU heterogenous mode for the device.
* - Added \ref nvmlDeviceGetVgpuHeterogeneousMode to query the vGPU heterogenous mode for the device.
* - Added \ref nvmlVgpuInstanceGetPlacementId to query placement ID of the active vGPU instance.
* - Added \ref nvmlDeviceGetVgpuTypeSupportedPlacements to query the supported vGPU placement IDs of a vGPU type.
* - Added \ref nvmlDeviceGetVgpuTypeCreatablePlacements to query the creatable vGPU placement IDs of a vGPU type.
* - Added support to display confidential compute protected memory along with fb & bar1 in nvidia-smi pmon & dmon commands.
* - Added \ref nvmlDeviceGetGpuFabricInfoV to query Gpu Fabric Probe Info for the device.
* - Deprecated \ref nvmlDeviceGetGpuFabricInfo. This function should not be used, and will be removed in a future release. Use \ref nvmlDeviceGetGpuFabricInfoV instead.
* - Modified \ref nvmlDeviceGetGpuInstanceProfileInfo and \ref nvmlDeviceGetGpuInstancePossiblePlacements_v2 to no longer require MIG being enabled
* - Added \ref nvmlSystemSetConfComputeKeyRotationThresholdInfo to set confidential compute key rotation threshold.
* - Added \ref nvmlSystemGetConfComputeKeyRotationThresholdInfo to query confidential compute key rotation threshold detail.
* - Added \ref nvmlDeviceSetVgpuCapabilities to set the desirable vGPU capability of a device.
*
*
* \section changelog25 Changes between NVML v535 Update and v545 ===
*
* - Added a new error code \ref NVML_ERROR_GPU_NOT_FOUND to be returned if no supported GPUS are found during initialization.
* - In \ref nvmlGpuFabricInfo_t \p partitionId has been renamed to \p cliqueId.
* - Added new versioned structs \ref nvmlGpuInstanceProfileInfo_v3_t and \ref nvmlComputeInstanceProfileInfo_v3_t.
* - Added \ref nvmlDeviceGetLastBBXFlushTime for retrieving the timestamp and duration of the latest flush of the BBX object to the inforom storage.
* - Added \ref NVML_POWER_SCOPE_MEMORY to report out power usage for GPU Memory.
* - Added \ref nvmlDeviceGetPciInfoExt which expands \ref nvmlDeviceGetPciInfo_v3 to also report PCI base and sub classcodes.
* - Added new struct \ref nvmlPciInfoExt_v1_t, which is used in \ref nvmlDeviceGetPciInfoExt.
* - Added \ref nvmlDeviceGetRunningProcessDetailList api to get information about Compute, Graphics or MPS-Compute processes running on a GPU with protected memory usage info.
*
*
* \section changelog24 Changes between NVML v530 Update and v535 ===
*
* - Fixed \ref nvmlDeviceGetMemoryErrorCounter and \ref nvmlDeviceGetFieldValues to return correct SRAM volatile total error counts.
* - Added \ref nvmlDeviceGetSramEccErrorStatus to query SRAM ECC error status for the device.
* - Added \ref nvmlDeviceGetModuleId for getting device module id
* - Updated \ref nvmlDeviceGetPowerSource API to report undersized power source.
* - Added \ref nvmlDeviceGetJpgUtilization and \ref nvmlDeviceGetOfaUtilization APIs
* - Added \ref nvmlSystemGetNvlinkBwMode and \ref nvmlSystemSetNvlinkBwMode APIs
* - Added \ref nvmlDeviceSetVgpuSchedulerState to set the vGPU scheduler state.
* - Added new field ID \ref NVML_FI_DEV_IS_RESETLESS_MIG_SUPPORTED for device's resetless MIG capability
* - Added \ref nvmlDeviceGetComputeRunningProcesses_v3 to get information about Compute processes running on a GPU.
* - Added \ref nvmlDeviceGetGraphicsRunningProcesses_v3 to get information about Graphics processes running on a GPU.
* - Added \ref nvmlDeviceGetMPSComputeRunningProcesses_v3 to get information about MPS-Compute processes running on a GPU.
* - Added \ref nvmlDeviceGetRunningProcessDetailList to get information about Compute, Graphics or MPS-Compute processes running on a GPU with protected memory usage info. Currently returns NVML_ERROR_NOT_SUPPORTED. Functionality will be implemented in next release.
* - Added new field ID \ref NVML_FI_DEV_PCIE_COUNT_CORRECTABLE_ERRORS for PCIe correctable errors counter
* - Added new field ID \ref NVML_FI_DEV_PCIE_COUNT_NAKS_RECEIVED for PCIe NAK Receive counter
* - Added new field ID \ref NVML_FI_DEV_PCIE_COUNT_RECEIVER_ERROR for PCIe receiver error counter
* - Added new field ID \ref NVML_FI_DEV_PCIE_COUNT_BAD_TLP for PCIe bad TLP counter
* - Added new field ID \ref NVML_FI_DEV_PCIE_COUNT_NAKS_SENT for NAK Send counter
* - Added new field ID \ref NVML_FI_DEV_PCIE_COUNT_BAD_DLLP for PCIe bad DLLP counter
* - Added new field ID \ref NVML_FI_DEV_PCIE_COUNT_NON_FATAL_ERROR for PCIe non fatal error counter
* - Added new field ID \ref NVML_FI_DEV_PCIE_COUNT_FATAL_ERROR for PCIe fatal error counter
* - Added new field ID \ref NVML_FI_DEV_PCIE_COUNT_UNSUPPORTED_REQ for PCIe unsupported request counter
* - Added new field ID \ref NVML_FI_DEV_PCIE_COUNT_LCRC_ERROR for PCIe LCRC error counter
* - Added new field ID \ref NVML_FI_DEV_PCIE_COUNT_LANE_ERROR for per lane error counter with scope as PCIe lane number.
* - Added \ref nvmlDeviceGetPowerUsage to retrieve current power usage
* - Added \ref nvmlDeviceGetTotalEnergyConsumption to get current energy consumption
* - Added \ref nvmlDeviceSetPowerManagementLimit_v2 to set the power limit
* - Renamed nvmlDeviceCcuGetStreamState to nvmlGpmQueryIfStreamingEnabled and nvmlDeviceCcuSetStreamState to nvmlGpmSetStreamingEnabled.
*
*
* \section changelog23 Changes between NVML v525 Update and v530 ===
*
* - Fixed a typo in nvmlGpuP2PStatus_t: added a new enum entry for NVML_P2P_STATUS_CHIPSET_NOT_SUPPORTED with the same numeric value as the existing erroneous entry ("NVML_P2P_STATUS_CHIPSET_NOT_SUPPORED")
* - Added \ref nvmlDeviceGetVgpuSchedulerLog to fetch the vGPU software scheduler logs.
* - Added \ref nvmlDeviceGetVgpuSchedulerState to fetch the vGPU software scheduler state.
* - Added \ref nvmlDeviceGetVgpuSchedulerCapabilities to fetch the vGPU software scheduler capabilities.
*
*
* \section changelog22 Changes between NVML v520 Update and v525 ===
*
* - Added \ref nvmlDeviceSetNvLinkDeviceLowPowerThreshold to set the NvLink low power threshold.
* - Added \p nvmlDeviceGetPcieAtomicCaps to report PCIe atomic capabilities.
* - Added \p nvmlDeviceCcuGetStreamState API to report the counter collection unit stream state.
* - Added \p nvmlDeviceCcuSetStreamState API to set the counter collection unit stream state.
* - Removed support for NVML_FI_DEV_LINK_SPEED_MBPS_L{0..} field Ids in Hopper. Replaced with NVML_FI_DEV_NVLINK_GET_SPEED with scope as link Id.
* - Removed support for NVML_FI_DEV_NVLINK_CRC_FLIT_ERROR_COUNT{0..} field Ids in Hopper. Replaced with NVML_FI_DEV_NVLINK_ERROR_DL_CRC with scope as link Id.
* - Removed support for NVML_FI_DEV_NVLINK_REPLAY_ERROR_COUNT_L{0..} field Ids in Hopper. Replaced with NVML_FI_DEV_NVLINK_ERROR_DL_REPLAY with scope as link Id.
* - Removed support for NVML_FI_DEV_NVLINK_RECOVERY_ERROR_COUNT_{0..} field Ids in Hopper. Replaced with NVML_FI_DEV_NVLINK_ERROR_DL_RECOVERY with scope as link Id.
* - Added new field ID \ref NVML_FI_DEV_NVLINK_GET_STATE to get nvlink state
* - Added new field ID \ref NVML_FI_DEV_NVLINK_GET_VERSION to get nvlink version
* - Added new field ID \ref NVML_FI_DEV_C2C_LINK_COUNT to get C2C link count
* - Added new field ID \ref NVML_FI_DEV_C2C_LINK_GET_STATUS to get C2C link status
* - Added new field ID \ref NVML_FI_DEV_C2C_LINK_GET_MAX_BW to get C2C link bandwidth
*
*
* \section changelog21 Changes between NVML v515 Update and v520 ===
*
* - Added \ref nvmlDeviceGetMemClkVfOffset API to report the MemClk VF offset value.
* - Added \ref nvmlDeviceGetMemClkMinMaxVfOffset API to report the Memory clock min and max VF offset that user can set for a specified GPU.
* - Added \ref nvmlDeviceGetGpcClkMinMaxVfOffset API to report the Graphics clock min and max VF offset that user can set for a specified GPU.
* - Added \ref nvmlGpmMetricsGet to calculate GPM metrics from two GPM samples
* - Added \ref nvmlGpmSampleFree to free allocated GPM sample
* - Added \ref nvmlGpmSampleAlloc to allocate a GPM sample
* - Added \ref nvmlGpmSampleGet to retrieve a GPM snapshot
* - Added \ref nvmlGpmQueryDeviceSupport to query whether a device supports GPM
* - Added \ref nvmlDeviceGetFanControlPolicy_v2 API to report the control policy for a specified GPU fan.
* - Added \ref nvmlDeviceSetFanControlPolicy API to set the control policy for a specified GPU fan.
*
*
* \section changelog20 Changes between NVML v510 Update and v515 ===
*
* - Added \ref nvmlDeviceGetMinMaxClockOfPState API to report the min and max clocks of some clock domain for a given PState.
* - Added \ref nvmlDeviceGetSupportedPerformanceStates API to get all supported Performance States (P-States) for the GPU.
* - Added \ref nvmlDeviceGetGpcClkVfOffset API to report the GPCCLK VF offset value.
* - Added \ref nvmlDeviceGetMinMaxFanSpeed API to report the min and max fan speed that user can set for a specified GPU fan.
*
*
* \section changelog19 Changes between NVML v495 Update and v510 ===
*
* - Added \ref nvmlDeviceGetGpuInstanceProfileInfoV and \ref nvmlGpuInstanceGetComputeInstanceProfileInfoV APIs to include the profile name in their output.
* - Added \ref nvmlDeviceGetMemoryBusWidth API to report the GPU's Memory Bus Width.
* - Added \ref nvmlDeviceGetPcieLinkMaxSpeed API to report the GPU's PCIe Max Speed.
* - Added \ref nvmlDeviceGetPowerSource API to report the GPU's power source as AC or battery.
* - Added \ref nvmlDeviceGetNumFans API to report the GPU's number of fans.
* - Added \ref nvmlDeviceGetNumGpuCores API to report the GPU's number of cores.
* - Added \ref nvmlDeviceGetMemoryInfo_v2. The new version accounts separately for system-reserved memory, and includes it in the used memory amount. The previous version of the API reduced the total memory amount by the amount of system-reserved memory.
* - Added \ref nvmlDeviceGetAdaptiveClockInfoStatus API to report the status of adaptive clocking for the GPU.
*
*
* \section changelog18 Changes between NVML v465 Update and v470 ===
*
* - Added new MIG GPU instance profile NVML_GPU_INSTANCE_PROFILE_1_SLICE_REV1.
* - Added \ref nvmlDeviceGetGpuInstancePossiblePlacements_v2. The previous version of the API will not support the profiles with possible placements greater than its total capacity, such as NVML_GPU_INSTANCE_PROFILE_1_SLICE_REV1.
*
*
* \section changelog17 Changes between NVML v460 Update and v465 ===
*
* - Added new NVML_BRAND_* enumeration values for NVIDIA, NVIDIA_RTX, GEFORCE_RTX, QUADRO_RTX and TITAN_RTX
* - Updated \ref nvmlDeviceGetHandleByUUID to make it MIG-aware.
* - Updated \ref nvmlDeviceGetUUID to return MIG UUIDs in the canonical format, 'MIG-UUID'.
* - Updated \ref nvmlDeviceGetHandleByUUID to accept both UUID formats, 'MIG-UUID' and 'MIG-GPU UUID/GID/CID'.
* - The \ref nvmlDeviceSetAPIRestriction and \ref nvmlDeviceGetAPIRestriction APIs would no longer support the ability to toggle root-only requirement for \ref nvmlDeviceSetApplicationsClocks and \ref nvmlDeviceResetApplicationsClocks.
*
*
* \section changelog16 Changes between NVML v450 Update and v460 ===
*
* - Added \ref nvmlDeviceCreateGpuInstanceWithPlacement to allow placement specification when creating a new MIG GPU instance.
*
*
* \section changelog15 Changes between NVML v445 Update and v450 ===
*
* - Updated \ref nvmlDeviceGetFanSpeed and \ref nvmlDeviceGetFanSpeed_v2 for allowing fan speeds greater than 100% to be reported.
* - Added \ref nvmlDeviceGetCpuAffinityWithinScope to determine the closest processor(s) within a NUMA node or socket.
* - Added \ref nvmlDeviceGetMemoryAffinity to determine the closest NUMA node(s) within a NUMA node or socket.
* - Added support to query and disable MIG mode on Windows.
*
*
* \section changelog14 Changes between NVML v418 Update and v445 ===
*
* - Added support for NVIDIA Ampere architecture.
* - Added support for Multi Instance GPU management. Refer "Multi Instance GPU Management" section for details.
*
*
* \section changelog13 Changes between NVML v361 Update and v418
*
* - Support for Volta and Turing architectures, bug fixes, performance improvements, and new features
*
*
* \section changelog12 Changes between NVML v349 Update and v361
*
* - Added \ref nvmlDeviceGetBoardPartNumber to return GPU part numbers
* - Removed support for exclusive thread compute mode (Deprecated in 7.5)
* - Added NVML_CLOCK_VIDEO (encoder/decoder) clock type as a supported clock type for \ref nvmlDeviceGetClockInfo and \ref nvmlDeviceGetMaxClockInfo.
*
*
* \section changelog11 Changes between NVML v346 Update and v349
*
* The following new functionality is exposed on NVIDIA display drivers version 349 Production or later
* - Updated \ref nvmlDeviceGetMemoryInfo to report Used/Free memory under Windows WDDM mode
* - Added \ref nvmlDeviceGetTopologyCommonAncestor to find the common path between two devices
* - Added \ref nvmlDeviceGetTopologyNearestGpus to get a set of GPUs given a path level
* - Added \ref nvmlSystemGetTopologyGpuSet to retrieve a set of GPUs with a given CPU affinity
* - Updated \ref nvmlDeviceGetAccountingPids, \ref nvmlDeviceGetAccountingBufferSize and \ref nvmlDeviceGetAccountingStats to report accounting information for both active and terminated processes. The execution time field in \ref nvmlAccountingStats_t structure is populated only when the process is terminated.
*
*
* \section changelog10 Changes between NVML v340 Update and v346
*
* The following new functionality is exposed on NVIDIA display drivers version 346 Production or later
* - added the public APIs nvmlDeviceGetPcieReplayCounter and nvmlDeviceGetPcieThroughput
* - Discontinued Perl bindings support
* - Added \p nvmlDeviceGetGraphicsRunningProcesses_v2 to get information about Graphics processes running on a GPU.
*
*
* \section changelog9 Changes between NVML v331 Update and v340
*
* The following new functionality is exposed on NVIDIA display drivers version 340 Production or later
* - Added \ref nvmlDeviceGetSamples to get recent power, utilization and clock samples for the GPU.
* - Added \ref nvmlDeviceGetTemperatureThreshold to retrieve temperature threshold information.
* - Added \ref nvmlDeviceGetBrand to retrieve brand information (e.g. Tesla, Quadro, etc.)
* - Added support for K40d and K80
* - Added nvmlDeviceGetTopology internal API to retrieve path info between PCI devices (remove this for DITA)
* - Added \ref nvmlDeviceGetViolationStatus to get the duration of time during which the device was throttled (lower than requested clocks) due to thermal or power constraints.
* - Added \ref nvmlDeviceGetEncoderUtilization and \ref nvmlDeviceGetDecoderUtilization APIs
* - Added \ref nvmlDeviceGetCpuAffinity to determine the closest processor(s) affinity to a specific GPU
* - Added \ref nvmlDeviceSetCpuAffinity to bind a specific GPU to the closest processor
* - Added \ref nvmlDeviceClearCpuAffinity to unbind a specific GPU
* - Added \ref nvmlDeviceGetBoardId to get a unique boardId for the running system
* - Added \ref nvmlDeviceGetMultiGpuBoard to get whether the device is on a multiGPU board
* - Added \ref nvmlDeviceGetAutoBoostedClocksEnabled and nvmlDeviceSetAutoBoostedClocksEnabled for querying and setting the state of auto boosted clocks on supporting hardware.
* - Added \ref nvmlDeviceSetDefaultAutoBoostedClocksEnabled for setting the default state of auto boosted clocks on supporting hardware.
*
*
* \section changelog8 Changes between NVML v5.319 Update and v331
*
* The following new functionality is exposed on NVIDIA display drivers version 331 Production or later
* - Added \ref nvmlDeviceGetMinorNumber to get the minor number for the device.
* - Added \ref nvmlDeviceGetBAR1MemoryInfo to get BAR1 total, available and used memory size.
* - Added \ref nvmlDeviceGetBridgeChipInfo to get the information related to bridge chip firmware.
* - Added enforced power limit query API \ref nvmlDeviceGetEnforcedPowerLimit
* - Updated \ref nvmlEventSetWait_v2 to return xid event data in case of xid error event.
* - Added support for K8
*
* \section changelog7 Changes between NVML v5.319 RC and v5.319 Update
*
* The following new functionality is exposed on NVIDIA display drivers version 319 Update or later
*
* - Added \ref nvmlDeviceSetAPIRestriction and \ref nvmlDeviceGetAPIRestriction, with initial ability to toggle root-only requirement for \ref nvmlDeviceSetApplicationsClocks and \ref nvmlDeviceResetApplicationsClocks.
*
* \section changelog6 Changes between NVML v4.304 and v5.319 RC
*
* The following new functionality is exposed on NVIDIA display drivers version 319 Production or later
*
* - IMPORTANT: Added _v2 versions of \ref nvmlDeviceGetHandleByIndex_v2 and \ref nvmlDeviceGetCount_v2 that also count devices not accessible by current user
* - IMPORTANT: nvmlDeviceGetHandleByIndex_v2 (default) can also return NVML_ERROR_NO_PERMISSION
* - Added nvmlInit_v2 and nvmlDeviceGetHandleByIndex_v2 that is safer and thus recommended function for initializing the library
* - nvmlInit_v2 lazily initializes only requested devices (queried with nvmlDeviceGetHandle*)
* - nvml.h defines nvmlInit_v2 and nvmlDeviceGetHandleByIndex_v2 as default functions
* - Added \ref nvmlDeviceGetIndex
* - Added \ref NVML_ERROR_GPU_IS_LOST to report GPUs that have fallen off the bus.
* - Note: All NVML device APIs can return this error code, as a GPU can fall off the bus at any time.
* - Added new class of APIs for gathering process statistics (\ref nvmlAccountingStats)
* - Application Clocks are no longer supported on GPU's from Quadro product line
* - Added APIs to support dynamic page retirement. See \ref nvmlDeviceGetRetiredPages and
* \ref nvmlDeviceGetRetiredPagesPendingStatus
* - Renamed nvmlClocksThrottleReasonUserDefinedClocks to nvmlClocksThrottleReasonApplicationsClocksSetting. Old name is deprecated and can be removed in one of the next major releases.
* - Added \ref nvmlDeviceGetDisplayActive and updated documentation to clarify how it differs from \ref nvmlDeviceGetDisplayMode
*
* \section changelog5 Changes between NVML v4.304 RC and v4.304 Production
*
* The following new functionality is exposed on NVIDIA display drivers version 304 Production or later
*
* - Added \ref nvmlDeviceGetGpuOperationMode and \ref nvmlDeviceSetGpuOperationMode
*
* \section changelog4 Changes between NVML v3.295 and v4.304 RC
*
* The following new functionality is exposed on NVIDIA display drivers version 304 RC or later
*
* - Added \ref nvmlDeviceGetInforomConfigurationChecksum and \ref nvmlDeviceValidateInforom
* - Added new error return value for initialization failure due to kernel module not receiving interrupts
* - Added \ref nvmlDeviceSetApplicationsClocks, \ref nvmlDeviceGetApplicationsClock, \ref nvmlDeviceResetApplicationsClocks
* - Added \ref nvmlDeviceGetSupportedMemoryClocks and \ref nvmlDeviceGetSupportedGraphicsClocks
* - Added \ref nvmlDeviceGetPowerManagementLimitConstraints, \ref nvmlDeviceGetPowerManagementDefaultLimit and \ref nvmlDeviceSetPowerManagementLimit
* - Added \ref nvmlDeviceGetInforomImageVersion
* - Expanded \ref nvmlDeviceGetUUID to support all CUDA capable GPUs
* - Deprecated \ref nvmlDeviceGetDetailedEccErrors in favor of \ref nvmlDeviceGetMemoryErrorCounter
* - Added \ref NVML_MEMORY_LOCATION_TEXTURE_MEMORY to support reporting of texture memory error counters
* - Added \ref nvmlDeviceGetCurrentClocksThrottleReasons and \ref nvmlDeviceGetSupportedClocksThrottleReasons
* - \ref NVML_CLOCK_SM is now also reported on supported Kepler devices.
* - Dropped support for GT200 based Tesla brand GPUs: C1060, M1060, S1070
*
* \section changelog3 Changes between NVML v2.285 and v3.295
*
* The following new functionality is exposed on NVIDIA display drivers version 295 or later
*
* - deprecated \ref nvmlDeviceGetHandleBySerial in favor of newly added \ref nvmlDeviceGetHandleByUUID
* - Marked the input parameters of \ref nvmlDeviceGetHandleBySerial, \ref nvmlDeviceGetHandleByUUID and \ref nvmlDeviceGetHandleByPciBusId_v2 as const
* - Added \ref nvmlDeviceOnSameBoard
* - Added \ref nvmlConstants defines
* - Added \ref nvmlDeviceGetMaxPcieLinkGeneration, \ref nvmlDeviceGetMaxPcieLinkWidth, \ref nvmlDeviceGetCurrPcieLinkGeneration,\ref nvmlDeviceGetCurrPcieLinkWidth
* - Format change of \ref nvmlDeviceGetUUID output to match the UUID standard. This function will return a different value.
* - \ref nvmlDeviceGetDetailedEccErrors will report zero for unsupported ECC error counters when a subset of ECC error counters are supported
* \section changelog1 Changes between NVML v1.0 and v2.285
*
* The following new functionality is exposed on NVIDIA display drivers version 285 or later
*
* - Added possibility to query separately current and pending driver model with \p nvmlDeviceGetDriverModel
* - Added API \ref nvmlDeviceGetVbiosVersion function to report VBIOS version.
* - Added pciSubSystemId to \ref nvmlPciInfo_t struct
* - Added API \ref nvmlErrorString function to convert error code to string
* - Updated docs to indicate we support M2075 and C2075
* - Added API \ref nvmlSystemGetHicVersion function to report HIC firmware version
* - Added NVML versioning support
* - Functions that changed API and/or size of structs have appended versioning suffix
* (e.g. nvmlDeviceGetPciInfo_v2). Appropriate C defines have been
* added that map old function names to the newer version of the function
* - Added support for concurrent library usage by multiple libraries
* - Added API \ref nvmlDeviceGetMaxClockInfo function for reporting device's clock limits
* - Added new error code NVML_ERROR_DRIVER_NOT_LOADED used by \ref nvmlInit_v2
* - Extended \ref nvmlPciInfo_t struct with new field: sub system id
* - Added NVML support on Windows guest account
* - Changed format of pciBusId string (to XXXX:XX:XX.X) of \ref nvmlPciInfo_t
* - Parsing of busId in \ref nvmlDeviceGetHandleByPciBusId_v2 is less restrictive. You can pass 0:2:0.0 or 0000:02:00 and other variations
* - Added API for events waiting for GPU events (Linux only) see docs of \ref nvmlEvents
* - Added API \p nvmlDeviceGetComputeRunningProcesses_v2 and \ref nvmlSystemGetProcessName functions for looking up currently running compute applications
* - Deprecated \ref nvmlDeviceGetPowerState in favor of \ref nvmlDeviceGetPerformanceState.
* - Added \ref NVML_FI_DEV_POWER_REQUESTED_LIMIT to report out the power limit requested by the client.
*/

View File

@@ -0,0 +1,33 @@
/*! @page DeprecationNotices Deprecation and/or removal notices for the NVML library
* This chap†er lists the NVML functions marked for deprecation and/or removal. Starting from CUDA 13.1 deprecated functions will generate a compiler warning. Removed functions will return the NVML error code NVML_ERROR_DEPRECATED.
*
* \section depNotice1 CUDA 13.0 ===
* The following functions are deprecated starting CUDA 13.0; they will be removed in CUDA 14.0.
*
* - nvmlDeviceSetApplicationsClocks
* - nvmlDeviceGetApplicationsClock
* - nvmlDeviceGetDefaultApplicationsClock
* - nvmlDeviceResetApplicationsClocks
* - nvmlDeviceGetViolationStatus
* - nvmlVgpuInstanceGetLicenseStatus
* - nvmlDeviceResetNvLinkUtilizationCounter
* - nvmlDeviceFreezeNvLinkUtilizationCounter
* - nvmlDeviceGetNvLinkUtilizationCounter
* - nvmlDeviceGetNvLinkUtilizationControl
* - nvmlDeviceSetNvLinkUtilizationControl
* - nvmlDeviceSetMemClkVfOffset
* - nvmlDeviceSetGpcClkVfOffset
* - nvmlDeviceGetGpuFabricInfo
* - nvmlDeviceGetDetailedEccErrors
* - nvmlDeviceGetPowerManagementMode
* - nvmlDeviceGetPowerState
* - nvmlDeviceGetSupportedClocksThrottleReasons
* - nvmlDeviceGetCurrentClocksThrottleReasons
* - nvmlDeviceGetTemperature
* - nvmlDeviceGetHandleBySerial
*
* The following data structures are deprecated starting CUDA 13.0
*
* - nvmlGpuFabricInfo_v2_t
*
*/

View File

@@ -0,0 +1,87 @@
ARCH := $(shell getconf LONG_BIT)
OS := $(shell cat /etc/issue)
ifneq (,$(wildcard /etc/redhat-release))
RHEL_OS := $(shell cat /etc/redhat-release)
endif
# Gets Driver Branch
DRIVER_BRANCH := $(shell nvidia-smi | grep Driver | cut -f 3 -d' ' | cut -f 1 -d '.')
# Location of the CUDA Toolkit
CUDA_PATH ?= "/usr/local/cuda-8.0"
ifeq (${ARCH},$(filter ${ARCH},32 64))
# If correct architecture and libnvidia-ml library is not found
# within the environment, build using the stub library
ifneq (,$(findstring Ubuntu,$(OS)))
DEB := $(shell dpkg -l | grep cuda)
ifneq (,$(findstring cuda, $(DEB)))
NVML_LIB := /usr/lib/nvidia-$(DRIVER_BRANCH)
else
NVML_LIB := /lib${ARCH}
endif
endif
ifneq (,$(findstring SUSE,$(OS)))
RPM := $(shell rpm -qa cuda*)
ifneq (,$(findstring cuda, $(RPM)))
NVML_LIB := /usr/lib${ARCH}
else
NVML_LIB := /lib${ARCH}
endif
endif
ifneq (,$(findstring CentOS,$(RHEL_OS)))
RPM := $(shell rpm -qa cuda*)
ifneq (,$(findstring cuda, $(RPM)))
NVML_LIB := /usr/lib${ARCH}/nvidia
else
NVML_LIB := /lib${ARCH}
endif
endif
ifneq (,$(findstring Red Hat,$(RHEL_OS)))
RPM := $(shell rpm -qa cuda*)
ifneq (,$(findstring cuda, $(RPM)))
NVML_LIB := /usr/lib${ARCH}/nvidia
else
NVML_LIB := /lib${ARCH}
endif
endif
ifneq (,$(findstring Fedora,$(RHEL_OS)))
RPM := $(shell rpm -qa cuda*)
ifneq (,$(findstring cuda, $(RPM)))
NVML_LIB := /usr/lib${ARCH}/nvidia
else
NVML_LIB := /lib${ARCH}
endif
endif
else
NVML_LIB := ../../lib${ARCH}/stubs/
$(info "libnvidia-ml.so.1" not found, using stub library.)
endif
ifneq (${ARCH},$(filter ${ARCH},32 64))
$(error Unknown architecture!)
endif
NVML_LIB += ../lib/
NVML_LIB_L := $(addprefix -L , $(NVML_LIB))
CFLAGS := -I ../../include -I ../include
LDFLAGS := -lnvidia-ml $(NVML_LIB_L)
all: example supportedVgpus
example: example.o
$(CC) $< $(CFLAGS) $(LDFLAGS) -o $@
supportedVgpus: supportedVgpus.o
$(CC) $< $(CFLAGS) $(LDFLAGS) -o $@
clean:
-@rm -f example.o
-@rm -f example
-@rm -f supportedVgpus.o
-@rm -f supportedVgpus

View File

@@ -0,0 +1,10 @@
The NVIDIA GDK provides a simple example program that shows how to build an
NVML client. When running an NVML client while the GDK is installed, be
sure your library path first includes the actual NVML library (installed
with the driver), not the stub library that exists solely for
compilation on systems without an NVIDIA driver available.
If you have installed this example code via your packaging system,
you should first copy it to a user directory before compilation.
The packaging system uninstall feature will not remove this directory if it
contains new files beyond what were installed as part of the GDK.

View File

@@ -0,0 +1,180 @@
/***************************************************************************\
|* *|
|* Copyright 2010-2016 NVIDIA Corporation. All rights reserved. *|
|* *|
|* NOTICE TO USER: *|
|* *|
|* This source code is subject to NVIDIA ownership rights under U.S. *|
|* and international Copyright laws. Users and possessors of this *|
|* source code are hereby granted a nonexclusive, royalty-free *|
|* license to use this code in individual and commercial software. *|
|* *|
|* NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE *|
|* CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR *|
|* IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH *|
|* REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF *|
|* MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR *|
|* PURPOSE. IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, *|
|* INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES *|
|* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN *|
|* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING *|
|* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE *|
|* CODE. *|
|* *|
|* U.S. Government End Users. This source code is a "commercial item" *|
|* as that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting *|
|* of "commercial computer software" and "commercial computer software *|
|* documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) *|
|* and is provided to the U.S. Government only as a commercial end item. *|
|* Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through *|
|* 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the *|
|* source code with only those rights set forth herein. *|
|* *|
|* Any use of this source code in individual and commercial software must *|
|* include, in the user documentation and internal comments to the code, *|
|* the above Disclaimer and U.S. Government End Users Notice. *|
|* *|
|* *|
\***************************************************************************/
#include <stdio.h>
#include <nvml.h>
static const char * convertToComputeModeString(nvmlComputeMode_t mode)
{
switch (mode)
{
case NVML_COMPUTEMODE_DEFAULT:
return "Default";
case NVML_COMPUTEMODE_EXCLUSIVE_THREAD:
return "Exclusive_Thread";
case NVML_COMPUTEMODE_PROHIBITED:
return "Prohibited";
case NVML_COMPUTEMODE_EXCLUSIVE_PROCESS:
return "Exclusive Process";
default:
return "Unknown";
}
}
int main(void)
{
nvmlReturn_t result;
unsigned int device_count, i;
// First initialize NVML library
result = nvmlInit();
if (NVML_SUCCESS != result)
{
printf("Failed to initialize NVML: %s\n", nvmlErrorString(result));
printf("Press ENTER to continue...\n");
getchar();
return 1;
}
result = nvmlDeviceGetCount(&device_count);
if (NVML_SUCCESS != result)
{
printf("Failed to query device count: %s\n", nvmlErrorString(result));
goto Error;
}
printf("Found %u device%s\n\n", device_count, device_count != 1 ? "s" : "");
printf("Listing devices:\n");
for (i = 0; i < device_count; i++)
{
nvmlDevice_t device;
char name[NVML_DEVICE_NAME_BUFFER_SIZE];
nvmlPciInfo_t pci;
nvmlComputeMode_t compute_mode;
// Query for device handle to perform operations on a device
// You can also query device handle by other features like:
// nvmlDeviceGetHandleBySerial
// nvmlDeviceGetHandleByPciBusId
result = nvmlDeviceGetHandleByIndex(i, &device);
if (NVML_SUCCESS != result)
{
printf("Failed to get handle for device %u: %s\n", i, nvmlErrorString(result));
goto Error;
}
result = nvmlDeviceGetName(device, name, NVML_DEVICE_NAME_BUFFER_SIZE);
if (NVML_SUCCESS != result)
{
printf("Failed to get name of device %u: %s\n", i, nvmlErrorString(result));
goto Error;
}
// pci.busId is very useful to know which device physically you're talking to
// Using PCI identifier you can also match nvmlDevice handle to CUDA device.
result = nvmlDeviceGetPciInfo(device, &pci);
if (NVML_SUCCESS != result)
{
printf("Failed to get pci info for device %u: %s\n", i, nvmlErrorString(result));
goto Error;
}
printf("%u. %s [%s]\n", i, name, pci.busId);
// This is a simple example on how you can modify GPU's state
result = nvmlDeviceGetComputeMode(device, &compute_mode);
if (NVML_ERROR_NOT_SUPPORTED == result)
printf("\t This is not CUDA capable device\n");
else if (NVML_SUCCESS != result)
{
printf("Failed to get compute mode for device %u: %s\n", i, nvmlErrorString(result));
goto Error;
}
else
{
// try to change compute mode
printf("\t Changing device's compute mode from '%s' to '%s'\n",
convertToComputeModeString(compute_mode),
convertToComputeModeString(NVML_COMPUTEMODE_PROHIBITED));
result = nvmlDeviceSetComputeMode(device, NVML_COMPUTEMODE_PROHIBITED);
if (NVML_ERROR_NO_PERMISSION == result)
printf("\t\t Need root privileges to do that: %s\n", nvmlErrorString(result));
else if (NVML_ERROR_NOT_SUPPORTED == result)
printf("\t\t Compute mode prohibited not supported. You might be running on\n"
"\t\t windows in WDDM driver model or on non-CUDA capable GPU\n");
else if (NVML_SUCCESS != result)
{
printf("\t\t Failed to set compute mode for device %u: %s\n", i, nvmlErrorString(result));
goto Error;
}
else
{
printf("\t Restoring device's compute mode back to '%s'\n",
convertToComputeModeString(compute_mode));
result = nvmlDeviceSetComputeMode(device, compute_mode);
if (NVML_SUCCESS != result)
{
printf("\t\t Failed to restore compute mode for device %u: %s\n", i, nvmlErrorString(result));
goto Error;
}
}
}
}
result = nvmlShutdown();
if (NVML_SUCCESS != result)
printf("Failed to shutdown NVML: %s\n", nvmlErrorString(result));
printf("All done.\n");
printf("Press ENTER to continue...\n");
getchar();
return 0;
Error:
result = nvmlShutdown();
if (NVML_SUCCESS != result)
printf("Failed to shutdown NVML: %s\n", nvmlErrorString(result));
printf("Press ENTER to continue...\n");
getchar();
return 1;
}

View File

@@ -0,0 +1,160 @@
/***************************************************************************\
|* *|
|* Copyright 2010-2016 NVIDIA Corporation. All rights reserved. *|
|* *|
|* NOTICE TO USER: *|
|* *|
|* This source code is subject to NVIDIA ownership rights under U.S. *|
|* and international Copyright laws. Users and possessors of this *|
|* source code are hereby granted a nonexclusive, royalty-free *|
|* license to use this code in individual and commercial software. *|
|* *|
|* NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE *|
|* CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR *|
|* IMPLIED WARRANTY OF ANY KIND. NVIDIA DISCLAIMS ALL WARRANTIES WITH *|
|* REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF *|
|* MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR *|
|* PURPOSE. IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, *|
|* INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES *|
|* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN *|
|* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING *|
|* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE *|
|* CODE. *|
|* *|
|* U.S. Government End Users. This source code is a "commercial item" *|
|* as that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting *|
|* of "commercial computer software" and "commercial computer software *|
|* documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) *|
|* and is provided to the U.S. Government only as a commercial end item. *|
|* Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through *|
|* 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the *|
|* source code with only those rights set forth herein. *|
|* *|
|* Any use of this source code in individual and commercial software must *|
|* include, in the user documentation and internal comments to the code, *|
|* the above Disclaimer and U.S. Government End Users Notice. *|
|* *|
|* *|
\***************************************************************************/
#include <stdio.h>
#include <nvml.h>
#include <stdlib.h>
int main(void)
{
nvmlReturn_t result;
unsigned int device_count, i;
// First initialize NVML library
result = nvmlInit();
if (NVML_SUCCESS != result)
{
printf("Failed to initialize NVML: %s\n", nvmlErrorString(result));
return 1;
}
result = nvmlDeviceGetCount(&device_count);
if (NVML_SUCCESS != result)
{
printf("Failed to query device count: %s\n", nvmlErrorString(result));
goto Error;
}
printf("Found %u device%s\n", device_count, device_count != 1 ? "s" : "");
printf("Listing devices:\n");
for (i = 0; i < device_count; i++)
{
nvmlDevice_t device;
char name[NVML_DEVICE_NAME_BUFFER_SIZE];
nvmlPciInfo_t pci;
// Query for device handle to perform operations on a device
// You can also query device handle by other features like:
// nvmlDeviceGetHandleBySerial
// nvmlDeviceGetHandleByPciBusId
result = nvmlDeviceGetHandleByIndex(i, &device);
if (NVML_SUCCESS != result)
{
printf("Failed to get handle for device %u: %s\n", i, nvmlErrorString(result));
goto Error;
}
result = nvmlDeviceGetName(device, name, NVML_DEVICE_NAME_BUFFER_SIZE);
if (NVML_SUCCESS != result)
{
printf("Failed to get name of device %u: %s\n", i, nvmlErrorString(result));
goto Error;
}
// pci.busId is very useful to know which device physically you're talking to
// Using PCI identifier you can also match nvmlDevice handle to CUDA device.
result = nvmlDeviceGetPciInfo(device, &pci);
if (NVML_SUCCESS != result)
{
printf("Failed to get pci info for device %u: %s\n", i, nvmlErrorString(result));
goto Error;
}
printf("%u. %s [%s]\n", i, name, pci.busId);
// This is an example to get the supported vGPUs type names
unsigned int vgpuCount = 0;
nvmlVgpuTypeId_t *vgpuTypeIds = NULL;
unsigned int j;
result = nvmlDeviceGetSupportedVgpus(device, &vgpuCount, NULL);
if (NVML_ERROR_INSUFFICIENT_SIZE != result)
goto Error;
if (vgpuCount != 0)
{
vgpuTypeIds = malloc(sizeof(nvmlVgpuTypeId_t) * vgpuCount);
if (!vgpuTypeIds)
{
printf("Memory allocation of %d bytes failed \n", (int)(sizeof(*vgpuTypeIds)*vgpuCount));
goto Error;
}
result = nvmlDeviceGetSupportedVgpus(device, &vgpuCount, vgpuTypeIds);
if (NVML_SUCCESS != result)
{
printf("Failed to get the supported vGPUs with status %d \n", (int)result);
goto Error;
}
printf(" Displaying vGPU type names: \n");
for (j = 0; j < vgpuCount; j++)
{
char vgpuTypeName[NVML_DEVICE_NAME_BUFFER_SIZE];
unsigned int bufferSize = NVML_DEVICE_NAME_BUFFER_SIZE;
if (NVML_SUCCESS == (result = nvmlVgpuTypeGetName(vgpuTypeIds[j], vgpuTypeName, &bufferSize)))
{
printf(" %s\n",vgpuTypeName);
}
else
{
printf("Failed to query the vGPU type name with status %d \n", (int)result);
}
}
}
if (vgpuTypeIds)
free(vgpuTypeIds);
}
result = nvmlShutdown();
if (NVML_SUCCESS != result)
printf("Failed to shutdown NVML: %s\n", nvmlErrorString(result));
printf("All done.\n");
return 0;
Error:
result = nvmlShutdown();
if (NVML_SUCCESS != result)
printf("Failed to shutdown NVML: %s\n", nvmlErrorString(result));
return 1;
}

File diff suppressed because it is too large Load Diff

BIN
var/pkgs/ipxe/bootx64.efi Normal file

Binary file not shown.

BIN
var/pkgs/ipxe/ipxe.efi Normal file

Binary file not shown.

BIN
var/pkgs/ipxe/undionly.kpxe Normal file

Binary file not shown.

751
var/pkgs/scripts/init.sh Normal file
View File

@@ -0,0 +1,751 @@
#!/bin/bash
# ============================================================================
# Sun HPC 系统初始化脚本
# 功能:系统安装完成后自动配置 HPC 计算节点环境
# 版本1.0
# ============================================================================
set -e
# ============================================================================
# 配置变量(根据实际环境修改)
# ============================================================================
# 日志文件
LOG_FILE="/var/log/sunhpc-init.log"
FRONTEND_IP='172.16.9.254'
# HTTP 服务器地址
HTTP_SERVER="http://${FRONTEND_IP}"
# YUM 仓库配置
YUM_REPO_NAME="sunhpc-local"
YUM_REPO_BASEURL="${HTTP_SERVER}/rockylinux/9.7"
YUM_REPO_GPGCHECK=0
# 主机名映射文件(在 HTTP 服务器上)
HOSTNAME_MAP_URL="${HTTP_SERVER}/ks/hostname-map.txt"
# MOTD 文件 URL
MOTD_URL="${HTTP_SERVER}/ks/motd"
# NTP 服务器
NTP_SERVER="ntp.aliyun.com"
# DNS 服务器
DNS_SERVERS="114.114.114.114 223.5.5.5"
# ============================================================================
# 颜色输出函数
# ============================================================================
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
log_info() {
echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}
log_error() {
echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}
log_step() {
echo -e "${BLUE}[STEP]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a $LOG_FILE
}
# ============================================================================
# 基础环境准备
# ============================================================================
init_log() {
# 创建日志文件
touch $LOG_FILE
chmod 644 $LOG_FILE
log_info "=========================================="
log_info "Sun HPC Node Initialization Started"
log_info "=========================================="
}
check_network() {
log_step "Checking network connectivity..."
# 测试网络连接
if ping -c 1 -W 3 $FRONTEND_IP &>/dev/null; then
log_info "Network connectivity: OK"
return 0
else
log_warn "Cannot reach HTTP server, will retry later"
return 1
fi
}
# ============================================================================
# 1. 创建 .sunhpc-release 文件
# ============================================================================
create_release_file() {
log_step "Creating .sunhpc-release file..."
cat > /.sunhpc-release << EOF
Sun HPC Platform Release 1.0
Build Date: $(date '+%Y-%m-%d %H:%M:%S')
Hostname: $(hostname)
Kernel: $(uname -r)
Architecture: $(uname -m)
EOF
chmod 644 /.sunhpc-release
log_info "Created /.sunhpc-release file"
}
# ============================================================================
# 2. 配置主机名和 /etc/hosts
# ============================================================================
configure_hostname() {
log_step "Configuring hostname and /etc/hosts..."
local mac=$(ip link show | grep -oP 'ether \K[0-9a-f:]+' | head -1 | tr '[:upper:]' '[:lower:]')
local hostname=""
# 从 HTTP 服务器获取主机名映射
if check_network; then
# 下载主机名映射文件
local map_file="/tmp/hostname-map.txt"
curl -s -o "$map_file" "$HOSTNAME_MAP_URL" 2>/dev/null
if [[ -f "$map_file" ]]; then
# 根据 MAC 地址查找主机名
hostname=$(grep -i "$mac" "$map_file" | awk '{print $2}' | head -1)
# 如果没有找到,根据 IP 最后一段生成
if [[ -z "$hostname" ]]; then
local ip_addr=$(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1' | head -1)
local ip_last=$(echo $ip_addr | awk -F'.' '{print $4}')
hostname="cn$(printf "%03d" $ip_last)"
log_warn "No hostname mapping for MAC $mac, using generated: $hostname"
fi
else
log_warn "Cannot download hostname map, using default"
local ip_addr=$(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1' | head -1)
local ip_last=$(echo $ip_addr | awk -F'.' '{print $4}')
hostname="cn$(printf "%03d" $ip_last)"
fi
else
# 网络不通时使用默认主机名
hostname="node-$(hostname -s)"
fi
# 设置主机名
hostnamectl set-hostname "$hostname"
log_info "Hostname set to: $hostname"
# 备份原始 hosts 文件
cp /etc/hosts /etc/hosts.bak.$(date +%Y%m%d)
# 构建新的 hosts 文件
cat > /etc/hosts << EOF
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
# Sun HPC Node Configuration
$ip_addr $hostname
# Management Node
$FRONTEND_IP cluster
# Optional: Add other compute nodes here
EOF
# 尝试下载完整的集群 hosts 文件
if check_network; then
local cluster_hosts="${HTTP_SERVER}/ks/cluster-hosts.txt"
if wget --spider -q "$cluster_hosts" 2>/dev/null; then
wget -q -O /tmp/cluster-hosts.txt "$cluster_hosts"
cat /tmp/cluster-hosts.txt >> /etc/hosts
log_info "Downloaded cluster hosts configuration"
else
log_warn "$cluster_hosts not found on server."
fi
fi
log_info "Updated /etc/hosts"
}
# ============================================================================
# 3. 配置 MOTD (Message of The Day)
# ============================================================================
configure_motd() {
log_step "Configuring MOTD..."
# 备份原始 MOTD
if [[ -f /etc/motd ]]; then
cp /etc/motd /etc/motd.bak.$(date +%Y%m%d)
fi
# 尝试从服务器下载 MOTD
if check_network; then
if wget --spider -q "$MOTD_URL" 2>/dev/null; then
wget -q -O /etc/motd "$MOTD_URL"
log_info "Downloaded MOTD from server"
else
log_warn "Cannot download MOTD, creating default"
create_default_motd
fi
else
create_default_motd
fi
chmod 644 /etc/motd
}
create_default_motd() {
cat > /etc/motd << EOF
===========================================================
Sun HPC Platform - Compute Node
===========================================================
Welcome to Sun High Performance Computing Cluster
System Information:
--------------------
Hostname....: $(hostname)
IP Address..: $(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1' | head -1)
OS Version..: $(cat /etc/redhat-release 2>/dev/null || echo "Rocky Linux")
Kernel......: $(uname -r)
Architecture: $(uname -m)
CPU Cores...: $(nproc)
Memory......: $(free -h | awk '/^Mem:/{print $2}')
Important URLs:
--------------------
• Documentation : http://172.16.9.254/docs
• Job Submission : http://172.16.9.254/slurm
• Monitoring: http : http://172.16.9.254/monitor
Slurm Commands:
--------------------
sinfo - View partition information
squeue - View job queue
srun - Run interactive job
sbatch - Submit batch job
scancel - Cancel job
===========================================================
* Unauthorized access is prohibited
* All activities are logged and monitored
* For support: hpc@sun.com or ext. 12345
===========================================================
EOF
}
# ============================================================================
# 4. 配置 YUM 本地仓库
# ============================================================================
configure_yum_repo() {
log_step "Configuring YUM repository..."
local repo_file="/etc/yum.repos.d/${YUM_REPO_NAME}.repo"
# 备份现有 repo 文件
if [[ -f "$repo_file" ]]; then
cp "$repo_file" "${repo_file}.bak.$(date +%Y%m%d)"
fi
# 创建仓库配置文件
cat > "$repo_file" << EOF
[${YUM_REPO_NAME}]
name=Sun HPC Local Repository
baseurl=${YUM_REPO_BASEURL}
enabled=1
gpgcheck=${YUM_REPO_GPGCHECK}
priority=1
EOF
# 如果是 Rocky 8/9可能需要配置 appstream
if [[ -d "/etc/yum.repos.d" ]]; then
local appstream_repo="/etc/yum.repos.d/${YUM_REPO_NAME}-appstream.repo"
cat > "$appstream_repo" << EOF
[${YUM_REPO_NAME}-appstream]
name=Sun HPC Local AppStream Repository
baseurl=${YUM_REPO_BASEURL}-appstream
enabled=1
gpgcheck=${YUM_REPO_GPGCHECK}
priority=1
EOF
fi
# 清理 YUM 缓存并测试
yum clean all &>/dev/null
yum makecache &>/dev/null
if [[ $? -eq 0 ]]; then
log_info "YUM repository configured successfully"
else
log_warn "YUM repository configured but cache generation failed (network may be down)"
fi
# 显示启用的仓库
log_info "Enabled repositories:"
yum repolist 2>/dev/null | grep -E "^${YUM_REPO_NAME}" | tee -a $LOG_FILE
}
# ============================================================================
# 5. 配置 DNS 解析
# ============================================================================
configure_dns() {
log_step "Configuring DNS resolution..."
# 备份 resolv.conf
cp /etc/resolv.conf /etc/resolv.conf.bak.$(date +%Y%m%d) 2>/dev/null || true
# 配置 DNS
cat > /etc/resolv.conf << EOF
# Sun HPC DNS Configuration
nameserver ${DNS_SERVERS%% *}
$(for dns in ${DNS_SERVERS}; do echo "nameserver $dns"; done | tail -n +2)
# Local domain
search sunhpc.local local
EOF
# 防止 NetworkManager 覆盖 resolv.conf
if [[ -f /etc/NetworkManager/NetworkManager.conf ]]; then
if ! grep -q "dns=none" /etc/NetworkManager/NetworkManager.conf; then
sed -i '/^\[main\]/a dns=none' /etc/NetworkManager/NetworkManager.conf
systemctl restart NetworkManager 2>/dev/null || true
fi
fi
log_info "DNS configured: ${DNS_SERVERS}"
}
# ============================================================================
# 6. 配置 NTP 时间同步
# ============================================================================
configure_ntp() {
log_step "Configuring NTP time synchronization..."
# 使用 chrony (Rocky 8/9 默认)
if command -v chronyd &>/dev/null; then
# 备份配置
cp /etc/chrony.conf /etc/chrony.conf.bak.$(date +%Y%m%d)
# 配置 chrony
cat > /etc/chrony.conf << EOF
# Sun HPC NTP Configuration
server ${NTP_SERVER} iburst
pool 2.rocky.pool.ntp.org iburst
# Record the rate at which the system clock gains/losses time.
driftfile /var/lib/chrony/drift
# Allow the system clock to be stepped in the first three updates
makestep 1.0 3
# Enable kernel synchronization of the real-time clock (RTC)
rtcsync
# Specify file containing keys for NTP authentication
keyfile /etc/chrony.keys
# Specify directory for log files
logdir /var/log/chrony
EOF
# 重启 chrony
systemctl restart chronyd &>/dev/null
systemctl enable chronyd &>/dev/null
log_info "Chrony NTP configured with server: ${NTP_SERVER}"
else
# 使用 ntpd (旧系统)
if command -v ntpd &>/dev/null; then
cat > /etc/ntp.conf << EOF
server ${NTP_SERVER} iburst
restrict default nomodify notrap nopeer noquery
restrict 127.0.0.1
restrict ::1
driftfile /var/lib/ntp/drift
EOF
systemctl restart ntpd &>/dev/null
systemctl enable ntpd &>/dev/null
log_info "NTP configured with server: ${NTP_SERVER}"
else
log_warn "No NTP service found (chronyd or ntpd)"
fi
fi
}
# ============================================================================
# 7. 配置 SSH 服务
# ============================================================================
configure_ssh() {
log_step "Configuring SSH service..."
# 备份配置
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%Y%m%d)
# 优化 SSH 配置
sed -i 's/#PermitRootLogin.*/PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
sed -i 's/#PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
sed -i 's/#PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/#UseDNS.*/UseDNS no/' /etc/ssh/sshd_config
sed -i 's/#GSSAPIAuthentication.*/GSSAPIAuthentication no/' /etc/ssh/sshd_config
# 重启 SSH 服务
systemctl restart sshd &>/dev/null
log_info "SSH service configured"
}
# ============================================================================
# 8. 配置防火墙
# ============================================================================
configure_firewall() {
log_step "Configuring firewall..."
# 检查 firewalld 是否运行
if systemctl is-active firewalld &>/dev/null; then
# 开放常用端口
firewall-cmd --permanent --add-service=ssh &>/dev/null
firewall-cmd --permanent --add-service=dhcp &>/dev/null
firewall-cmd --permanent --add-port=873/tcp &>/dev/null # rsync
firewall-cmd --permanent --add-port=111/udp &>/dev/null # rpcbind
# 重新加载
firewall-cmd --reload &>/dev/null
log_info "Firewall configured"
else
log_warn "Firewalld not running, skipping configuration"
fi
}
# ============================================================================
# 9. 安装常用软件包
# ============================================================================
install_packages() {
log_step "Installing common packages..."
local packages=(
wget curl vim nano
htop iotop iftop
net-tools bind-utils
telnet nc tcpdump
rsync tree lsof
gcc make autoconf automake
openssl-devel zlib-devel
nfs-utils cifs-utils
ntpdate
)
if check_network; then
for pkg in "${packages[@]}"; do
if rpm -q "$pkg" &>/dev/null; then
log_info "Package already installed: $pkg"
else
log_info "Installing package: $pkg"
yum install -y "$pkg" &>> $LOG_FILE || log_warn "Failed to install: $pkg"
fi
done
else
log_warn "Network unavailable, skipping package installation"
fi
}
# ============================================================================
# 11. 配置用户环境
# ============================================================================
configure_user_env() {
log_step "Configuring user environment..."
# 创建共享目录
mkdir -p /share/{apps,home}
mkdir -p /state/partition1/{tmp,work}
# 设置权限
chmod 755 /share
chmod 1777 /state/partition1/tmp
# 配置全局环境变量
cat > /etc/profile.d/sunhpc.sh << 'EOF'
# Sun HPC Environment Variables
export SHARE_HOME=/share
export STATE_HOME=/state/partition1
EOF
chmod 644 /etc/profile.d/sunhpc.sh
log_info "User environment configured"
}
# ============================================================================
# 12. 配置系统优化参数
# ============================================================================
configure_sysctl() {
log_step "Configuring system optimization..."
cat > /etc/sysctl.d/99-sunhpc.conf << EOF
# Sun HPC System Optimization
# Network optimization
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
net.core.netdev_max_backlog = 5000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_sack = 1
net.ipv4.tcp_timestamps = 1
# Memory optimization
vm.swappiness = 10
vm.dirty_ratio = 30
vm.dirty_background_ratio = 5
vm.vfs_cache_pressure = 50
# File system
fs.file-max = 1048576
fs.inotify.max_user_watches = 1048576
# Process scheduler
kernel.sched_autogroup_enabled = 0
kernel.sched_migration_cost_ns = 5000000
EOF
sysctl -p /etc/sysctl.d/99-sunhpc.conf &>/dev/null
log_info "System optimization configured"
}
# ============================================================================
# 13. 配置系统限制
# ============================================================================
configure_limits() {
log_step "Configuring system limits..."
cat > /etc/security/limits.d/99-sunhpc.conf << EOF
# Sun HPC System Limits
* soft nofile 1048576
* hard nofile 1048576
* soft nproc 131072
* hard nproc 131072
* soft memlock unlimited
* hard memlock unlimited
root soft nofile 1048576
root hard nofile 1048576
EOF
log_info "System limits configured"
}
# ============================================================================
# 14. 配置定时任务
# ============================================================================
configure_crontab() {
log_step "Configuring cron jobs..."
cat > /etc/cron.d/sunhpc << EOF
# Sun HPC Cron Jobs
# Sync time every hour
0 * * * * root /usr/sbin/chronyc -a makestep &>/dev/null
# Clean old logs daily
0 2 * * * root find /var/log -name "*.log" -mtime +30 -delete 2>/dev/null
# Report node status every 5 minutes
*/5 * * * * root /usr/local/bin/node-status-report &>/dev/null
EOF
chmod 644 /etc/cron.d/sunhpc
log_info "Cron jobs configured"
}
# ============================================================================
# 15. 创建节点状态上报脚本
# ============================================================================
create_report_script() {
log_step "Creating node status report script..."
cat > /usr/local/bin/node-status-report << 'EOF'
#!/bin/bash
# Node status report script for Sun HPC
HTTP_SERVER="http://172.16.9.254"
NODE_NAME=$(hostname)
IP_ADDR=$(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1' | head -1)
LOAD_AVG=$(uptime | awk -F'load average:' '{print $2}' | cut -d, -f1)
MEM_TOTAL=$(free -g | awk '/^Mem:/{print $2}')
MEM_USED=$(free -g | awk '/^Mem:/{print $3}')
DISK_USED=$(df -h / | awk 'NR==2{print $5}' | sed 's/%//')
SLURM_STATUS=$(systemctl is-active slurm-slurmd 2>/dev/null || echo "unknown")
# Build status JSON
STATUS_JSON="{\"node\":\"$NODE_NAME\",\"ip\":\"$IP_ADDR\",\"load\":$LOAD_AVG,\"mem_total\":$MEM_TOTAL,\"mem_used\":$MEM_USED,\"disk_used\":$DISK_USED,\"slurm\":\"$SLURM_STATUS\",\"timestamp\":\"$(date -Iseconds)\"}"
# Send to management node
curl -s -X POST -H "Content-Type: application/json" -d "$STATUS_JSON" ${HTTP_SERVER}/api/node-status &>/dev/null
EOF
chmod +x /usr/local/bin/node-status-report
log_info "Node status report script created"
}
# ============================================================================
# 16. 配置日志轮转
# ============================================================================
configure_logrotate() {
log_step "Configuring log rotation..."
cat > /etc/logrotate.d/sunhpc << EOF
/var/log/sunhpc-init.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 644 root root
}
EOF
log_info "Log rotation configured"
}
# ============================================================================
# 17. 清理临时文件
# ============================================================================
cleanup() {
log_step "Cleaning up temporary files..."
# 删除临时文件
rm -f /tmp/hostname-map.txt 2>/dev/null
rm -f /tmp/cluster-hosts.txt 2>/dev/null
# 清除 YUM 缓存
yum clean all &>/dev/null
log_info "Cleanup completed"
}
# ============================================================================
# 18. 生成初始化完成报告
# ============================================================================
generate_report() {
log_step "Generating initialization report..."
cat > /root/init-report.txt << EOF
===========================================
Sun HPC Node Initialization Report
===========================================
Init Time: $(date '+%Y-%m-%d %H:%M:%S')
Hostname: $(hostname)
IP Address: $(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1' | head -1)
MAC Address: $(ip link show | grep -oP 'ether \K[0-9a-f:]+' | head -1)
Services Status:
- NetworkManager: $(systemctl is-active NetworkManager)
- chronyd: $(systemctl is-active chronyd 2>/dev/null || echo "stopped")
- sshd: $(systemctl is-active sshd)
- slurm-slurmd: $(systemctl is-active slurm-slurmd 2>/dev/null || echo "stopped")
- firewalld: $(systemctl is-active firewalld)
YUM Repositories:
$(yum repolist)
Files Created:
- /.sunhpc-release
- /etc/hosts (updated)
- /etc/motd (updated)
- /etc/yum.repos.d/sunhpc-local.repo
- /etc/chrony.conf (updated)
- /etc/security/limits.d/99-sunhpc.conf
- /etc/sysctl.d/99-sunhpc.conf
===========================================
EOF
cat /root/init-report.txt >> $LOG_FILE
log_info "Initialization report saved to /root/init-report.txt"
}
# ============================================================================
# 主函数
# ============================================================================
main() {
log_info "Starting Sun HPC node initialization..."
# 执行所有初始化步骤
init_log
check_network
create_release_file
configure_hostname
configure_motd
configure_yum_repo
configure_dns
configure_ntp
configure_ssh
configure_firewall
install_packages
configure_slurm
configure_user_env
configure_sysctl
configure_limits
configure_crontab
create_report_script
configure_logrotate
cleanup
generate_report
log_info "=========================================="
log_info "Sun HPC node initialization completed!"
log_info "=========================================="
# 显示关键信息
echo ""
echo -e "${GREEN}=== Initialization Complete ===${NC}"
echo -e "Hostname: $(hostname)"
echo -e "Release file: $(cat /.sunhpc-release | head -1)"
echo -e "Log file: $LOG_FILE"
echo -e "Report: /root/init-report.txt"
echo ""
}
# ============================================================================
# 脚本入口
# ============================================================================
# 检查是否需要重启
if [[ "$1" == "--reboot" ]]; then
main
log_info "Rebooting in 5 seconds..."
sleep 5
reboot
else
main
log_info "Initialization completed. You may reboot if needed."
fi

21
var/pkgs/scripts/ipxe.sh Normal file
View File

@@ -0,0 +1,21 @@
#!ipxe
:main_menu
menu iPXE boot menu
item rockylinux Install Rockylinux 9.7
item local Boot from Local Disk
choose --default rockylinux --timeout 5000 selected || goto local
:rockylinux
echo Booting Rockylinux from networking
kernel http://172.16.9.254/linux/rockylinux/9.7/images/pxeboot/vmlinuz \
net.ifnames=0 biosdevname=0 inst.sshd \
inst.repo=http://172.16.9.254/linux/rockylinux/9.7 \
inst.ks=http://172.16.9.254/linux/ks/rhel.ks
initrd http://172.16.9.254/linux/rockylinux/9.7/images/pxeboot/initrd.img
boot
:local
exit

77
var/pkgs/scripts/rhel.ks Normal file
View File

@@ -0,0 +1,77 @@
graphical
timezone Asia/Shanghai --utc
keyboard --xlayouts="us"
lang en_US.UTF-8
selinux --disabled
url --url='http://172.16.9.254/linux/rockylinux/9.7'
network --bootproto=dhcp --device=link --ipv6=auto --activate
# Partition clearing information
# zerombr
# clearpart --all --initlabel
# ignoredisk --only-use=sda
# part /boot --fstype="xfs" --ondisk=sda --size=1024
# part swap --fstype="swap" --ondisk=sda --size=4096
# part / --fstype="xfs" --ondisk=sda --size=97278
# part /home --fstype="xfs" --ondisk=sda --size=20480
# autopart --type=lvm
# autopart --type=plain
# autopart --nohome
# autopart --noswap
%include /tmp/diskinfo
%packages
@^minimal-environment
@development
@standard
vim
wget
curl
autofs
nfs-utils
nfs4-acl-tools
sssd-nfs-idmap
%end
rootpw --plaintext "admin_b101"
user --name=dell --plaintext --password="admin_b101" --gecos="dell"
reboot
%pre --interpreter=/bin/bash
if [ -d /sys/firmware/efi ]; then
cat > /tmp/diskinfo <<EOF
clearpart --all --initlabel
part /boot/efi --fstype=efi --size=600 --fsoptions="umask=0077,shortname=uefi"
part /boot --fstype=xfs --size=1024
part pv.01 --size=1 --grow
volgroup vg_sys pv.01
logvol / --fstype=xfs --name=root --vgname=vg_sys --size=51200
logvol swap --fstype=swap --name=swap --vgname=vg_sys --size=4096
logvol /data --fstype=xfs --name=data --vgname=vg_sys --size=1 --grow
EOF
else
cat > /tmp/diskinfo <<EOF
clearpart --all --initlabel
part /boot --fstype=xfs --size=1024 --asprimary
part pv.01 --size=1 --grow
volgroup vg_sys pv.01
logvol / --fstype=xfs --name=root --vgname=vg_sys --size=51200
logvol swap --fstype=swap --name=swap --vgname=vg_sys --size=4096
logvol /data --fstype=xfs --name=data --vgname=vg_sys --size=1 --grow
EOF
fi
%end
%post
curl -s -o /tmp/init.sh http://172.16.9.254/linux/ks/init.sh
chmod +x /tmp/init.sh
/tmp/init.sh
%end
%addon com_redhat_kdump --disable
%end