mirror of
https://github.com/MengMengCode/CLICD.git
synced 2026-08-06 05:52:19 +08:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a2da61e076 | |||
| 49a6981e28 |
@@ -113,7 +113,7 @@ func printMenu() {
|
|||||||
fmt.Println(" 7. Reinstall container")
|
fmt.Println(" 7. Reinstall container")
|
||||||
fmt.Println(" 8. Reset web admin password")
|
fmt.Println(" 8. Reset web admin password")
|
||||||
fmt.Printf(" 9. %s web panel\n", webStatus)
|
fmt.Printf(" 9. %s web panel\n", webStatus)
|
||||||
fmt.Println(" 10. Import existing ct-* containers")
|
fmt.Println(" 10. Import existing LXC containers")
|
||||||
fmt.Println(" 11. Uninstall CLICD")
|
fmt.Println(" 11. Uninstall CLICD")
|
||||||
fmt.Println(" 0. System info")
|
fmt.Println(" 0. System info")
|
||||||
fmt.Println(" q. Quit")
|
fmt.Println(" q. Quit")
|
||||||
@@ -330,9 +330,9 @@ func isWebPanelRunning() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func cliImportExistingContainers() {
|
func cliImportExistingContainers() {
|
||||||
fmt.Println("\n--- Import existing CLICD containers ---")
|
fmt.Println("\n--- Import existing LXC containers ---")
|
||||||
fmt.Println("This imports LXC containers named ct-{id} from /var/lib/lxc into CLICD config.")
|
fmt.Println("This imports containers from /var/lib/lxc into CLICD config.")
|
||||||
fmt.Println("Containers with names like ubuntu or alpine are skipped because CLICD requires ct-{id}.")
|
fmt.Println("Imported containers keep their real LXC name so Web and CLI manage the same container.")
|
||||||
|
|
||||||
imported, err := manager.ImportExistingClicdContainers()
|
imported, err := manager.ImportExistingClicdContainers()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ type Container struct {
|
|||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
UUID string `json:"uuid"`
|
UUID string `json:"uuid"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
LXCName string `json:"lxc_name,omitempty"`
|
||||||
Template string `json:"template"`
|
Template string `json:"template"`
|
||||||
VCPU float64 `json:"vcpu"`
|
VCPU float64 `json:"vcpu"`
|
||||||
RAMMB int `json:"ram_mb"`
|
RAMMB int `json:"ram_mb"`
|
||||||
@@ -97,6 +98,9 @@ type Container struct {
|
|||||||
|
|
||||||
// LxcName returns the internal LXC container name (ct-{id})
|
// LxcName returns the internal LXC container name (ct-{id})
|
||||||
func (c *Container) LxcName() string {
|
func (c *Container) LxcName() string {
|
||||||
|
if c.LXCName != "" {
|
||||||
|
return c.LXCName
|
||||||
|
}
|
||||||
return fmt.Sprintf("ct-%d", c.ID)
|
return fmt.Sprintf("ct-%d", c.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+23
-11
@@ -1915,9 +1915,9 @@ func (m *Manager) ListContainers() ([]config.Container, error) {
|
|||||||
return containers, nil
|
return containers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImportExistingClicdContainers imports LXC containers named ct-{id} into the
|
// ImportExistingClicdContainers imports existing LXC containers into the CLICD
|
||||||
// CLICD config. Containers with arbitrary LXC names cannot be imported because
|
// config. Native CLICD containers keep ct-{id}; arbitrary LXC names are stored
|
||||||
// CLICD derives the runtime LXC name from the numeric container ID.
|
// in Container.LXCName so Web and CLI can manage the same imported container.
|
||||||
func (m *Manager) ImportExistingClicdContainers() ([]config.Container, error) {
|
func (m *Manager) ImportExistingClicdContainers() ([]config.Container, error) {
|
||||||
entries, err := os.ReadDir(m.LxcPath)
|
entries, err := os.ReadDir(m.LxcPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1926,10 +1926,12 @@ func (m *Manager) ImportExistingClicdContainers() ([]config.Container, error) {
|
|||||||
|
|
||||||
existingIDs := make(map[int]bool)
|
existingIDs := make(map[int]bool)
|
||||||
existingNames := make(map[string]bool)
|
existingNames := make(map[string]bool)
|
||||||
|
existingLXCNames := make(map[string]bool)
|
||||||
maxID := config.AppConfig.NextContainerID - 1
|
maxID := config.AppConfig.NextContainerID - 1
|
||||||
for _, c := range config.AppConfig.Containers {
|
for _, c := range config.AppConfig.Containers {
|
||||||
existingIDs[c.ID] = true
|
existingIDs[c.ID] = true
|
||||||
existingNames[c.Name] = true
|
existingNames[c.Name] = true
|
||||||
|
existingLXCNames[c.LxcName()] = true
|
||||||
if c.ID > maxID {
|
if c.ID > maxID {
|
||||||
maxID = c.ID
|
maxID = c.ID
|
||||||
}
|
}
|
||||||
@@ -1941,22 +1943,30 @@ func (m *Manager) ImportExistingClicdContainers() ([]config.Container, error) {
|
|||||||
if !entry.IsDir() {
|
if !entry.IsDir() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
matches := re.FindStringSubmatch(entry.Name())
|
lxcName := entry.Name()
|
||||||
if len(matches) != 2 {
|
if existingLXCNames[lxcName] {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := strconv.Atoi(matches[1])
|
id := 0
|
||||||
if err != nil || id <= 0 || existingIDs[id] {
|
if matches := re.FindStringSubmatch(lxcName); len(matches) == 2 {
|
||||||
continue
|
if parsed, err := strconv.Atoi(matches[1]); err == nil && parsed > 0 && !existingIDs[parsed] {
|
||||||
|
id = parsed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if id == 0 {
|
||||||
|
id = maxID + 1
|
||||||
|
for existingIDs[id] {
|
||||||
|
id++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
name := entry.Name()
|
name := lxcName
|
||||||
if existingNames[name] {
|
if existingNames[name] {
|
||||||
name = fmt.Sprintf("imported-%d", id)
|
name = fmt.Sprintf("imported-%d", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
status, err := m.GetContainerStatus(entry.Name())
|
status, err := m.GetContainerStatus(lxcName)
|
||||||
if err != nil || status == "" {
|
if err != nil || status == "" {
|
||||||
status = "unknown"
|
status = "unknown"
|
||||||
}
|
}
|
||||||
@@ -1965,6 +1975,7 @@ func (m *Manager) ImportExistingClicdContainers() ([]config.Container, error) {
|
|||||||
ID: id,
|
ID: id,
|
||||||
UUID: config.NewContainerUUID(),
|
UUID: config.NewContainerUUID(),
|
||||||
Name: name,
|
Name: name,
|
||||||
|
LXCName: lxcName,
|
||||||
Template: "imported",
|
Template: "imported",
|
||||||
VCPU: 1,
|
VCPU: 1,
|
||||||
RAMMB: 512,
|
RAMMB: 512,
|
||||||
@@ -1978,7 +1989,7 @@ func (m *Manager) ImportExistingClicdContainers() ([]config.Container, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if status == "running" {
|
if status == "running" {
|
||||||
if ip, err := m.GetContainerIP(entry.Name()); err == nil {
|
if ip, err := m.GetContainerIP(lxcName); err == nil {
|
||||||
c.IP = ip
|
c.IP = ip
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1987,6 +1998,7 @@ func (m *Manager) ImportExistingClicdContainers() ([]config.Container, error) {
|
|||||||
imported = append(imported, c)
|
imported = append(imported, c)
|
||||||
existingIDs[id] = true
|
existingIDs[id] = true
|
||||||
existingNames[name] = true
|
existingNames[name] = true
|
||||||
|
existingLXCNames[lxcName] = true
|
||||||
if id > maxID {
|
if id > maxID {
|
||||||
maxID = id
|
maxID = id
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-1
@@ -416,7 +416,17 @@ download_release_if_needed() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
install_binary() {
|
install_binary() {
|
||||||
cp ./clicd /usr/local/bin/clicd
|
if has_cmd systemctl; then
|
||||||
|
systemctl stop clicd >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
if has_cmd rc-service; then
|
||||||
|
rc-service clicd stop >/dev/null 2>&1 || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
tmp_bin="/usr/local/bin/clicd.new.$$"
|
||||||
|
cp ./clicd "$tmp_bin"
|
||||||
|
chmod +x "$tmp_bin"
|
||||||
|
mv -f "$tmp_bin" /usr/local/bin/clicd
|
||||||
chmod +x /usr/local/bin/clicd
|
chmod +x /usr/local/bin/clicd
|
||||||
log "Installed binary: /usr/local/bin/clicd"
|
log "Installed binary: /usr/local/bin/clicd"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user