Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
27 changes: 27 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Lint

on:
push:
branches: ["**"]
pull_request:
branches: ["**"]

jobs:
lint:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: false

- name: Install system dependencies
run: sudo apt-get install -y libvirt-dev pkg-config

- name: golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: latest
28 changes: 28 additions & 0 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Unit Test

on:
push:
branches: ["**"]
pull_request:
branches: ["**"]

jobs:
test:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version-file: go.mod
cache: true

- name: Install system dependencies
run: sudo apt-get install -y libvirt-dev pkg-config whois

- name: Build
run: go build ./...

- name: Test
run: go test -v -count=1 ./...
24 changes: 24 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
linters:
enable:
- errcheck
- unused
- govet
- staticcheck

issues:
exclude-rules:
# libvirt resource cleanup — error return is not actionable
- linters: [errcheck]
text: "Error return value of `.*\\.Free` is not checked"

# zap logger sync — standard deferred pattern
- linters: [errcheck]
text: "Error return value of `.*\\.Sync` is not checked"

# http.ResponseWriter.Write — error not recoverable after headers sent
- linters: [errcheck]
text: "Error return value of `.*w\\.Write` is not checked"

# json.Encoder.Encode in HTTP handlers — same rationale
- linters: [errcheck]
text: "Error return value of `.*\\.Encode` is not checked"
17 changes: 5 additions & 12 deletions DomCon/domainList_status/cpu_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

// 인터페이스 구현체

func (vs *VCPUStatus) EmitStatus(dls *DomainListStatus) error {
func (vs *VCPUStatus) EmitStatus(dls *DomainListStatus) {
vs.Total = int(dls.VCPUTotal)
vs.Allocated = int(dls.VcpuAllocated)
vs.Sleeping = int(dls.VcpuSleeping)
Expand All @@ -16,8 +16,6 @@ func (vs *VCPUStatus) EmitStatus(dls *DomainListStatus) error {
if vs.Idle < 0 {
vs.Idle = 0
}

return nil
}

func (dls *DomainListStatus) Update() {
Expand All @@ -29,23 +27,18 @@ func (dls *DomainListStatus) UpdateCPUTotal() {
dls.VCPUTotal = int64(totalCPU)
}

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

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

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

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

func (dls *DomainListStatus) TakeSleepingCPU(vcpu int) {
atomic.AddInt64(&dls.VcpuSleeping, -int64(vcpu))
return nil
}
7 changes: 4 additions & 3 deletions DomCon/domain_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,21 @@ func (DC *DomListControl) GetDomain(uuid string, LibvirtInst *libvirt.Connect) (
if err != nil {
return nil, err
}
DC.AddNewDomain(dom, uuid)
if err := DC.AddNewDomain(dom, uuid); err != nil {
return nil, err
}
return dom, nil
}

return domain, nil
}

func (DC *DomListControl) DeleteDomain(Domain *libvirt.Domain, uuid string, vcpu int) error {
func (DC *DomListControl) DeleteDomain(Domain *libvirt.Domain, uuid string, vcpu int) {
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 {
Expand Down
17 changes: 6 additions & 11 deletions DomCon/domain_seeker.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ import (
"libvirt.org/go/libvirt"
)


func DomSeekUUIDFactory(LibInstance *libvirt.Connect,UUID string)*DomainSeekingByUUID{
return &DomainSeekingByUUID{
func DomSeekUUIDFactory(LibInstance *libvirt.Connect, UUID string) *DomainSeekingByUUID {
return &DomainSeekingByUUID{
LibvirtInst: LibInstance,
UUID: UUID,
}
}


func ReturnUUID(UUID string) (*uuid.UUID, error) {
uuidParsed, err := uuid.Parse(UUID)
if err != nil {
Expand All @@ -25,23 +23,20 @@ func ReturnUUID(UUID string) (*uuid.UUID, error) {
return &uuidParsed, nil
}


func (DSU *DomainSeekingByUUID) ReturnDomain() (*Domain, error) {
parsedUUID, err := uuid.Parse(DSU.UUID)
if err != nil {
return nil,virerr.ErrorGen(virerr.InvalidUUID, err)
return nil, virerr.ErrorGen(virerr.InvalidUUID, err)
}
domain, err := DSU.LibvirtInst.LookupDomainByUUID(parsedUUID[:])
if err != nil {
return nil,virerr.ErrorGen(virerr.DomainSearchError, err)
}else if domain==nil {
return nil,virerr.ErrorGen(virerr.NoSuchDomain, err)
return nil, virerr.ErrorGen(virerr.DomainSearchError, err)
} else if domain == nil {
return nil, virerr.ErrorGen(virerr.NoSuchDomain, err)
}


return &Domain{
Domain: domain,
domainMutex: sync.Mutex{},
}, nil
}

28 changes: 0 additions & 28 deletions api/snapshot_model.go

This file was deleted.

13 changes: 4 additions & 9 deletions api/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@ import (
"go.uber.org/zap"
)






func (i *InstHandler) ReturnStatusUUID(w http.ResponseWriter, r *http.Request) {
param := &DomainStatusRequest{}
resp := ResponseGen[status.DataTypeHandler]("domain Status UUID")
Expand All @@ -38,14 +33,15 @@ func (i *InstHandler) ReturnStatusUUID(w http.ResponseWriter, r *http.Request) {

DomainDetail := status.DomainDetailFactory(outputStruct, dom)

outputStruct.GetInfo(dom)
if err := outputStruct.GetInfo(dom); err != nil {
resp.ResponseWriteErr(w, err, http.StatusInternalServerError)
return
}
DomainDetail.DataHandle = outputStruct
resp.ResponseWriteOK(w, &DomainDetail.DataHandle)

}



func (i *InstHandler) ReturnStatusHost(w http.ResponseWriter, r *http.Request) {
param := &HostStatusRequest{}
resp := ResponseGen[status.HostDataTypeHandler]("Host Status Return")
Expand All @@ -62,7 +58,6 @@ func (i *InstHandler) ReturnStatusHost(w http.ResponseWriter, r *http.Request) {
return
}


host, err := status.HostInfoHandler(dataHandle, i.DomainControl.DomainListStatus)
if err != nil {
resp.ResponseWriteErr(w, err, http.StatusInternalServerError)
Expand Down
30 changes: 13 additions & 17 deletions api/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,44 +10,42 @@ import (
virerr "github.com/easy-cloud-Knet/KWS_Core/error"
)



type BaseResponse[T any] struct {
Information *T `json:"information,omitempty"`
Message string `json:"message"`
Information *T `json:"information,omitempty"`
Message string `json:"message"`
Errors *virerr.ErrorDescriptor `json:"errors,omitempty"`
ErrorDebug string `json:"errrorDebug,omitempty"`
ErrorDebug string `json:"errrorDebug,omitempty"`
}

func ResponseGen[T any](message string) *BaseResponse[T] {
return &BaseResponse[T]{
Message: fmt.Sprintf("%s operation", message),
Message: fmt.Sprintf("%s operation", message),
}
}

// HTTP 요청을 디코딩하는 함수
func HttpDecoder[T any](r *http.Request, param *T) error {
body, err := io.ReadAll(r.Body)
if err != nil {
return virerr.ErrorGen(virerr.FaildDeEncoding,fmt.Errorf("%w error unmarshaling body into Structure",err))
return virerr.ErrorGen(virerr.FaildDeEncoding, fmt.Errorf("%w error unmarshaling body into Structure", err))
}
defer r.Body.Close()

if err := json.Unmarshal(body, param); err != nil {
return virerr.ErrorGen(virerr.FaildDeEncoding,fmt.Errorf("%w error unmarshaling body into Structure",err))
return virerr.ErrorGen(virerr.FaildDeEncoding, fmt.Errorf("%w error unmarshaling body into Structure", err))
}
return nil
}

func (br *BaseResponse[T]) ResponseWriteErr(w http.ResponseWriter, err error, statusCode int) {
br.Message += " failed"
errDesc, ok:= err.(virerr.ErrorDescriptor)
if !ok{
errDesc, ok := err.(virerr.ErrorDescriptor)
if !ok {
http.Error(w, br.Message, http.StatusInternalServerError)
return
}
br.Errors = &errDesc
br.ErrorDebug= errDesc.Error()
br.ErrorDebug = errDesc.Error()
data, marshalErr := json.Marshal(br)
if marshalErr != nil {
http.Error(w, "failed to marshal error response", http.StatusInternalServerError)
Expand All @@ -61,23 +59,21 @@ func (br *BaseResponse[T]) ResponseWriteErr(w http.ResponseWriter, err error, st
func (br *BaseResponse[T]) ResponseWriteOK(w http.ResponseWriter, info *T) {
br.Message += " success"
br.Information = info
br.Errors=nil
br.Errors = nil
data, err := json.Marshal(br)
if err != nil {
http.Error(w, "failed to marshal success response", http.StatusInternalServerError)
return
}


w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write(data)
}


func (i *InstHandler) domainConGetter()(*domCon.DomListControl, error){
if(i.DomainControl == nil){
func (i *InstHandler) domainConGetter() (*domCon.DomListControl, error) {
if i.DomainControl == nil {
return nil, virerr.ErrorGen(virerr.InvalidParameter, fmt.Errorf("domainController not initialled yet"))
}
return i.DomainControl,nil
return i.DomainControl, nil
}
Loading
Loading