Skip to content
Open

hh #62

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
77909ca
Merge pull request #51 from easy-cloud-Knet/autoconfig
Jbchan01 Jul 29, 2025
1213caf
boot instance method added
kwonkwonn Aug 19, 2025
cb875ad
Merge pull request #53 from easy-cloud-Knet/boot
kwonkwonn Aug 19, 2025
cbfeb62
handler added
kwonkwonn Aug 19, 2025
4686c8f
Merge pull request #54 from easy-cloud-Knet/autoconfig
Jbchan01 Aug 27, 2025
abb2a69
disk size specification added
kwonkwonn Oct 1, 2025
5126e77
erge branch 'main' of https://github.com/easy-cloud-Knet/KWS_Core
kwonkwonn Oct 1, 2025
67c5ae8
feat/fetching os information per booting option added
kwonkwonn Oct 31, 2025
35b434a
mit licnese added for viability
kwonkwonn Nov 14, 2025
0d378e1
mit licnese added for viability
kwonkwonn Nov 14, 2025
52d2afa
test function added
kwonkwonn Nov 19, 2025
443987b
looking for best structure
kwonkwonn Nov 19, 2025
4da999b
base operation for adding instsance specs done, needs test and sysncr…
kwonkwonn Nov 21, 2025
00aabcd
all functions for retreving both alive,dead vm status implremented, n…
kwonkwonn Nov 22, 2025
c1c40f2
vcpu status retreving done, need to add abstraction structure to use …
kwonkwonn Nov 23, 2025
0c43e76
Merge pull request #55 from easy-cloud-Knet/vcpu_info
kwonkwonn Nov 23, 2025
a6150d1
fixed operation to be done atomic
kwonkwonn Nov 23, 2025
d7d3e0e
Merge pull request #56 from easy-cloud-Knet/vcpu_info
kwonkwonn Nov 23, 2025
cae7080
add log printing ont deleting domain than only responsing it through …
kwonkwonn Nov 24, 2025
b6bd335
retreving vcpu error while domain is inactive specified, need further…
kwonkwonn Nov 24, 2025
f97cce0
Merge pull request #58 from easy-cloud-Knet/vcpu_info
kwonkwonn Nov 24, 2025
ab12948
Implement internal snapshot logic
Jbchan01 Dec 24, 2025
56a8862
internal_snapshot
Jbchan01 Jan 4, 2026
40ce344
internal_snapshot
Jbchan01 Jan 4, 2026
bbb64ee
Merge pull request #61 from easy-cloud-Knet/snapshot
kwonkwonn Jan 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions DomCon/DomainUpdate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package domCon

// Di injector for domain xml unparse and update

// func (DC *DomListControl) UpdateDomainStatus(Dom *Domain, logger *zap.Logger) error {

// domcnf, err := domStatus.XMLUnparse(Dom.Domain)
// if err != nil {
// logger.Error("failed to unparse domain XML", zap.Error(err))
// return err
// }

// }
18 changes: 18 additions & 0 deletions DomCon/control_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package domCon
import (
"sync"

domStatus "github.com/easy-cloud-Knet/KWS_Core/DomCon/domain_status"
"libvirt.org/go/libvirt"
)

Expand All @@ -11,20 +12,37 @@ import (
// DomainList 에서 uuid형태로 각각의 도메인을 관리






type DomListControl struct {
DomainList map[string]*Domain
domainListMutex sync.Mutex
DomainListStatus * domStatus.DomainListStatus
}
// 각 도메인을 관리하는 인메모리 구조체
// mutex 를 통해 동시성 제어
// 메모리 누수방지 + libvirt 접근 최소화 위해 libvirt.Domain 포인터를 보유



type Domain struct {
Domain *libvirt.Domain
domainMutex sync.Mutex
}
// 각 도메인의 상태변경시에 사용하는 구조체
// mutex 를 통해 동시성 제어



type DomainSeekingByUUID struct {
LibvirtInst *libvirt.Connect
UUID string
}
// 도메인 탐색 인터페이스
// 인메모리 도메인 리스트에 없을 경우 libvirt 에서 도메인을 찾아 반환하는 역할


type DomainSeeker interface {
ReturnDomain() (*Domain, error)
Expand Down
50 changes: 42 additions & 8 deletions DomCon/domain_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"sync"

domStatus "github.com/easy-cloud-Knet/KWS_Core/DomCon/domain_status"
virerr "github.com/easy-cloud-Knet/KWS_Core/error"
"go.uber.org/zap"
"libvirt.org/go/libvirt"
Expand All @@ -20,15 +21,32 @@ func DomListConGen() *DomListControl {
return &DomListControl{
domainListMutex: sync.Mutex{},
DomainList: make(map[string]*Domain),
DomainListStatus: &domStatus.DomainListStatus{},
}
}// 전역적으로 사용되는 도메인 리스트 컨트롤러 생성


func (DC *DomListControl) AddNewDomain(domain *Domain, uuid string) error {
DC.domainListMutex.Lock()
defer DC.domainListMutex.Unlock()

DC.DomainList[uuid] = domain
vcpu, err :=domain.Domain.GetMaxVcpus()
if err != nil {
Err:=fmt.Errorf("%v error while getting vcpu count during adding new domain",err)
return Err
}
DC.DomainListStatus.AddAllocatedCPU(int(vcpu))
return nil
}

func (DC *DomListControl) AddNewDomain(domain *Domain, uuid string) {
func (DC *DomListControl) AddExistingDomain(domain *Domain, uuid string) {
DC.domainListMutex.Lock()
defer DC.domainListMutex.Unlock()

DC.DomainList[uuid] = domain
}
// Exstring Domain only called from initial booting, and adding specs is not its role

func (DC *DomListControl) GetDomain(uuid string, LibvirtInst *libvirt.Connect) (*Domain, error) {
fmt.Println(DC)
Expand All @@ -51,15 +69,18 @@ func (DC *DomListControl) GetDomain(uuid string, LibvirtInst *libvirt.Connect) (
return domain, nil
}

func (DC *DomListControl) DeleteDomain(Domain *libvirt.Domain, uuid string) error {
func (DC *DomListControl) DeleteDomain(Domain *libvirt.Domain, uuid string, vcpu int) error {
DC.domainListMutex.Lock()
delete(DC.DomainList, uuid)
Domain.Free()
DC.domainListMutex.Unlock()
DC.DomainListStatus.TakeAllocatedCPU(vcpu)
return nil
}

func (DC *DomListControl) FindAndDeleteDomain(LibvirtInst *libvirt.Connect, uuid string) error {
//아직 활용처가 없어서, vcpu 삭제를 추가하지 않았음/
// DeleteDomain 함수의 TakeAllocatedCPU 호출을 참고..
DC.domainListMutex.Lock()
domain, Exist := DC.DomainList[uuid]
DC.domainListMutex.Unlock()
Expand Down Expand Up @@ -90,24 +111,35 @@ func (DC *DomListControl) retrieveDomainsByState(LibvirtInst *libvirt.Connect, s
return err
}

DC.domainListMutex.Lock()
defer DC.domainListMutex.Unlock()

dataDog := domStatus.NewDataDog(state)
wg:= &sync.WaitGroup{}
for _, dom := range domains {
uuid, err := dom.GetUUIDString()
if err != nil {
logger.Sugar().Error("Failed to get UUID for domain", err)
continue
}

DC.DomainList[uuid] = &Domain{
NewDom:= &Domain{
Domain: &dom,
domainMutex: sync.Mutex{},
}
// logger.Infof("Added domain: UUID=%s", uuid)
DC.AddExistingDomain(NewDom,uuid)

wg.Add(1)
go func(targetDom libvirt.Domain) {
defer wg.Done()
retrieveFunc := dataDog.Retreive(&targetDom, DC.DomainListStatus, *logger)
if retrieveFunc != nil {
logger.Sugar().Errorf("Failed to retrieve status for domain UUID=%s: %v", uuid, retrieveFunc)
}

}(dom)
logger.Sugar().Infof("Added domain: UUID=%s", uuid)
}

wg.Wait()
fmt.Printf("%+v", *DC.DomainListStatus)

logger.Sugar().Infof("Total %d domains added (state: %d)", len(domains), state)
return nil
}
Expand Down Expand Up @@ -139,3 +171,5 @@ func (DC *DomListControl) GetAllUUIDs() []string {
}
return uuids
}

////////////////////////////////////////////////
34 changes: 34 additions & 0 deletions DomCon/domain_status/cpu_status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package domStatus

import (
"runtime"
"sync/atomic"
)

func (dls *DomainListStatus) UpdateCPUTotal() {
totalCPU := runtime.NumCPU()
dls.VCPUTotal = int64(totalCPU)
}

func (dls *DomainListStatus) AddAllocatedCPU(vcpu int) error {
atomic.AddInt64(&dls.VcpuAllocated, int64(vcpu))
return nil
}

func (dls *DomainListStatus) AddSleepingCPU(vcpu int) error {
atomic.AddInt64(&dls.VcpuSleeping, int64(vcpu))
return nil
}
func (dls *DomainListStatus) TakeAllocatedCPU(vcpu int) error {

atomic.AddInt64(&dls.VcpuAllocated, -int64(vcpu))
return nil
}

func (dls *DomainListStatus) TakeSleepingCPU(vcpu int) error {

atomic.AddInt64(&dls.VcpuSleeping, -int64(vcpu))
return nil
}


51 changes: 51 additions & 0 deletions DomCon/domain_status/cpu_status_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package domStatus

import (
"sync"
"testing"
)



func TestVCPUAtomic(t *testing.T){
dls := &DomainListStatus{}

wg:= sync.WaitGroup{}

wg.Add(1000)
for i:=0; i<1000; i++{
go func(){
dls.AddAllocatedCPU(4)
dls.AddSleepingCPU(1)
defer wg.Done()
}()
}
wg.Wait()

result:= dls.VcpuAllocated
if result != 4000{
t.Errorf("Expected 4000 allocated CPUs, got %d", result)
}
result1:=dls.VcpuSleeping
if result1 != 1000{
t.Errorf("Expected 1000 sleeping CPUs, got %d", result)
}
wg.Add(450)

for i:=0; i<450; i++{
go func(){
dls.TakeAllocatedCPU(4)
dls.TakeSleepingCPU(1)
defer wg.Done()
}()
}
wg.Wait()
finalAllocated:= dls.VcpuAllocated
if finalAllocated != 2200{
t.Errorf("Expected 2200 allocated CPUs after taking, got %d", finalAllocated)
}
finalSleeping:= dls.VcpuSleeping
if finalSleeping != 550{
t.Errorf("Expected 550 sleeping CPUs after taking, got %d", finalSleeping)
}
}
49 changes: 49 additions & 0 deletions DomCon/domain_status/newStatus.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package domStatus

import (
"fmt"

"go.uber.org/zap"
"libvirt.org/go/libvirt"
)



func NewDataDog(state libvirt.ConnectListAllDomainsFlags) DataDog {
switch state {
case libvirt.CONNECT_LIST_DOMAINS_ACTIVE:
fmt.Println("returning active")
return &libvirtStatus{}
case libvirt.CONNECT_LIST_DOMAINS_INACTIVE:
fmt.Println("returning inactive")
return &XMLStatus{}
default:
return nil
}
}


func (ds *XMLStatus) Retreive(dom *libvirt.Domain,DLS *DomainListStatus, logger zap.Logger) ( error) {
domcnf, err := XMLUnparse(dom)
if err != nil {
logger.Error("failed to unparse domain XML", zap.Error(err))
return nil
}
DLS.AddAllocatedCPU(int(domcnf.VCPU.Value))
DLS.AddSleepingCPU(int(domcnf.VCPU.Value))
return nil

}

func (ls *libvirtStatus) Retreive(dom *libvirt.Domain, DLS *DomainListStatus, logger zap.Logger) (error) {
cpuCount, err := dom.GetMaxVcpus()
if err != nil {
logger.Error("failed to get live vcpu count", zap.Error(err))
return nil
}

fmt.Printf("%+v", cpuCount)
DLS.AddAllocatedCPU(int(cpuCount))
return nil

}
67 changes: 67 additions & 0 deletions DomCon/domain_status/status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package domStatus

import (
"go.uber.org/zap"
"libvirt.org/go/libvirt"
)

// cpu 는 각각 4개의 상태를 가짐
// 할당되어 활동중임
// 할당되어 있으나 유휴상태임(도메인이 꺼져있는 상태)
// 할당되어 있지 않음
// 총 cpu 수

// 우선순위 = 할당 되어 있지 않은 cpu 부터
// 그 이후 할당되어 있으나 유휴 상태인 cpu

type DataDog interface {
Retreive(*libvirt.Domain,*DomainListStatus ,zap.Logger) ( error )
}

type XMLStatus struct{
}
// 꺼져있는 도메인의 cpu 수

type libvirtStatus struct{
}
// 할당되어 활동중인 cpu 수

type DomainListStatus struct {
VCPUTotal int64 // 호스트 전체 cpu 수
VcpuAllocated int64 // 할당 된 vcpu 수
VcpuSleeping int64 // 유휴 상태인 vcpu 수
// vcpuIdle = 할당되어 있지 않은 vcpu 수
//VcpuIdle = VcpuTotal-VcpuAllocated
}

//////////////////////////////


type StatusEmitter interface{
EmitStatus(dls *DomainListStatus) ( error)
}
// 상태 반환을 위한 인터페이스
// 각 상태 구조체는 EmitStatus 메서드를 구현해야함
// status service 에서 사용


type VCPUStatus struct{
Total int `json:"total"`
Allocated int `json:"allocated"`
Sleeping int `json:"sleeping"`
Idle int `json:"idle"`
}
// 인터페이스 구현체

func (vs *VCPUStatus) EmitStatus(dls *DomainListStatus) ( error) {
vs.Total = int(dls.VCPUTotal)
vs.Allocated = int(dls.VcpuAllocated)
vs.Sleeping = int(dls.VcpuSleeping)

vs.Idle = vs.Total - vs.Allocated
if vs.Idle < 0 {
vs.Idle = 0
}

return nil
}
Loading