mirror of
https://github.com/MengMengCode/CLICD.git
synced 2026-08-06 05:52:19 +08:00
修复了一些已知问题
This commit is contained in:
+83
-19
@@ -429,6 +429,7 @@ func (m *Manager) defineContainer(id int, vmName string, cfg lxc.ContainerConfig
|
||||
ipv6Assignments = assigned
|
||||
}
|
||||
ipv6List := configIPv6AssignmentAddresses(ipv6Assignments)
|
||||
ipv4List := configIPv4AssignmentAddresses(publicIPv4s)
|
||||
defaultHostIP := lxc.DefaultPortMappingHostIP(publicIPv4s)
|
||||
|
||||
var xml string
|
||||
@@ -448,7 +449,7 @@ func (m *Manager) defineContainer(id int, vmName string, cfg lxc.ContainerConfig
|
||||
}
|
||||
winAdminPassword = generateWindowsPassword()
|
||||
unattendPath := filepath.Join(m.instanceDir(vmName), "unattend.iso")
|
||||
if err := createWindowsUnattendISO(unattendPath, cfg.Name, winAdminPassword, ipv6List); err != nil {
|
||||
if err := createWindowsUnattendISO(unattendPath, cfg.Name, winAdminPassword, ipv6List, ipv4List); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
xml = windowsDomainXML(vmName, int(cfg.VCPU), cfg.RAMMB, diskPath, ImagePath(image.ID), unattendPath, mac, cfg.IOSpeedMBps, cfg.NetworkBWMbps)
|
||||
@@ -464,7 +465,7 @@ func (m *Manager) defineContainer(id int, vmName string, cfg lxc.ContainerConfig
|
||||
if err := createOverlayDisk(ImagePath(image.ID), diskPath, cfg.DiskGB); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := createSeedISO(seedPath, vmName, cfg.Name, sshPassword, sshPublicKey, mac, ipv6List, *image); err != nil {
|
||||
if err := createSeedISO(seedPath, vmName, cfg.Name, sshPassword, sshPublicKey, mac, ipv6List, ipv4List, *image); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
xml = domainXML(vmName, int(cfg.VCPU), cfg.RAMMB, diskPath, seedPath, mac, cfg.IOSpeedMBps, cfg.NetworkBWMbps, image.Desktop != "")
|
||||
@@ -1389,7 +1390,7 @@ func (m *Manager) RefreshNetwork(id int) (string, error) {
|
||||
if changed {
|
||||
config.SaveConfig()
|
||||
}
|
||||
if c.Status == "running" && len(c.PortMappings) > 0 && shouldApplyPortMappings(id, changed) {
|
||||
if c.Status == "running" && shouldApplyPortMappings(id, changed) {
|
||||
if err := lxc.NewManager().ApplyPortMappings(id); err != nil {
|
||||
return ip, err
|
||||
}
|
||||
@@ -1596,7 +1597,7 @@ func createEmptyDisk(target string, diskGB int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func createWindowsUnattendISO(target, hostname, adminPassword string, ipv6s []string) error {
|
||||
func createWindowsUnattendISO(target, hostname, adminPassword string, ipv6s []string, ipv4s []string) error {
|
||||
tool := firstAvailableCommand("genisoimage", "mkisofs", "xorriso")
|
||||
if tool == "" {
|
||||
return fmt.Errorf("one of genisoimage, mkisofs, xorriso is required for Windows unattended setup")
|
||||
@@ -1622,13 +1623,13 @@ func createWindowsUnattendISO(target, hostname, adminPassword string, ipv6s []st
|
||||
if err := os.WriteFile(filepath.Join(setupScriptsDir, "SetupComplete.cmd"), []byte(windowsSetupCompleteCMD()), 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(clicdDir, "FirstLogon.ps1"), []byte(windowsFirstLogonPowerShell(adminPassword, ipv6s)), 0600); err != nil {
|
||||
if err := os.WriteFile(filepath.Join(clicdDir, "FirstLogon.ps1"), []byte(windowsFirstLogonPowerShell(adminPassword, ipv6s, ipv4s)), 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(dir, "SetupComplete.cmd"), []byte(windowsSetupCompleteCMD()), 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(dir, "FirstLogon.ps1"), []byte(windowsFirstLogonPowerShell(adminPassword, ipv6s)), 0600); err != nil {
|
||||
if err := os.WriteFile(filepath.Join(dir, "FirstLogon.ps1"), []byte(windowsFirstLogonPowerShell(adminPassword, ipv6s, ipv4s)), 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = os.Remove(target)
|
||||
@@ -1738,7 +1739,7 @@ exit /b 0
|
||||
`
|
||||
}
|
||||
|
||||
func windowsFirstLogonPowerShell(adminPassword string, ipv6s []string) string {
|
||||
func windowsFirstLogonPowerShell(adminPassword string, ipv6s []string, ipv4s []string) string {
|
||||
commands := []string{
|
||||
"$ErrorActionPreference='Continue'",
|
||||
"$ProgressPreference='SilentlyContinue'",
|
||||
@@ -1774,6 +1775,12 @@ func windowsFirstLogonPowerShell(adminPassword string, ipv6s []string) string {
|
||||
windowsIPv6PowerShell(ipv6s),
|
||||
)
|
||||
}
|
||||
ipv4s = normalizeKVMIPv4List(ipv4s)
|
||||
if len(ipv4s) > 0 {
|
||||
commands = append(commands,
|
||||
windowsIPv4PowerShell(ipv4s),
|
||||
)
|
||||
}
|
||||
commands = append(commands,
|
||||
"New-Item -ItemType File -Force -Path 'C:\\CLICD\\init.done' | Out-Null",
|
||||
"} finally { Stop-Transcript | Out-Null }",
|
||||
@@ -1806,11 +1813,47 @@ func windowsIPv6PowerShell(ipv6s []string) string {
|
||||
}, "\r\n")
|
||||
}
|
||||
|
||||
func windowsIPv4PowerShell(ipv4s []string) string {
|
||||
ipv4s = normalizeKVMIPv4List(ipv4s)
|
||||
if len(ipv4s) == 0 {
|
||||
return ""
|
||||
}
|
||||
quoted := make([]string, 0, len(ipv4s))
|
||||
for _, ipv4 := range ipv4s {
|
||||
quoted = append(quoted, "'"+strings.ReplaceAll(ipv4, "'", "''")+"'")
|
||||
}
|
||||
return strings.Join([]string{
|
||||
"$clicdIPv4=@(" + strings.Join(quoted, ",") + ")",
|
||||
"$iface=$null",
|
||||
"for ($i=0; $i -lt 60 -and -not $iface; $i++) { $iface=Get-NetAdapter | Where-Object { $_.Status -eq 'Up' -and $_.HardwareInterface } | Sort-Object ifIndex | Select-Object -First 1; if (-not $iface) { Start-Sleep -Seconds 5 } }",
|
||||
"if ($iface) {",
|
||||
" foreach ($ip in $clicdIPv4) {",
|
||||
" Get-NetIPAddress -InterfaceIndex $iface.ifIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue | Where-Object { $_.IPAddress -eq $ip } | Remove-NetIPAddress -Confirm:$false -ErrorAction SilentlyContinue",
|
||||
" New-NetIPAddress -IPAddress $ip -PrefixLength 32 -InterfaceIndex $iface.ifIndex -SkipAsSource:$false -ErrorAction SilentlyContinue | Out-Null",
|
||||
" }",
|
||||
"}",
|
||||
}, "\r\n")
|
||||
}
|
||||
|
||||
func normalizeKVMIPv4List(values []string) []string {
|
||||
seen := map[string]bool{}
|
||||
result := make([]string, 0, len(values))
|
||||
for _, value := range values {
|
||||
value = strings.TrimSpace(value)
|
||||
if value == "" || seen[value] {
|
||||
continue
|
||||
}
|
||||
seen[value] = true
|
||||
result = append(result, value)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func shellQuoteWindows(value string) string {
|
||||
return `"` + strings.ReplaceAll(value, `"`, `\"`) + `"`
|
||||
}
|
||||
|
||||
func createSeedISO(seedPath, instanceID, hostname, password, publicKey, mac string, ipv6s []string, image Image) error {
|
||||
func createSeedISO(seedPath, instanceID, hostname, password, publicKey, mac string, ipv6s []string, ipv4s []string, image Image) error {
|
||||
guestSetup := kvmSSHSetupScript(password, publicKey)
|
||||
if desktopSetup := kvmDesktopSetupScript(image); desktopSetup != "" {
|
||||
guestSetup += "\n" + desktopSetup
|
||||
@@ -1846,29 +1889,40 @@ runcmd:
|
||||
%s
|
||||
`, hostname, password, authorizedKeys, setupScript)
|
||||
metaData := fmt.Sprintf("instance-id: %s\nlocal-hostname: %s\n", instanceID, hostname)
|
||||
ipv6Block := ""
|
||||
|
||||
// Build static address block (IPv4 + IPv6)
|
||||
ipv4s = normalizeKVMIPv4List(ipv4s)
|
||||
addressBlock := ""
|
||||
addressLines := make([]string, 0, len(ipv4s)+len(ipv6s))
|
||||
for _, ipv4 := range ipv4s {
|
||||
addressLines = append(addressLines, fmt.Sprintf(" - %s/32", ipv4))
|
||||
}
|
||||
for _, ipv6 := range ipv6s {
|
||||
addressLines = append(addressLines, fmt.Sprintf(" - %s/128", ipv6))
|
||||
}
|
||||
if len(addressLines) > 0 {
|
||||
addressBlock = fmt.Sprintf("\n addresses:\n%s", strings.Join(addressLines, "\n"))
|
||||
}
|
||||
|
||||
// IPv6 routes (only needed when IPv6 addresses are configured)
|
||||
ipv6RouteBlock := ""
|
||||
if len(ipv6s) > 0 {
|
||||
addressLines := make([]string, 0, len(ipv6s))
|
||||
for _, ipv6 := range ipv6s {
|
||||
addressLines = append(addressLines, fmt.Sprintf(" - %s/128", ipv6))
|
||||
}
|
||||
ipv6Block = fmt.Sprintf(`
|
||||
addresses:
|
||||
%s
|
||||
ipv6RouteBlock = fmt.Sprintf(`
|
||||
routes:
|
||||
- to: default
|
||||
via: %s
|
||||
on-link: true
|
||||
metric: 100`, strings.Join(addressLines, "\n"), ipv6GatewayLinkLocal)
|
||||
metric: 100`, ipv6GatewayLinkLocal)
|
||||
}
|
||||
|
||||
networkConfig := fmt.Sprintf(`version: 2
|
||||
ethernets:
|
||||
nic0:
|
||||
match:
|
||||
macaddress: "%s"
|
||||
dhcp4: true
|
||||
dhcp6: false%s
|
||||
`, strings.ToLower(mac), ipv6Block)
|
||||
dhcp6: false%s%s
|
||||
`, strings.ToLower(mac), addressBlock, ipv6RouteBlock)
|
||||
dir := filepath.Dir(seedPath)
|
||||
userPath := filepath.Join(dir, "user-data")
|
||||
metaPath := filepath.Join(dir, "meta-data")
|
||||
@@ -1900,6 +1954,16 @@ func configIPv6AssignmentAddresses(assignments []config.IPv6Assignment) []string
|
||||
return values
|
||||
}
|
||||
|
||||
func configIPv4AssignmentAddresses(assignments []config.PublicIPv4Assignment) []string {
|
||||
values := make([]string, 0, len(assignments))
|
||||
for _, item := range assignments {
|
||||
if strings.TrimSpace(item.Address) != "" {
|
||||
values = append(values, strings.TrimSpace(item.Address))
|
||||
}
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
func normalizeKVMIPv6List(values []string) []string {
|
||||
seen := map[string]bool{}
|
||||
result := make([]string, 0, len(values))
|
||||
|
||||
Reference in New Issue
Block a user