Skip to content

Commit 0535fcf

Browse files
authored
Merge pull request #21 from ukleon123/Dev
Dev
2 parents ffcda4f + 1cedda9 commit 0535fcf

4 files changed

Lines changed: 322 additions & 123 deletions

File tree

service/vm.go

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010

1111
"github.com/easy-cloud-Knet/KWS_Control/request"
1212
"github.com/easy-cloud-Knet/KWS_Control/request/model"
13+
"github.com/easy-cloud-Knet/KWS_Control/structure"
1314
"github.com/easy-cloud-Knet/KWS_Control/util"
1415

1516
vms "github.com/easy-cloud-Knet/KWS_Control/structure"
@@ -104,16 +105,17 @@ func CreateVM(w http.ResponseWriter, r *http.Request, contextStruct *vms.Control
104105
// 문제가 생겼을 때 지우는 무언가
105106
var guacamoleConfigured = false
106107
var coreResourcesAllocated = false
108+
var uuid = structure.UUID(req.UUID.String().(string))
107109

108110
cleanup := func() {
109111
if guacamoleConfigured {
110112
log.Info("clean up clean up")
111-
if cleanupErr := CleanupGuacamoleConfig(string(req.UUID), contextStruct.GuacDB); cleanupErr != nil {
113+
if cleanupErr := CleanupGuacamoleConfig(string(uuid), contextStruct.GuacDB); cleanupErr != nil {
112114
log.Error("Failed to cleanup Guacamole config during rollback: %v", cleanupErr)
113115
}
114116
}
115117
if coreResourcesAllocated {
116-
delete(selectedCore.VMInfoIdx, req.UUID)
118+
delete(selectedCore.VMInfoIdx, uuid)
117119
selectedCore.FreeMemory += req.HardwareInfo.Memory
118120
selectedCore.FreeCPU += req.HardwareInfo.CPU
119121
selectedCore.FreeDisk += req.HardwareInfo.Disk
@@ -129,16 +131,16 @@ func CreateVM(w http.ResponseWriter, r *http.Request, contextStruct *vms.Control
129131
fmt.Printf("AssignInternalAddress(): %s", instanceIp)
130132
fmt.Println(publicKeyOpenSSH) // TODO: 코어로 보내줘야함
131133

132-
userPass := GuacamoleConfig(req.Users[0].Name, string(req.UUID), instanceIp, privateKeyPEM, contextStruct.GuacDB)
134+
userPass := GuacamoleConfig(req.Users[0].Name, string(uuid), instanceIp, privateKeyPEM, contextStruct.GuacDB)
133135

134136
if userPass == "" {
135137
log.Error("Failed to configure Guacamole", true)
136138
return errors.New("failed to configure Guacamole")
137139
}
138140
guacamoleConfigured = true
139141

140-
newVM := &vms.VMInfo{
141-
UUID: req.UUID,
142+
newVM := &structure.VMInfo{
143+
UUID: uuid,
142144
GuacPassword: userPass,
143145
Memory: req.HardwareInfo.Memory,
144146
Cpu: req.HardwareInfo.CPU,
@@ -150,7 +152,7 @@ func CreateVM(w http.ResponseWriter, r *http.Request, contextStruct *vms.Control
150152
if selectedCore.VMInfoIdx == nil {
151153
selectedCore.VMInfoIdx = make(map[vms.UUID]*vms.VMInfo)
152154
}
153-
selectedCore.VMInfoIdx[req.UUID] = newVM
155+
selectedCore.VMInfoIdx[uuid] = newVM
154156
selectedCore.FreeMemory -= req.HardwareInfo.Memory
155157
selectedCore.FreeCPU -= req.HardwareInfo.CPU
156158
selectedCore.FreeDisk -= req.HardwareInfo.Disk
@@ -169,22 +171,29 @@ func CreateVM(w http.ResponseWriter, r *http.Request, contextStruct *vms.Control
169171
cleanup() // 직접 지우지 말고 요 함수 하나로--
170172
return err
171173
}
174+
err = contextStruct.AddInstance(newVM, selectedCoreIndex)
175+
if err != nil {
176+
log.Error("Error database instance insertion failed: %v", err, true)
177+
cleanup() // 직접 지우지 말고 요 함수 하나로--
178+
}
172179

173180
// ControlContext global 상태 업데이트
174181
if contextStruct.VMLocation == nil {
175182
contextStruct.VMLocation = make(map[vms.UUID]*vms.Core)
176183
}
177-
contextStruct.VMLocation[req.UUID] = &contextStruct.Cores[selectedCoreIndex]
184+
contextStruct.VMLocation[uuid] = &contextStruct.Cores[selectedCoreIndex]
178185
contextStruct.AliveVM = append(contextStruct.AliveVM, newVM)
179-
log.Info("VM %s added to ControlContext", req.UUID, true)
186+
log.Info("VM %s added to ControlContext", uuid, true)
180187

181-
log.Info("UUID %s CreateVM request success on core %s", req.UUID, selectedCore.IP, true)
188+
log.Info("UUID %s CreateVM request success on core %s", uuid, selectedCore.IP, true)
182189
return nil
183190
}
184191

185192
func DeleteVM(uuid vms.UUID, contextStruct *vms.ControlContext) error {
193+
log := util.GetLogger()
186194
core := contextStruct.FindCoreByVmUUID(uuid)
187195
if core == nil {
196+
log.Error("VM with UUID %s not found", string(uuid))
188197
return fmt.Errorf("VM with UUID %s not found", string(uuid))
189198
}
190199

@@ -193,8 +202,18 @@ func DeleteVM(uuid vms.UUID, contextStruct *vms.ControlContext) error {
193202
UUID: uuid,
194203
Type: model.HardDelete,
195204
})
205+
if err != nil {
206+
log.Error("error deleting VM %s on core %s: %w", uuid, core.IP, err)
207+
return err
208+
}
209+
210+
err = contextStruct.DeleteInstance(uuid)
211+
if err != nil {
212+
log.Error("error deleting instance %s from ControlContext: %v", uuid, err)
213+
return err
214+
}
196215

197-
return err
216+
return nil
198217
}
199218

200219
func ShutdownVM(uuid vms.UUID, contextStruct *vms.ControlContext) error {

startup/init.go

Lines changed: 116 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -23,112 +23,11 @@ func InitializeCoreData(configPath string) (structure.ControlContext, error) {
2323

2424
var infra structure.ControlContext
2525

26-
// 모든 Core 정의
27-
infra.VMLocation = make(map[structure.UUID]*structure.Core)
28-
for i := range infra.Cores {
29-
for vmUUID := range infra.Cores[i].VMInfoIdx {
30-
infra.VMLocation[vmUUID] = &infra.Cores[i]
31-
}
32-
infra.Cores[i].IsAlive = false
33-
}
34-
35-
// config에 설정된 코어에 대해서 정보 업데이트
3626
config, err := readConfig(configPath)
3727
if err != nil {
3828
return structure.ControlContext{}, fmt.Errorf("failed to read config file %s: %w", configPath, err)
3929
}
4030

41-
// 환경변수에서 먼저 설정을 불러오고 값이 없을 때만 config 파일에서 가져옴
42-
var coreAddresses []string
43-
coresEnv := os.Getenv("CORES")
44-
if coresEnv != "" {
45-
coreAddresses = strings.Split(coresEnv, ",")
46-
} else {
47-
coreAddresses = config.Cores
48-
}
49-
50-
g, ctx := errgroup.WithContext(context.Background())
51-
for _, coreAddress := range coreAddresses {
52-
parts := strings.Split(coreAddress, ":")
53-
if len(parts) != 2 {
54-
return structure.ControlContext{}, fmt.Errorf("invalid core address format in '%s': expected ip:port", coreAddress)
55-
}
56-
ip := parts[0]
57-
port, err := strconv.Atoi(parts[1])
58-
if err != nil {
59-
return structure.ControlContext{}, fmt.Errorf("error converting port number from %s: %w", coreAddress, err)
60-
}
61-
62-
core := findCore(infra.Cores, ip, uint16(port))
63-
if core == nil {
64-
newCore := structure.Core{
65-
IP: ip,
66-
Port: uint16(port),
67-
IsAlive: true,
68-
}
69-
infra.Cores = append(infra.Cores, newCore)
70-
core = &infra.Cores[len(infra.Cores)-1]
71-
} else {
72-
core.IsAlive = true
73-
}
74-
75-
currentCore := core
76-
g.Go(func() error {
77-
client := request.NewCoreClient(currentCore)
78-
79-
memResp, err := client.GetCoreMachineMemoryInfo(ctx)
80-
if err != nil {
81-
currentCore.IsAlive = false
82-
return fmt.Errorf("failed to get Memory info for core %s:%d: %w", currentCore.IP, currentCore.Port, err)
83-
}
84-
diskResp, err := client.GetCoreMachineDiskInfo(ctx)
85-
if err != nil {
86-
currentCore.IsAlive = false
87-
return fmt.Errorf("failed to get Disk info for core %s:%d: %w", currentCore.IP, currentCore.Port, err)
88-
}
89-
90-
totalMemoryMiB := uint32(memResp.Total * 1024)
91-
totalDiskMiB := uint32(diskResp.Total * 1024)
92-
freeMemoryMiB := uint32(memResp.Available * 1024)
93-
freeDiskMiB := uint32(diskResp.Free * 1024)
94-
95-
var totalCpuCores uint32
96-
if currentCore.CoreInfoIdx.Cpu > 0 {
97-
totalCpuCores = currentCore.CoreInfoIdx.Cpu
98-
} else {
99-
log.DebugInfo("currentCore.CoreInfoIdx.Cpu: %d", currentCore.CoreInfoIdx.Cpu)
100-
totalCpuCores = 9999 // 음 코어를 현재 반환받지 못하는-
101-
}
102-
103-
allocatedCpuCores := uint32(0)
104-
if currentCore.VMInfoIdx != nil {
105-
for _, vm := range currentCore.VMInfoIdx {
106-
allocatedCpuCores += vm.Cpu
107-
}
108-
}
109-
freeCpuCores := totalCpuCores - allocatedCpuCores
110-
111-
currentCore.CoreInfoIdx.Cpu = totalCpuCores
112-
currentCore.CoreInfoIdx.Memory = totalMemoryMiB
113-
currentCore.CoreInfoIdx.Disk = totalDiskMiB
114-
115-
currentCore.FreeDisk = freeDiskMiB
116-
currentCore.FreeMemory = freeMemoryMiB
117-
currentCore.FreeCPU = freeCpuCores
118-
119-
return nil
120-
})
121-
}
122-
123-
if err := g.Wait(); err != nil {
124-
return structure.ControlContext{}, fmt.Errorf("failed to get core info: %w", err)
125-
}
126-
127-
guacBaseUrlEnv := os.Getenv("GUACAMOLE_BASE_URL")
128-
if guacBaseUrlEnv != "" {
129-
config.GuacBaseURL = guacBaseUrlEnv
130-
}
131-
13231
// ---------------- Main DB connection -----------------------
13332
dbUserMain := os.Getenv("DB_USER")
13433
if dbUserMain == "" {
@@ -170,11 +69,11 @@ func InitializeCoreData(configPath string) (structure.ControlContext, error) {
17069

17170
dsnMain := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s", dbUserMain, dbPasswordMain, dbHostMain, dbPortMain, dbNameMain)
17271

173-
log.DebugInfo("database connection info: %s:%s@tcp(%s:%s)/%s", dbUserMain, dbPasswordMain, dbHostMain, dbPortMain, dbNameMain)
72+
log.Info("database connection info: %s:%s@tcp(%s:%s)/%s", dbUserMain, dbPasswordMain, dbHostMain, dbPortMain, dbNameMain)
17473
mainDB, err := sql.Open("mysql", dsnMain)
17574

176-
log.DebugInfo("generic database connection opened")
177-
log.DebugInfo("generic database stats: %v", mainDB.Stats())
75+
log.Info("generic database connection opened", true)
76+
log.Info("generic database stats: %v", mainDB.Stats(), true)
17877

17978
if err != nil {
18079
log.DebugError("failed to open generic database connection: %v", err)
@@ -238,6 +137,119 @@ func InitializeCoreData(configPath string) (structure.ControlContext, error) {
238137
infra.Config = config
239138
infra.GuacDB = db
240139
infra.DB = mainDB
140+
141+
// 모든 Core 정의
142+
infra.VMLocation = make(map[structure.UUID]*structure.Core)
143+
for i := range infra.Cores {
144+
for vmUUID := range infra.Cores[i].VMInfoIdx {
145+
infra.VMLocation[vmUUID] = &infra.Cores[i]
146+
}
147+
infra.Cores[i].IsAlive = false
148+
}
149+
150+
// config에 설정된 코어에 대해서 정보 업데이트
151+
152+
// 환경변수에서 먼저 설정을 불러오고 값이 없을 때만 config 파일에서 가져옴
153+
var coreAddresses []string
154+
coresEnv := os.Getenv("CORES")
155+
if coresEnv != "" {
156+
coreAddresses = strings.Split(coresEnv, ",")
157+
} else {
158+
coreAddresses = config.Cores
159+
}
160+
161+
g, ctx := errgroup.WithContext(context.Background())
162+
for _, coreAddress := range coreAddresses {
163+
parts := strings.Split(coreAddress, ":")
164+
if len(parts) != 2 {
165+
return structure.ControlContext{}, fmt.Errorf("invalid core address format in '%s': expected ip:port", coreAddress)
166+
}
167+
ip := parts[0]
168+
port, err := strconv.Atoi(parts[1])
169+
if err != nil {
170+
return structure.ControlContext{}, fmt.Errorf("error converting port number from %s: %w", coreAddress, err)
171+
}
172+
173+
core := findCore(infra.Cores, ip, uint16(port))
174+
if core == nil {
175+
newCore := structure.Core{
176+
IP: ip,
177+
Port: uint16(port),
178+
IsAlive: true,
179+
}
180+
infra.Cores = append(infra.Cores, newCore)
181+
core = &infra.Cores[len(infra.Cores)-1]
182+
log.DebugInfo("Added new core: %s:%d", ip, port)
183+
} else {
184+
core.IsAlive = true
185+
}
186+
187+
currentCore := core
188+
g.Go(func() error {
189+
client := request.NewCoreClient(currentCore)
190+
191+
memResp, err := client.GetCoreMachineMemoryInfo(ctx)
192+
if err != nil {
193+
currentCore.IsAlive = false
194+
return fmt.Errorf("failed to get Memory info for core %s:%d: %w", currentCore.IP, currentCore.Port, err)
195+
}
196+
diskResp, err := client.GetCoreMachineDiskInfo(ctx)
197+
if err != nil {
198+
currentCore.IsAlive = false
199+
return fmt.Errorf("failed to get Disk info for core %s:%d: %w", currentCore.IP, currentCore.Port, err)
200+
}
201+
202+
totalMemoryMiB := uint32(memResp.Total * 1024)
203+
totalDiskMiB := uint32(diskResp.Total * 1024)
204+
freeMemoryMiB := uint32(memResp.Available * 1024)
205+
freeDiskMiB := uint32(diskResp.Free * 1024)
206+
207+
var totalCpuCores uint32
208+
if currentCore.CoreInfoIdx.Cpu > 0 {
209+
totalCpuCores = currentCore.CoreInfoIdx.Cpu
210+
} else {
211+
log.DebugInfo("currentCore.CoreInfoIdx.Cpu: %d", currentCore.CoreInfoIdx.Cpu)
212+
totalCpuCores = 9999 // 음 코어를 현재 반환받지 못하는-
213+
}
214+
215+
currentCore.CoreInfoIdx.Cpu = totalCpuCores
216+
currentCore.CoreInfoIdx.Memory = totalMemoryMiB
217+
currentCore.CoreInfoIdx.Disk = totalDiskMiB
218+
219+
currentCore.FreeDisk = freeDiskMiB
220+
currentCore.FreeMemory = freeMemoryMiB
221+
currentCore.FreeCPU = totalCpuCores
222+
223+
return nil
224+
})
225+
}
226+
227+
if err := g.Wait(); err != nil {
228+
return structure.ControlContext{}, fmt.Errorf("failed to get core info: %w", err)
229+
}
230+
231+
vmInfoList, coreIdxList, err := infra.GetAllInstanceInfo()
232+
if err != nil {
233+
return structure.ControlContext{}, fmt.Errorf("failed to get all instance info: %w", err)
234+
}
235+
236+
for i, vmInfo := range vmInfoList {
237+
coreIdx := coreIdxList[i]
238+
if coreIdx < 0 || coreIdx >= len(infra.Cores) {
239+
return structure.ControlContext{}, fmt.Errorf("core index %d out of range for core list", coreIdx)
240+
}
241+
core := &infra.Cores[coreIdx]
242+
if core.VMInfoIdx == nil {
243+
core.VMInfoIdx = make(map[structure.UUID]*structure.VMInfo)
244+
}
245+
if _, exists := core.VMInfoIdx[vmInfo.UUID]; !exists {
246+
core.VMInfoIdx[vmInfo.UUID] = &vmInfo
247+
infra.VMLocation[vmInfo.UUID] = core
248+
} else {
249+
log.DebugInfo("VM %s already exists in core %d, skipping", vmInfo.UUID, coreIdx)
250+
}
251+
}
252+
241253
return infra, nil
242254
}
243255

0 commit comments

Comments
 (0)