metadata.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. package network
  2. import (
  3. "encoding/json"
  4. "os"
  5. "path/filepath"
  6. "sync"
  7. )
  8. var defaultMetadataPath = "/etc/proxmox-router/metadata.json"
  9. // MetadataManager manages user annotations for interfaces.
  10. type MetadataManager struct {
  11. mu sync.RWMutex
  12. filePath string
  13. store MetadataStore
  14. }
  15. func NewMetadataManager(customPath string) *MetadataManager {
  16. p := defaultMetadataPath
  17. if customPath != "" {
  18. p = customPath
  19. }
  20. mm := &MetadataManager{
  21. filePath: p,
  22. store: MetadataStore{
  23. Interfaces: make(map[string]InterfaceMetadata),
  24. },
  25. }
  26. mm.load()
  27. return mm
  28. }
  29. func (mm *MetadataManager) load() {
  30. mm.mu.Lock()
  31. defer mm.mu.Unlock()
  32. data, err := os.ReadFile(mm.filePath)
  33. if err != nil {
  34. return
  35. }
  36. _ = json.Unmarshal(data, &mm.store)
  37. if mm.store.Interfaces == nil {
  38. mm.store.Interfaces = make(map[string]InterfaceMetadata)
  39. }
  40. }
  41. func (mm *MetadataManager) save() error {
  42. dir := filepath.Dir(mm.filePath)
  43. if err := os.MkdirAll(dir, 0755); err != nil {
  44. return err
  45. }
  46. data, err := json.MarshalIndent(mm.store, "", " ")
  47. if err != nil {
  48. return err
  49. }
  50. return os.WriteFile(mm.filePath, data, 0644)
  51. }
  52. func (mm *MetadataManager) Get(name string) InterfaceMetadata {
  53. mm.mu.RLock()
  54. defer mm.mu.RUnlock()
  55. return mm.store.Interfaces[name]
  56. }
  57. func (mm *MetadataManager) Set(name string, role, desc string) error {
  58. mm.mu.Lock()
  59. defer mm.mu.Unlock()
  60. meta := mm.store.Interfaces[name]
  61. meta.Role = role
  62. meta.Description = desc
  63. mm.store.Interfaces[name] = meta
  64. return mm.save()
  65. }
  66. func (mm *MetadataManager) AddIP(name, cidr string) error {
  67. mm.mu.Lock()
  68. defer mm.mu.Unlock()
  69. meta := mm.store.Interfaces[name]
  70. for _, ip := range meta.IPAddresses {
  71. if ip == cidr {
  72. return nil
  73. }
  74. }
  75. meta.IPAddresses = append(meta.IPAddresses, cidr)
  76. meta.AutoUp = true
  77. mm.store.Interfaces[name] = meta
  78. return mm.save()
  79. }
  80. func (mm *MetadataManager) RemoveIP(name, cidr string) error {
  81. mm.mu.Lock()
  82. defer mm.mu.Unlock()
  83. meta := mm.store.Interfaces[name]
  84. var updated []string
  85. for _, ip := range meta.IPAddresses {
  86. if ip != cidr {
  87. updated = append(updated, ip)
  88. }
  89. }
  90. meta.IPAddresses = updated
  91. mm.store.Interfaces[name] = meta
  92. return mm.save()
  93. }
  94. func (mm *MetadataManager) GetAllWithIPs() map[string][]string {
  95. mm.mu.RLock()
  96. defer mm.mu.RUnlock()
  97. res := make(map[string][]string)
  98. for name, meta := range mm.store.Interfaces {
  99. if len(meta.IPAddresses) > 0 {
  100. res[name] = append([]string(nil), meta.IPAddresses...)
  101. }
  102. }
  103. return res
  104. }
  105. func (mm *MetadataManager) Delete(name string) error {
  106. mm.mu.Lock()
  107. defer mm.mu.Unlock()
  108. delete(mm.store.Interfaces, name)
  109. return mm.save()
  110. }
  111. // Rename migrates interface metadata when an interface is renamed.
  112. func (mm *MetadataManager) Rename(oldName, newName string) error {
  113. mm.mu.Lock()
  114. defer mm.mu.Unlock()
  115. if meta, exists := mm.store.Interfaces[oldName]; exists {
  116. delete(mm.store.Interfaces, oldName)
  117. mm.store.Interfaces[newName] = meta
  118. return mm.save()
  119. }
  120. return nil
  121. }