package wizard import ( "errors" "fmt" "net" "os" "sunhpc/pkg/database" "sunhpc/pkg/info" "sunhpc/pkg/logger" "sunhpc/pkg/utils" "github.com/BurntSushi/toml" ) // 配置项映射:定义每个配置项对应的表名、键名 type ConfigMapping struct { Title string `toml:"title"` Base struct { ClusterName string `toml:"cluster_name"` Country string `toml:"country"` State string `toml:"state"` City string `toml:"city"` HomePage string `toml:"homepage"` Contact string `toml:"contact"` License string `toml:"license"` BaseDir string `toml:"base_dir"` WorkDir string `toml:"work_dir"` DistroDir string `toml:"distro_dir"` Partition string `toml:"partition"` Distribution string `toml:"distribution"` Timezone string `toml:"timezone"` SafePort string `toml:"safe_port"` SafeDirs string `toml:"safe_dirs"` SafeSecurity string `toml:"safe_security"` PluginDirs string `toml:"plugin_dirs"` PluginPort string `toml:"plugin_port"` GangliaAddr string `toml:"ganglia_addr"` } `toml:"base"` Pxelinux struct { NextServer string `toml:"next_server"` PxeFilename string `toml:"pxe_filename"` PxeLinuxDir string `toml:"pxelinux_dir"` BootArgs string `toml:"boot_args"` } `toml:"pxelinux"` Public struct { PublicHostname string `toml:"public_hostname"` PublicInterface string `toml:"public_interface"` PublicAddress string `toml:"public_address"` PublicNetmask string `toml:"public_netmask"` PublicGateway string `toml:"public_gateway"` PublicNetwork string `toml:"public_network"` PublicDomain string `toml:"public_domain"` PublicCIDR string `toml:"public_cidr"` PublicDNS string `toml:"public_dns"` PublicMac string `toml:"public_mac"` PublicMTU string `toml:"public_mtu"` PublicNTP string `toml:"public_ntp"` } `toml:"public"` Private struct { PrivateHostname string `toml:"private_hostname"` PrivateInterface string `toml:"private_interface"` PrivateAddress string `toml:"private_address"` PrivateNetmask string `toml:"private_netmask"` PrivateNetwork string `toml:"private_network"` PrivateDomain string `toml:"private_domain"` PrivateCIDR string `toml:"private_cidr"` PrivateMac string `toml:"private_mac"` PrivateMTU string `toml:"private_mtu"` } `toml:"private"` } type IPMaskInfo struct { NetworkAddress string // 网络地址 192.168.1.0 CIDR string // CIDR 格式 192.168.1.0/24 IPAddress string // IP 地址 192.168.1.100 MacAddress string // MAC 地址 00:11:22:33:44:55 Netmask string // 子网掩码 255.255.255.0 PrefixLength int // 前缀长度 24 } type AttrItem struct { Key string Value string Shadow string Category int Catindex int } func NewConfigWithDefault() *ConfigMapping { return &ConfigMapping{ Title: "Cluster Configuration", Base: struct { ClusterName string `toml:"cluster_name"` Country string `toml:"country"` State string `toml:"state"` City string `toml:"city"` HomePage string `toml:"homepage"` Contact string `toml:"contact"` License string `toml:"license"` BaseDir string `toml:"base_dir"` WorkDir string `toml:"work_dir"` DistroDir string `toml:"distro_dir"` Partition string `toml:"partition"` Distribution string `toml:"distribution"` Timezone string `toml:"timezone"` SafePort string `toml:"safe_port"` SafeDirs string `toml:"safe_dirs"` SafeSecurity string `toml:"safe_security"` PluginDirs string `toml:"plugin_dirs"` PluginPort string `toml:"plugin_port"` GangliaAddr string `toml:"ganglia_addr"` }{ ClusterName: "SunHPC_Cluster", Country: "CN", State: "Beijing", City: "Beijing", HomePage: "https://www.sunhpc.com", Contact: "admin@sunhpc.com", License: "MIT", BaseDir: "install", WorkDir: "/export", DistroDir: "/export/sunhpc", Partition: "default", Distribution: "sunhpc-dist", Timezone: "Asia/Shanghai", SafePort: "372", SafeDirs: "safe.d", SafeSecurity: "safe-security", PluginDirs: "/etc/sunhpc/plugin", PluginPort: "12123", GangliaAddr: "224.0.0.3", }, Pxelinux: struct { NextServer string `toml:"next_server"` PxeFilename string `toml:"pxe_filename"` PxeLinuxDir string `toml:"pxelinux_dir"` BootArgs string `toml:"boot_args"` }{ NextServer: "192.168.1.1", PxeFilename: "pxelinux.0", PxeLinuxDir: "/tftpboot/pxelinux", BootArgs: "net.ifnames=0 biosdevname=0", }, Public: struct { PublicHostname string `toml:"public_hostname"` PublicInterface string `toml:"public_interface"` PublicAddress string `toml:"public_address"` PublicNetmask string `toml:"public_netmask"` PublicGateway string `toml:"public_gateway"` PublicNetwork string `toml:"public_network"` PublicDomain string `toml:"public_domain"` PublicCIDR string `toml:"public_cidr"` PublicDNS string `toml:"public_dns"` PublicMac string `toml:"public_mac"` PublicMTU string `toml:"public_mtu"` PublicNTP string `toml:"public_ntp"` }{ PublicHostname: "cluster.hpc.org", PublicInterface: "eth0", PublicAddress: "", PublicNetmask: "", PublicGateway: "", PublicNetwork: "", PublicDomain: "hpc.org", PublicCIDR: "", PublicDNS: "", PublicMac: "00:11:22:33:44:55", PublicMTU: "1500", PublicNTP: "pool.ntp.org", }, Private: struct { PrivateHostname string `toml:"private_hostname"` PrivateInterface string `toml:"private_interface"` PrivateAddress string `toml:"private_address"` PrivateNetmask string `toml:"private_netmask"` PrivateNetwork string `toml:"private_network"` PrivateDomain string `toml:"private_domain"` PrivateCIDR string `toml:"private_cidr"` PrivateMac string `toml:"private_mac"` PrivateMTU string `toml:"private_mtu"` }{ PrivateHostname: "sunhpc", PrivateInterface: "eth1", PrivateAddress: "172.16.9.254", PrivateNetmask: "255.255.255.0", PrivateNetwork: "172.16.9.0", PrivateDomain: "example.com", PrivateCIDR: "172.16.9.0/24", PrivateMac: "00:11:22:33:44:66", PrivateMTU: "1500", }, } } func loadConfig() (*ConfigMapping, error) { configs := NewConfigWithDefault() cfgfile := "/etc/sunhpc/config.toml" // 尝试解析配置文件 if _, err := toml.DecodeFile(cfgfile, configs); err != nil { if errors.Is(err, os.ErrNotExist) { // 文件不存在,直接返回默认配置 logger.Infof("Config file %s not exist, use default config", cfgfile) return configs, nil } // 其他错误,返回错误 logger.Debugf("[DEBUG] Parse config file %s failed: %v", cfgfile, err) return nil, err } logger.Infof("Load config file %s success", cfgfile) return configs, nil } // saveConfig 入口函数:保存所有配置到数据库 func (m *model) saveConfig() error { m.force = false // 初始化全量覆盖标识 c, err := loadConfig() if err != nil { logger.Debugf("[DEBUG] Load config file failed: %v", err) return err } // 合并配置项 result := make(map[string]string) // base 配置 result["country"] = mergeValue(m.config.Country, c.Base.Country) result["state"] = mergeValue(m.config.State, c.Base.State) result["city"] = mergeValue(m.config.City, c.Base.City) result["contact"] = mergeValue(m.config.Contact, c.Base.Contact) result["homepage"] = mergeValue(m.config.HomePage, c.Base.HomePage) result["cluster_name"] = mergeValue(m.config.ClusterName, c.Base.ClusterName) result["license"] = c.Base.License result["distribution"] = c.Base.Distribution result["timezone"] = mergeValue(m.config.Timezone, c.Base.Timezone) result["base_dir"] = c.Base.BaseDir result["work_dir"] = c.Base.WorkDir result["distro_dir"] = mergeValue(m.config.DistroDir, c.Base.DistroDir) result["partition"] = c.Base.Partition // safe 配置 result["safe_port"] = c.Base.SafePort result["safe_dirs"] = c.Base.SafeDirs result["safe_security"] = c.Base.SafeSecurity // plugin 配置 result["plugin_dirs"] = c.Base.PluginDirs result["plugin_port"] = c.Base.PluginPort // monitor 配置 result["ganglia_addr"] = c.Base.GangliaAddr // public 配置 result["public_hostname"] = mergeValue(m.config.PublicHostname, c.Public.PublicHostname) result["public_interface"] = mergeValue(m.config.PublicInterface, c.Public.PublicInterface) result["public_address"] = mergeValue(m.config.PublicIPAddress, c.Public.PublicAddress) result["public_netmask"] = mergeValue(m.config.PublicNetmask, c.Public.PublicNetmask) result["public_gateway"] = mergeValue(m.config.PublicGateway, c.Public.PublicGateway) // 获取公网网络信息 publicIface := mergeValue(m.config.PublicInterface, c.Public.PublicInterface) publicInfo, err := GetNetworkInfo( publicIface, c.Public.PublicAddress, c.Public.PublicNetmask) if err != nil { logger.Debugf("[DEBUG] Get public interface %s IP mask info failed: %v", publicIface, err) } result["public_network"] = publicInfo.NetworkAddress result["public_domain"] = mergeValue(m.config.PublicDomain, c.Public.PublicDomain) result["public_cidr"] = mergeValue(c.Public.PublicCIDR, publicInfo.CIDR) result["public_dns"] = c.Public.PublicDNS result["public_mac"] = publicInfo.MacAddress result["public_mtu"] = mergeValue(m.config.PublicMTU, c.Public.PublicMTU) result["public_ntp"] = c.Public.PublicNTP // private 配置 // 获取内网网络信息 privateIface := mergeValue(m.config.PrivateInterface, c.Private.PrivateInterface) privateInfo, err := GetNetworkInfo( privateIface, c.Private.PrivateAddress, c.Private.PrivateNetmask) if err != nil { logger.Debugf("[DEBUG] Get private interface %s IP mask info failed: %v", privateIface, err) } result["private_hostname"] = mergeValue(m.config.PrivateHostname, c.Private.PrivateHostname) result["private_interface"] = mergeValue(m.config.PrivateInterface, c.Private.PrivateInterface) result["private_address"] = mergeValue(m.config.PrivateIPAddress, c.Private.PrivateAddress) result["private_netmask"] = mergeValue(m.config.PrivateNetmask, c.Private.PrivateNetmask) result["private_network"] = privateInfo.NetworkAddress result["private_domain"] = mergeValue(m.config.PrivateDomain, c.Private.PrivateDomain) result["private_cidr"] = mergeValue(c.Private.PrivateCIDR, privateInfo.CIDR) result["private_mac"] = privateInfo.MacAddress result["private_mtu"] = mergeValue(m.config.PrivateMTU, c.Private.PrivateMTU) // pxe 配置 result["next_server"] = mergeValue(privateInfo.IPAddress, c.Pxelinux.NextServer) result["pxe_filename"] = c.Pxelinux.PxeFilename result["pxelinux_dir"] = c.Pxelinux.PxeLinuxDir result["boot_args"] = c.Pxelinux.BootArgs // 插入数据到数据库 if err := insertDataToDB(result); err != nil { logger.Debugf("[DEBUG] Insert config data to database failed: %v", err) return err } logger.Debugf("Result: %v", result) return nil } func mergeValue(tui_value, cfg_value string) string { if tui_value == "" { return cfg_value } return tui_value } // 获取系统网络接口 func getNetworkInterfaces() []string { // 实现获取系统网络接口的逻辑 // 例如:使用 net.Interface() 函数获取系统网络接口 // 返回一个字符串切片,包含系统网络接口的名称 interfaces, err := net.Interfaces() if err != nil { return []string{utils.NoAvailableNetworkInterfaces} } var result []string for _, iface := range interfaces { // 跳过 loopback 接口 if iface.Flags&net.FlagLoopback != 0 { continue } result = append(result, iface.Name) } if len(result) == 0 { return []string{utils.NoAvailableNetworkInterfaces} } return result } func GetNetworkInfo(iface, ip, mask string) (*IPMaskInfo, error) { logger.Debugf("Get Network %s, IP %s, mask %s", iface, ip, mask) // 解析IP ipAddr := net.ParseIP(ip) if ipAddr == nil { logger.Debugf("Invalid IP address: %s", ip) return nil, fmt.Errorf("invalid IP address: %s", ip) } // 解析子网掩码 maskAddr := net.ParseIP(mask) if maskAddr == nil { logger.Debugf("Invalid subnet mask: %s", mask) return nil, fmt.Errorf("invalid subnet mask: %s", mask) } // 确保是IPv4地址 ipv4 := ipAddr.To4() maskv4 := maskAddr.To4() if ipv4 == nil || maskv4 == nil { logger.Debugf("Only support IPv4 address") return nil, fmt.Errorf("only support IPv4 address") } // 计算网络地址 (IP & 子网掩码) network := make([]byte, 4) for i := 0; i < 4; i++ { network[i] = ipv4[i] & maskv4[i] } networkAddr := fmt.Sprintf( "%d.%d.%d.%d", network[0], network[1], network[2], network[3]) // 计算前缀长度 prefixLen := 0 for i := 0; i < 4; i++ { for j := 7; j >= 0; j-- { if maskv4[i]&(1<