99
1010 "github.com/onkernel/hypeman/lib/hypervisor"
1111 "github.com/onkernel/hypeman/lib/logger"
12- "github.com/onkernel/hypeman/lib/vmm"
1312)
1413
1514// instanceMetadata is the minimal metadata we need to derive allocations
@@ -18,6 +17,8 @@ type instanceMetadata struct {
1817 Name string
1918 NetworkEnabled bool
2019 HypervisorType string
20+ IP string // Assigned IP address
21+ MAC string // Assigned MAC address
2122}
2223
2324// deriveAllocation derives network allocation from CH or snapshot
@@ -49,58 +50,38 @@ func (m *manager) deriveAllocation(ctx context.Context, instanceID string) (*All
4950 }
5051 netmask := fmt .Sprintf ("%d.%d.%d.%d" , ipNet .Mask [0 ], ipNet .Mask [1 ], ipNet .Mask [2 ], ipNet .Mask [3 ])
5152
52- // 4. Try to derive from running VM first
53- socketPath := m .paths .InstanceSocket (instanceID , hypervisor .SocketNameForType (hypervisor .Type (meta .HypervisorType )))
54- if fileExists (socketPath ) {
55- client , err := vmm .NewVMM (socketPath )
56- if err == nil {
57- resp , err := client .GetVmInfoWithResponse (ctx )
58- if err == nil && resp .JSON200 != nil && resp .JSON200 .Config .Net != nil && len (* resp .JSON200 .Config .Net ) > 0 {
59- nets := * resp .JSON200 .Config .Net
60- net := nets [0 ]
61- if net .Ip != nil && net .Mac != nil && net .Tap != nil {
62- log .DebugContext (ctx , "derived allocation from running VM" , "instance_id" , instanceID )
63- return & Allocation {
64- InstanceID : instanceID ,
65- InstanceName : meta .Name ,
66- Network : "default" ,
67- IP : * net .Ip ,
68- MAC : * net .Mac ,
69- TAPDevice : * net .Tap ,
70- Gateway : defaultNet .Gateway ,
71- Netmask : netmask ,
72- State : "running" ,
73- }, nil
74- }
53+ // 4. Use stored metadata to derive allocation (works for all hypervisors)
54+ if meta .IP != "" && meta .MAC != "" {
55+ tap := generateTAPName (instanceID )
56+
57+ // Determine state based on socket existence and snapshot
58+ socketPath := m .paths .InstanceSocket (instanceID , hypervisor .SocketNameForType (hypervisor .Type (meta .HypervisorType )))
59+ state := "stopped"
60+ if fileExists (socketPath ) {
61+ state = "running"
62+ } else {
63+ // Check for snapshot (standby state)
64+ snapshotConfigJson := m .paths .InstanceSnapshotConfig (instanceID )
65+ if fileExists (snapshotConfigJson ) {
66+ state = "standby"
7567 }
7668 }
77- }
7869
79- // 5. Try to derive from snapshot
80- // Cloud Hypervisor creates config.json in the snapshot directory
81- snapshotConfigJson := m .paths .InstanceSnapshotConfig (instanceID )
82- if fileExists (snapshotConfigJson ) {
83- vmConfig , err := m .parseVmJson (snapshotConfigJson )
84- if err == nil && vmConfig .Net != nil && len (* vmConfig .Net ) > 0 {
85- nets := * vmConfig .Net
86- if nets [0 ].Ip != nil && nets [0 ].Mac != nil && nets [0 ].Tap != nil {
87- log .DebugContext (ctx , "derived allocation from snapshot" , "instance_id" , instanceID )
88- return & Allocation {
89- InstanceID : instanceID ,
90- InstanceName : meta .Name ,
91- Network : "default" ,
92- IP : * nets [0 ].Ip ,
93- MAC : * nets [0 ].Mac ,
94- TAPDevice : * nets [0 ].Tap ,
95- Gateway : defaultNet .Gateway ,
96- Netmask : netmask ,
97- State : "standby" ,
98- }, nil
99- }
100- }
70+ log .DebugContext (ctx , "derived allocation from metadata" , "instance_id" , instanceID , "state" , state )
71+ return & Allocation {
72+ InstanceID : instanceID ,
73+ InstanceName : meta .Name ,
74+ Network : "default" ,
75+ IP : meta .IP ,
76+ MAC : meta .MAC ,
77+ TAPDevice : tap ,
78+ Gateway : defaultNet .Gateway ,
79+ Netmask : netmask ,
80+ State : state ,
81+ }, nil
10182 }
10283
103- // 6 . No allocation (stopped or network not yet configured)
84+ // 5 . No allocation (network not yet configured)
10485 return nil , nil
10586}
10687
@@ -164,22 +145,6 @@ func (m *manager) loadInstanceMetadata(instanceID string) (*instanceMetadata, er
164145 return & meta , nil
165146}
166147
167- // parseVmJson parses Cloud Hypervisor's config.json from snapshot
168- // Note: Despite the function name, this parses config.json (what CH actually creates)
169- func (m * manager ) parseVmJson (path string ) (* vmm.VmConfig , error ) {
170- data , err := os .ReadFile (path )
171- if err != nil {
172- return nil , fmt .Errorf ("read config.json: %w" , err )
173- }
174-
175- var vmConfig vmm.VmConfig
176- if err := json .Unmarshal (data , & vmConfig ); err != nil {
177- return nil , fmt .Errorf ("unmarshal config.json: %w" , err )
178- }
179-
180- return & vmConfig , nil
181- }
182-
183148// fileExists checks if a file exists
184149func fileExists (path string ) bool {
185150 _ , err := os .Stat (path )
0 commit comments