Skip to content

Commit a5aaf0e

Browse files
ukleon123wind5052
andauthored
Cms Implementation (#22)
* cms test complete * merge dev * subnet test ver1 * last_subnet algorithm complete * feat. adding last allocated subnet to database --------- Co-authored-by: wind5052 <[email protected]>
1 parent 0535fcf commit a5aaf0e

File tree

10 files changed

+253
-22
lines changed

10 files changed

+253
-22
lines changed

docker-compose.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ services:
22
redis:
33
image: redis:7-alpine
44
container_name: redis
5+
command: ["redis-server"]
6+
hostname: redis
57
ports:
68
- "6379:6379"
79
restart: unless-stopped
@@ -42,10 +44,16 @@ services:
4244
- GUAC_DB_PASSWORD=${GUAC_DB_PASSWORD}
4345
- GUAC_DB_HOST=${GUAC_DB_HOST}
4446
- GUAC_DB_NAME=${GUAC_DB_NAME}
47+
- REDIS_HOST=${REDIS_HOST}
48+
- CMS_HOST=${CMS_HOST}
4549
depends_on:
4650
- mysql
4751
- redis
4852

4953

5054
volumes:
5155
mysql_data:
56+
57+
58+
59+
# /usr/local/etc/redis/redis.conf

main.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func main() {
1616

1717
ctx := context.Background()
1818

19-
// Redis 초기화
19+
//Redis 초기화
2020
rdb, err := startup.InitializeRedis(ctx)
2121
if err != nil {
2222
log.Error("Failed to initialize Redis: %v", err, true)
@@ -30,8 +30,12 @@ func main() {
3030
log.Error("Failed to initialize: %v", err, true)
3131
panic(err)
3232
}
33-
3433
printCores(contextStruct.Cores)
34+
// cmsClient := service.NewCmsClient()
35+
// addrResp := cmsClient.NewCmsSubnet("20.20.22.")
36+
// fmt.Printf("%s\n", addrResp.IP)
37+
// fmt.Printf("%s\n", addrResp.MacAddr)
38+
// fmt.Printf("%s\n", addrResp.SdnUUID)
3539

3640
go func() {
3741
err := api.Server(contextStruct.Config.Port, &contextStruct, rdb)

request/model/vm.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ type CreateVMRequest struct {
2626
HardwareInfo HardwareInfo `json:"HWInfo"`
2727
NetConf NetDefine `json:"network"`
2828
Users []UserInfoVM `json:"users"`
29+
SdnUUID string `json:"sdnUUID"`
30+
MacAddr string `json:"macAddr"`
31+
Subnettype string `json:"Subnettype"`
2932
}
3033

3134
type DomainDeleteType uint

resources/config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ vm_internal_subnets:
22
- "127.0.0.1/24"
33

44
cores:
5-
- "192.168.0.10:12345"
5+
- "100.95.253.74:8080"
66

77
guacamole_base_url: "http://localhost/guacamole"
88
port: 8081

service/network.go

Lines changed: 179 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,179 @@
1-
package service
1+
package service
2+
3+
import (
4+
"bytes"
5+
"encoding/json"
6+
"fmt"
7+
"net/http"
8+
"os"
9+
"strconv"
10+
"strings"
11+
"time"
12+
13+
vms "github.com/easy-cloud-Knet/KWS_Control/structure"
14+
"github.com/easy-cloud-Knet/KWS_Control/util"
15+
)
16+
17+
type CmsClient struct {
18+
baseURL string
19+
client *http.Client
20+
}
21+
22+
type CmsResponse struct {
23+
IP string `json:"ip"`
24+
MacAddr string `json:"macAddr"`
25+
SdnUUID string `json:"sdnUUID"`
26+
}
27+
28+
type CmsRequest struct {
29+
Subnet string `json:"Subnet"`
30+
}
31+
32+
// fmt.Sprintf("%s/New/Instance", CMS_HOST)
33+
func NewCmsClient() *CmsClient {
34+
CMS_HOST := os.Getenv("CMS_HOST")
35+
return &CmsClient{
36+
baseURL: CMS_HOST,
37+
client: &http.Client{
38+
Timeout: 10 * time.Second,
39+
},
40+
}
41+
}
42+
43+
func (c *CmsClient) CmsRequest(Subnet string) (*CmsResponse, error) {
44+
log := util.GetLogger()
45+
46+
req_url := fmt.Sprintf("http://%s/New/Instance", c.baseURL)
47+
reqBody := CmsRequest{Subnet: Subnet}
48+
jsonBody, err := json.Marshal(reqBody)
49+
if err != nil {
50+
log.Error("CMS : failed to marshal JSON: %w", err)
51+
return nil, err
52+
}
53+
54+
req, err := http.NewRequest("POST", req_url, bytes.NewBuffer(jsonBody))
55+
if err != nil {
56+
log.Error("CMS : failed to NewRequest: %w", err)
57+
return nil, err
58+
}
59+
resp, err := c.client.Do(req)
60+
if err != nil {
61+
log.Error("CMS : failed to create request: %w", err)
62+
return nil, err
63+
}
64+
65+
defer resp.Body.Close()
66+
67+
if resp.StatusCode != http.StatusOK {
68+
log.Error("CMS : CMS returned status: %s", resp.Status)
69+
return nil, err
70+
}
71+
var addrResp CmsResponse
72+
if err := json.NewDecoder(resp.Body).Decode(&addrResp); err != nil {
73+
log.Error("CMS : failed to decode CMS response: %w", err)
74+
return nil, err
75+
}
76+
77+
return &addrResp, nil
78+
}
79+
80+
func (c *CmsClient) AddCmsSubnet(ctx *vms.ControlContext, uuid vms.UUID) (*CmsResponse, error) {
81+
log := util.GetLogger()
82+
83+
ip, err := GetVMIPByUUID(ctx, uuid)
84+
if err != nil {
85+
log.Error("AddCmsSubnet : GetVMIPByUUID: %w", err)
86+
return nil, err
87+
}
88+
subnet, err := GetSubnetFromIP(ip)
89+
if err != nil {
90+
log.Error("AddCmsSubnet : GetSubnetFromIP: %v", err)
91+
return nil, err
92+
}
93+
temp, err := c.CmsRequest(subnet)
94+
if err != nil {
95+
log.Error("AddCmsSubnet : c.CmsRequest(subnet): %v", err)
96+
return nil, err
97+
}
98+
99+
return temp, nil
100+
101+
}
102+
103+
func (c *CmsClient) NewCmsSubnet(ctx *vms.ControlContext) (*CmsResponse, error) {
104+
log := util.GetLogger()
105+
106+
last_subnet := ctx.Last_subnet
107+
next_last_subnet := Find_subnet(last_subnet)
108+
log.Info("NewCmsSubnet : next_last_subnet: %s", next_last_subnet)
109+
110+
temp, err := c.CmsRequest(next_last_subnet)
111+
if err != nil {
112+
log.Error("AddCmsSubnet : c.CmsRequest(subnet): %v", err)
113+
return nil, err
114+
}
115+
_, err = ctx.DB.Exec("UPDATE subnet SET last_subnet = ? WHERE id = 1", next_last_subnet)
116+
if err != nil {
117+
log.Error("Failed to update last_subnet in database: %v", err)
118+
return nil, err
119+
}
120+
ctx.Last_subnet = next_last_subnet
121+
return temp, nil
122+
}
123+
124+
func Find_subnet(last_subnet string) string {
125+
value := make([]int, 3)
126+
j := 0
127+
for i := 0; i < 3; i++ {
128+
var temp string
129+
for last_subnet[j] != '.' {
130+
temp = temp + string(last_subnet[j])
131+
j++
132+
}
133+
value[i], _ = strconv.Atoi(temp)
134+
j++
135+
}
136+
137+
if value[2] >= 255 {
138+
if value[1] >= 255 {
139+
if value[0] >= 255 {
140+
return "err"
141+
} else {
142+
value[0]++
143+
value[1] = 0
144+
value[2] = 0
145+
}
146+
} else {
147+
value[1]++
148+
value[2] = 0
149+
}
150+
} else {
151+
value[2]++
152+
}
153+
154+
result := fmt.Sprintf("%s.%s.%s.", strconv.Itoa(value[0]), strconv.Itoa(value[1]), strconv.Itoa(value[2]))
155+
return result
156+
}
157+
158+
func GetVMIPByUUID(ctx *vms.ControlContext, uuid vms.UUID) (string, error) {
159+
core, ok := ctx.VMLocation[uuid]
160+
if !ok {
161+
return "", fmt.Errorf("UUID %s not found in VMLocation", uuid)
162+
}
163+
164+
vmInfo, ok := core.VMInfoIdx[uuid]
165+
if !ok {
166+
return "", fmt.Errorf("VMInfo for UUID %s not found in Core", uuid)
167+
}
168+
169+
return vmInfo.IP_VM, nil
170+
}
171+
172+
func GetSubnetFromIP(ip string) (string, error) {
173+
parts := strings.Split(ip, ".")
174+
if len(parts) != 4 {
175+
return "", fmt.Errorf("invalid IP format: %s", ip)
176+
}
177+
178+
return strings.Join(parts[:3], ".") + ".", nil
179+
}

service/vm.go

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,13 @@ func CreateVM(w http.ResponseWriter, r *http.Request, contextStruct *vms.Control
102102
return err
103103
}
104104

105+
// add : back -> vm uuid -> cms 다른 api
106+
// new : subnet 찾기 -> cms
107+
105108
// 문제가 생겼을 때 지우는 무언가
106109
var guacamoleConfigured = false
107110
var coreResourcesAllocated = false
111+
var newSubnetAllocated = false
108112
var uuid = structure.UUID(req.UUID.String().(string))
109113

110114
cleanup := func() {
@@ -120,18 +124,35 @@ func CreateVM(w http.ResponseWriter, r *http.Request, contextStruct *vms.Control
120124
selectedCore.FreeCPU += req.HardwareInfo.CPU
121125
selectedCore.FreeDisk += req.HardwareInfo.Disk
122126
}
127+
if newSubnetAllocated {
128+
//subnet--
129+
}
123130
}
124131

125-
instanceIp, err := contextStruct.AssignInternalAddress()
132+
// instanceIp, err := contextStruct.AssignInternalAddress()
133+
// if err != nil {
134+
// log.Error("AssignInternalAddress() failed: %v", err, true)
135+
// return err
136+
// }
137+
var cmsResp *CmsResponse
138+
cmsClient := NewCmsClient()
139+
140+
if req.Subnettype == "Add" {
141+
cmsResp, err = cmsClient.AddCmsSubnet(contextStruct, uuid)
142+
} else {
143+
cmsResp, err = cmsClient.NewCmsSubnet(contextStruct)
144+
newSubnetAllocated = true
145+
}
126146
if err != nil {
127-
log.Error("AssignInternalAddress() failed: %v", err, true)
128-
return err
147+
log.Error("Failed to configure cms", true)
148+
return errors.New("failed to configure cms")
129149
}
130150

131-
fmt.Printf("AssignInternalAddress(): %s", instanceIp)
132-
fmt.Println(publicKeyOpenSSH) // TODO: 코어로 보내줘야함
151+
fmt.Printf("%s\n", cmsResp.IP)
152+
fmt.Printf("%s\n", cmsResp.MacAddr)
153+
fmt.Printf("%s\n", cmsResp.SdnUUID)
133154

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

136157
if userPass == "" {
137158
log.Error("Failed to configure Guacamole", true)
@@ -142,10 +163,11 @@ func CreateVM(w http.ResponseWriter, r *http.Request, contextStruct *vms.Control
142163
newVM := &structure.VMInfo{
143164
UUID: uuid,
144165
GuacPassword: userPass,
166+
MacAddr: cmsResp.MacAddr,
145167
Memory: req.HardwareInfo.Memory,
146168
Cpu: req.HardwareInfo.CPU,
147169
Disk: req.HardwareInfo.Disk,
148-
IP_VM: instanceIp,
170+
IP_VM: cmsResp.IP,
149171
}
150172

151173
// selected core 상태 업데이트
@@ -160,7 +182,9 @@ func CreateVM(w http.ResponseWriter, r *http.Request, contextStruct *vms.Control
160182

161183
log.DebugInfo("core %s updated: FreeMemory=%d, FreeCPU=%d, FreeDisk=%d", selectedCore.IP, selectedCore.FreeMemory, selectedCore.FreeCPU, selectedCore.FreeDisk)
162184

163-
req.NetConf.Ips = []string{instanceIp}
185+
req.NetConf.Ips = []string{cmsResp.IP}
186+
req.SdnUUID = cmsResp.SdnUUID
187+
req.MacAddr = cmsResp.MacAddr
164188
req.NetConf.NetType = 0
165189
req.Users[0].SSHAuthorizedKeys = []string{publicKeyOpenSSH}
166190

@@ -177,6 +201,13 @@ func CreateVM(w http.ResponseWriter, r *http.Request, contextStruct *vms.Control
177201
cleanup() // 직접 지우지 말고 요 함수 하나로--
178202
}
179203

204+
if newSubnetAllocated {
205+
_, err := contextStruct.DB.Exec("UPDATE subnet SET last_subnet = ? WHERE id = '1'", cmsResp.IP)
206+
if err != nil {
207+
log.Error("Error database Subnet insertion failed: %v", err, true)
208+
}
209+
}
210+
180211
// ControlContext global 상태 업데이트
181212
if contextStruct.VMLocation == nil {
182213
contextStruct.VMLocation = make(map[vms.UUID]*vms.Core)

startup/init.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,12 @@ func InitializeCoreData(configPath string) (structure.ControlContext, error) {
138138
infra.GuacDB = db
139139
infra.DB = mainDB
140140

141+
var last_subnet_db string
142+
err = infra.DB.QueryRow("SELECT last_subnet from core_base.subnet where id = '1'").Scan(&last_subnet_db)
143+
if err != nil {
144+
return structure.ControlContext{}, fmt.Errorf("failed to get last_subnet: %w", err)
145+
}
146+
infra.Last_subnet = last_subnet_db
141147
// 모든 Core 정의
142148
infra.VMLocation = make(map[structure.UUID]*structure.Core)
143149
for i := range infra.Cores {

startup/redis.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,22 @@ func InitializeRedis(ctx context.Context) (*redis.Client, error) {
1515

1616
REDIS_HOST := os.Getenv("REDIS_HOST")
1717
if REDIS_HOST == "" {
18-
REDIS_HOST = "100.101.247.128:6379"
18+
REDIS_HOST = "localhost:6379"
1919
}
2020

2121
// Redis 클라이언트 생성
2222
rdb := redis.NewClient(&redis.Options{
2323
Addr: REDIS_HOST,
2424
})
25-
2625
// 연결 테스트
2726
err := rdb.Set(ctx, "hello", "world", 0).Err()
2827
if err != nil {
29-
return nil, fmt.Errorf("failed to set test key in Redis: %w", err)
28+
return nil, fmt.Errorf("failed to set test key in Redis: %w %s ", err, REDIS_HOST)
3029
}
3130

3231
val, err := rdb.Get(ctx, "hello").Result()
3332
if err != nil {
34-
return nil, fmt.Errorf("failed to get test key from Redis: %w", err)
33+
return nil, fmt.Errorf("failed to set test key in Redis: %w %s ", err, REDIS_HOST)
3534
}
3635

3736
log.Info("Redis connection test successful: hello=%s", val, true)

0 commit comments

Comments
 (0)