diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 04c1789..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -KWS_* diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index dce9e03..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,136 +0,0 @@ -# CLAUDE.md — KWS_Core - -## Project Overview - -KWS_Core is a personal cloud management system that wraps libvirt (QEMU/KVM) with a REST API for VM lifecycle management. - -- **Module**: `github.com/easy-cloud-Knet/KWS_Core` -- **Language**: Go 1.24.0 -- **Key dependencies**: `libvirt.org/go/libvirt`, `go.uber.org/zap`, `github.com/shirou/gopsutil`, `gopkg.in/yaml.v3` - -## Build & Run - -```bash -make conf # First-time setup (installs Go, dependencies, monitoring) -make build # Compile → produces KWS_Core binary in project root -make run # Build + execute locally -make clean # Remove binary -``` - -**Deploy**: `sudo systemctl start kws_core` -**Logs**: `/var/log/kws/{YYYYMMDD}.log` + stdout - -## Architecture - -``` -HTTP Server (:8080) - ↓ -API Handlers (api/) — methods on InstHandler, JSON request/response - ↓ -Service Layer (vm/service/) — creation, termination, status, snapshot - ↓ -Domain Controller (DomCon/) — in-memory VM registry, thread-safe - ↓ -Libvirt (QEMU/KVM) -``` - -**Key directories**: -| Directory | Purpose | -|-----------|---------| -| `api/` | HTTP handlers, request/response types, generic `BaseResponse[T]` | -| `server/` | HTTP mux setup, route registration, logger middleware | -| `DomCon/` | In-memory domain map, mutex-guarded, domain seeking/caching | -| `DomCon/domain_status/` | CPU/memory accounting with atomic ops | -| `vm/service/creation/` | VM creation via `VMCreator` interface + factory | -| `vm/service/termination/` | Shutdown/deletion via `DomainTermination`/`DomainDeletion` interfaces | -| `vm/service/status/` | Host and VM metrics, `DataTypeHandler` router | -| `vm/service/snapshot/` | Snapshot lifecycle management | -| `vm/parsor/` | XML config generation, cloud-init YAML parsing | -| `error/` | Custom `VirError` types, `ErrorDescriptor`, `ErrorGen`/`ErrorJoin` | -| `logger/` | zap-based structured logger, HTTP middleware | -| `net/` | Network configuration parsing | - -**Entry point**: `main.go` → init logger → create DomListControl → connect libvirt → load domains → start server - -## Code Patterns (must follow) - -### Handler pattern -All HTTP endpoints are receiver methods on `InstHandler` (`api/type.go`). Standard flow: -1. Create param struct + `ResponseGen[T](message)` -2. Decode body with `HttpDecoder(r, param)` -3. Validate / retrieve domain -4. Call service layer -5. Return `resp.ResponseWriteOK(w, data)` or `resp.ResponseWriteErr(w, err, status)` - -### Factory pattern -Object creation uses `*Factory()` functions. Examples: -- `DomSeekUUIDFactory()` — domain lookup -- `DomainTerminatorFactory()` / `DomainDeleterFactory()` — shutdown/delete -- `LocalConfFactory()` / `LocalCreatorFactory()` — VM creation -- `DomListConGen()` — domain list controller - -### Interface-first design -Define interfaces before implementations: -- `VMCreator` — `CreateVM() (*libvirt.Domain, error)` -- `DomainTermination` — `TerminateDomain() (*libvirt.Domain, error)` -- `DomainDeletion` — `DeleteDomain() (*libvirt.Domain, error)` -- `DataTypeHandler` — `GetInfo(*domCon.Domain) error` -- `DomainSeeker` — `ReturnDomain() (*Domain, error)` - -### Thread safety -- `sync.Mutex` on `DomListControl` (list-level) and `Domain` (domain-level) -- `atomic.AddInt64` for CPU counter operations in `DomainListStatus` -- Lock → defer Unlock pattern throughout - -### Error handling -Use the custom error package (`error/Error.go`), not raw `errors.New()`: -```go -// Create a typed error -virerr.ErrorGen(virerr.DomainGenerationError, fmt.Errorf("detail: %w", err)) - -// Chain errors with context -virerr.ErrorJoin(existingErr, fmt.Errorf("additional context")) -``` -Predefined error constants: `NoSuchDomain`, `DomainGenerationError`, `LackCapacityCPU`, `LackCapacityRAM`, `InvalidUUID`, `InvalidParameter`, etc. - -### VM storage convention -All VM artifacts live in `/var/lib/kws/{uuid}/` — disk images (`{uuid}.qcow2`), cloud-init ISO (`cidata.iso`), config files. - -## Logging Rules - -- Use `*zap.Logger` injected via `InstHandler`. **Never** use `fmt.Println`, `fmt.Printf`, or `log.*` for runtime logs. -- Log only at **API/handler** and **service** layers. Lower layers return errors; callers decide how to log. -- **Levels**: Debug (dev detail), Info (operations), Warn (recoverable), Error (with `zap.Error(err)`), Fatal/Panic (bootstrap only). -- **Standard fields**: `component`, `uuid`, `request_id`, `error`. -- Prefix error logs with where the error occurred for debugging context. -- Never log raw pointers or entire internal structs. - -```go -// Good -logger.Error("failed to create vm", zap.String("uuid", uuid), zap.Error(err)) - -// Bad -fmt.Println("error:", err) -``` - -## Behavioral Guidelines - -### Think before coding -- State assumptions explicitly. If uncertain, ask. -- If multiple interpretations exist, present them — don't pick silently. -- If a simpler approach exists, say so. Push back when warranted. - -### Simplicity first -- Minimum code that solves the problem. No speculative features. -- No abstractions for single-use code. No "flexibility" that wasn't requested. -- No error handling for impossible scenarios. - -### Surgical changes -- Touch only what you must. Don't "improve" adjacent code or formatting. -- Match existing style, even if you'd do it differently. -- Remove imports/variables/functions that YOUR changes made unused. -- Every changed line should trace directly to the request. - -### Goal-driven execution -- Transform tasks into verifiable goals before implementing. -- For multi-step tasks, state a brief plan with verification steps. diff --git a/DomCon/DomainUpdate.go b/DomCon/DomainUpdate.go deleted file mode 100644 index a93a7b7..0000000 --- a/DomCon/DomainUpdate.go +++ /dev/null @@ -1,13 +0,0 @@ -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 -// } - -// } \ No newline at end of file diff --git a/DomCon/control_type.go b/DomCon/control_type.go index df32585..864aec6 100755 --- a/DomCon/control_type.go +++ b/DomCon/control_type.go @@ -3,7 +3,6 @@ package domCon import ( "sync" - domStatus "github.com/easy-cloud-Knet/KWS_Core/DomCon/domain_status" "libvirt.org/go/libvirt" ) @@ -12,37 +11,20 @@ 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) diff --git a/DomCon/domain_list.go b/DomCon/domain_list.go index b9b2c09..2be770b 100755 --- a/DomCon/domain_list.go +++ b/DomCon/domain_list.go @@ -4,7 +4,6 @@ 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" @@ -21,33 +20,18 @@ 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 { - return virerr.ErrorGen(virerr.DomainGenerationError, fmt.Errorf("error while getting vcpu count during adding new domain: %w", err)) - } - DC.DomainListStatus.AddAllocatedCPU(int(vcpu)) - return nil } -func (DC *DomListControl) AddExistingDomain(domain *Domain, uuid string) { +func (DC *DomListControl) AddNewDomain(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) DC.domainListMutex.Lock() domain, Exist := DC.DomainList[uuid] DC.domainListMutex.Unlock() @@ -55,27 +39,27 @@ func (DC *DomListControl) GetDomain(uuid string, LibvirtInst *libvirt.Connect) ( DomainSeeker := DomSeekUUIDFactory(LibvirtInst, uuid) dom, err := DomainSeeker.ReturnDomain() if err != nil { + fmt.Println(err) return nil, err } + fmt.Println(dom) DC.AddNewDomain(dom, uuid) return dom, nil } + fmt.Println(domain) return domain, nil } -func (DC *DomListControl) DeleteDomain(Domain *libvirt.Domain, uuid string, vcpu int) error { +func (DC *DomListControl) DeleteDomain(Domain *libvirt.Domain, uuid string) 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() @@ -106,34 +90,24 @@ 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 } - NewDom:= &Domain{ + + DC.DomainList[uuid] = &Domain{ Domain: &dom, domainMutex: sync.Mutex{}, } - 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.Infof("Added domain: UUID=%s", uuid) logger.Sugar().Infof("Added domain: UUID=%s", uuid) } - wg.Wait() - + logger.Sugar().Infof("Total %d domains added (state: %d)", len(domains), state) return nil } @@ -165,5 +139,3 @@ func (DC *DomListControl) GetAllUUIDs() []string { } return uuids } - -//////////////////////////////////////////////// \ No newline at end of file diff --git a/DomCon/domain_status/cpu_status.go b/DomCon/domain_status/cpu_status.go deleted file mode 100644 index 3795e2a..0000000 --- a/DomCon/domain_status/cpu_status.go +++ /dev/null @@ -1,34 +0,0 @@ -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 -} - - diff --git a/DomCon/domain_status/cpu_status_test.go b/DomCon/domain_status/cpu_status_test.go deleted file mode 100644 index ad28ecb..0000000 --- a/DomCon/domain_status/cpu_status_test.go +++ /dev/null @@ -1,51 +0,0 @@ -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) - } -} \ No newline at end of file diff --git a/DomCon/domain_status/newStatus.go b/DomCon/domain_status/newStatus.go deleted file mode 100644 index 7c96153..0000000 --- a/DomCon/domain_status/newStatus.go +++ /dev/null @@ -1,44 +0,0 @@ -package domStatus - -import ( - "go.uber.org/zap" - "libvirt.org/go/libvirt" -) - - - -func NewDataDog(state libvirt.ConnectListAllDomainsFlags) DataDog { - switch state { - case libvirt.CONNECT_LIST_DOMAINS_ACTIVE: - return &libvirtStatus{} - case libvirt.CONNECT_LIST_DOMAINS_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 - } - - DLS.AddAllocatedCPU(int(cpuCount)) - return nil - -} \ No newline at end of file diff --git a/DomCon/domain_status/status.go b/DomCon/domain_status/status.go deleted file mode 100644 index c01470f..0000000 --- a/DomCon/domain_status/status.go +++ /dev/null @@ -1,67 +0,0 @@ -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 -} diff --git a/DomCon/domain_status/xml_unparse.go b/DomCon/domain_status/xml_unparse.go deleted file mode 100644 index 1f60b86..0000000 --- a/DomCon/domain_status/xml_unparse.go +++ /dev/null @@ -1,26 +0,0 @@ -package domStatus - -import ( - "fmt" - - "libvirt.org/go/libvirt" - libvirtxml "libvirt.org/libvirt-go-xml" -) - -// 꺼져있는 도메인의 xml 을 파싱하여 도메인 상태를 업데이트 -func XMLUnparse(domain * libvirt.Domain) (*libvirtxml.Domain, error) { - - domainXML, err := domain.GetXMLDesc(0) - if err != nil { - return nil,fmt.Errorf("%xerror occured while calling xml specification", err) - } - domcnf := &libvirtxml.Domain{} - - err= domcnf.Unmarshal(domainXML) - if err != nil { - return nil, fmt.Errorf("%x error occured while unmarshalling xml, check for crushed format", err) - } - - return domcnf, nil -} - diff --git a/KWS_Core b/KWS_Core new file mode 100755 index 0000000..ac6f839 Binary files /dev/null and b/KWS_Core differ diff --git a/KWS_Server b/KWS_Server new file mode 100755 index 0000000..5ce5712 Binary files /dev/null and b/KWS_Server differ diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 3a7d67c..0000000 --- a/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -The MIT License - -Copyright (c) 2024-2025 Kwon Taekyoung -Copyright (c) 2024-2025 Jeon ByungChan - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - diff --git a/README.md b/README.md index 841b724..9e6ae70 100644 --- a/README.md +++ b/README.md @@ -1,104 +1,79 @@ -# KWS_Core -A VM lifecycle management REST API built on libvirt (QEMU/KVM). Provides HTTP endpoints for creating, booting, shutting down, deleting, and snapshotting virtual machines. +## 🛠️ Setup Instructions -## Prerequisites +Follow these simple steps to set up `kws_core`: -- **Linux** with systemd -- **Go** 1.24+ -- **libvirt** and **QEMU/KVM** -- **Open vSwitch** (for network bridging) -- **genisoimage** (cloud-init ISO generation) -- **mkpasswd** (VM user password hashing) +### 1️⃣ **Configuration** +First, configure your service by running: -## Quick Start +```bash +make conf +``` + +This will generate the necessary configuration files for your cloud service. 📄✨ + +--- + +### 2️⃣ **Build** +Next, build the application with: ```bash -make conf # Install Go, dependencies, monitoring agents -make build # Compile binary -sudo systemctl start kws_core # Start the service +make build ``` -## Build Commands +This compiles all the source code and prepares `kws_core` for deployment. 🏗️🔧 -| Command | Description | -|--------------|------------------------------------------------------| -| `make conf` | First-time setup: installs Go, node_exporter, promtail, configures libvirt hooks | -| `make build` | Compile to `KWS_Core` binary in project root | -| `make run` | Build and execute locally | -| `make clean` | Remove the binary | +--- -## Architecture +### 3️⃣ **Start the Service** +Finally, start your service using: +```bash +sudo systemctl start kws_core ``` -HTTP Server (:8080) - | -API Handlers (api/) -- methods on InstHandler, JSON request/response - | -Service Layer (vm/service/) -- creation, termination, status, snapshot - | -Domain Controller (DomCon/) -- in-memory VM registry, thread-safe - | -Libvirt (QEMU/KVM) + +Your personal cloud is now live! 🎉🌈 You can check its status with: + +```bash +sudo systemctl status kws_core ``` -## API Endpoints +--- -| Method | Path | Description | -|--------|--------------------------|------------------------------------| -| POST | `/createVM` | Create a new VM from a base image | -| POST | `/BOOTVM` | Boot an existing VM | -| POST | `/forceShutDownUUID` | Force shutdown a VM by UUID | -| POST | `/DeleteVM` | Delete a VM and its artifacts | -| GET | `/getStatusUUID` | Get status of a specific VM | -| GET | `/getStatusHost` | Get host system metrics | -| GET | `/getInstAllInfo` | Get detailed info for all VMs | -| GET | `/getAllUUIDs` | List all VM UUIDs | -| GET | `/getAll-uuidstatusList` | List all VMs with their states | -| POST | `/CreateSnapshot` | Create a VM snapshot | -| GET | `/ListSnapshots` | List snapshots for a VM | -| POST | `/RevertSnapshot` | Revert a VM to a snapshot | -| POST | `/DeleteSnapshot` | Delete a snapshot | +## 📂 Where Is Everything? -## Configuration +- **Configuration Files**: Located in the `conf/` directory. +- **Binary Files**: Generated in the `build/` directory after running `make build`. +- **Logs**: Check `/var/log/kws_core.log` for detailed logs. -| Item | Value | -|---------------|------------------------------------| -| Listen port | `8080` | -| VM storage | `/var/lib/kws/{uuid}/` | -| Log directory | `/var/log/kws/` | -| Log files | `{YYYYMMDD}.log` (daily rotation) | +--- -## Logging +## 💡 Tips & Tricks -Structured logging via [zap](https://github.com/uber-go/zap). Logs are written to `/var/log/kws/{YYYYMMDD}.log` and stdout. See [`logger/Readme.md`](logger/Readme.md) for conventions and usage guidelines. +- Want to restart the service? Run: + ```bash + sudo systemctl restart kws_core + ``` +- To stop the service gracefully, use: + ```bash + sudo systemctl stop kws_core + ``` -## Project Structure +--- -``` -KWS_Core/ - main.go -- Entry point - api/ -- HTTP handlers and request/response types - server/ -- HTTP mux setup and route registration - DomCon/ -- In-memory domain registry (mutex-guarded) - domain_status/ -- CPU/memory accounting with atomic ops - vm/ - service/ - creation/ -- VM creation (VMCreator interface, factory) - termination/ -- Shutdown and deletion - status/ -- Host and VM metrics - snapshot/ -- Snapshot lifecycle - parsor/ -- XML config and cloud-init YAML generation - net/ -- Network configuration parsing - error/ -- Custom VirError types and error chaining - logger/ -- zap logger setup and HTTP middleware - build/ -- Setup scripts (go.sh, autoconfig.sh, etc.) -``` +## 🎀 Why You'll Love It + +- **Simple Setup**: Just three commands to get started! +- **Customizable**: Configure it to suit your needs. +- **Reliable**: Built to keep your personal cloud running smoothly. + +--- + +Thank you for choosing `kws_core`! 🌟 Your cloud is now ready to serve you. Enjoy the journey! 🚀💕 -## Contributing +--- -See [`CLAUDE.md`](CLAUDE.md) for code conventions, patterns, and architectural guidelines. +Feel free to copy-paste this into an `README.md` file for your project! 😊 -## License +Sources -MIT License. See [`LICENSE`](LICENSE) for details. diff --git a/api/Control.go b/api/Control.go index e82f238..71db0e1 100755 --- a/api/Control.go +++ b/api/Control.go @@ -7,95 +7,73 @@ import ( domCon "github.com/easy-cloud-Knet/KWS_Core/DomCon" virerr "github.com/easy-cloud-Knet/KWS_Core/error" "github.com/easy-cloud-Knet/KWS_Core/vm/service/termination" - "go.uber.org/zap" "libvirt.org/go/libvirt" ) -func (i *InstHandler) ForceShutDownVM(w http.ResponseWriter, r *http.Request) { - param := &DomainControlRequest{} - resp := ResponseGen[any]("domain number of" + param.UUID + ", Force Shutdown VM") - if err := HttpDecoder(r, param); err != nil { - ERR := virerr.ErrorJoin(err, fmt.Errorf("error shutting down vm, from forceShutdown vm ")) - resp.ResponseWriteErr(w, ERR, http.StatusInternalServerError) - i.Logger.Error("failed to decode forceShutdown request", zap.Error(ERR)) - return - } - dom, err := i.DomainControl.GetDomain(param.UUID, i.LibvirtInst) - if err != nil { - ERR := virerr.ErrorJoin(err, fmt.Errorf("error shutting down vm, retreving Get domin error ")) - resp.ResponseWriteErr(w, ERR, http.StatusInternalServerError) - i.Logger.Error("failed to get domain for forceShutdown", zap.String("uuid", param.UUID), zap.Error(ERR)) + +func (i *InstHandler)ForceShutDownVM(w http.ResponseWriter, r *http.Request){ + param:= &DeleteDomain{} + resp:=ResponseGen[any]("domain number of"+param.UUID+", Force Shutdown VM") + + if err:=HttpDecoder(r,param); err!=nil{ + resp.ResponseWriteErr(w,virerr.ErrorJoin(err,fmt.Errorf("error shutting down vm, from forceShutdown vm ")), http.StatusInternalServerError) return } - vcpu, err := dom.Domain.GetMaxVcpus() - if err != nil { - ERR := virerr.ErrorJoin(err, fmt.Errorf("error shutting down vm, retreving Get domin error ")) - resp.ResponseWriteErr(w, ERR, http.StatusInternalServerError) - i.Logger.Error("failed to get vcpu count for forceShutdown", zap.String("uuid", param.UUID), zap.Error(ERR)) + fmt.Println(resp) + dom,err:= i.DomainControl.GetDomain(param.UUID,i.LibvirtInst) + if err!= nil{ + resp.ResponseWriteErr(w,virerr.ErrorJoin(err,fmt.Errorf("error shutting down vm, retreving Get domin error ")), http.StatusInternalServerError) return } - i.DomainControl.DomainListStatus.AddSleepingCPU(int(vcpu)) - DomainTerminator, _ := termination.DomainTerminatorFactory(dom) + DomainTerminator,_:= termination.DomainTerminatorFactory(dom) - _, err = DomainTerminator.TerminateDomain() - if err != nil { - resp.ResponseWriteErr(w, virerr.ErrorJoin(err, fmt.Errorf("error shutting down vm, retreving Get domin error ")), http.StatusInternalServerError) + _,err=DomainTerminator.TerminateDomain() + if err!= nil{ + resp.ResponseWriteErr(w,virerr.ErrorJoin(err,fmt.Errorf("error shutting down vm, retreving Get domin error ")), http.StatusInternalServerError) return } - resp.ResponseWriteOK(w, nil) -} + + resp.ResponseWriteOK(w,nil) + } + + -func (i *InstHandler) DeleteVM(w http.ResponseWriter, r *http.Request) { - param := &DomainControlRequest{} - resp := ResponseGen[libvirt.DomainInfo]("Deleting Vm") - if err := HttpDecoder(r, param); err != nil { - ERR := virerr.ErrorJoin(err, fmt.Errorf("error deleting vm, unparsing HTTP request ")) - resp.ResponseWriteErr(w, ERR, http.StatusInternalServerError) - i.Logger.Error("failed to decode deleteVM request", zap.Error(ERR)) +func (i *InstHandler)DeleteVM(w http.ResponseWriter, r *http.Request){ + param:=&DeleteDomain{} + resp:= ResponseGen[libvirt.DomainInfo]("Deleting Vm") + + if err:=HttpDecoder(r,param); err!=nil{ + resp.ResponseWriteErr(w,virerr.ErrorJoin(err,fmt.Errorf("error deleting vm, retreving Get domin error ")),http.StatusInternalServerError) return } - if _, err := domCon.ReturnUUID(param.UUID); err != nil { - ERR := virerr.ErrorJoin(err, fmt.Errorf("error deleting vm, invalid UUID ")) - resp.ResponseWriteErr(w, ERR, http.StatusInternalServerError) - i.Logger.Error("invalid UUID for deleteVM", zap.String("uuid", param.UUID), zap.Error(ERR)) + if _, err := domCon.ReturnUUID(param.UUID); err!=nil{ + resp.ResponseWriteErr(w,virerr.ErrorJoin(err,fmt.Errorf("error deleting vm, retreving Get domin error ")),http.StatusInternalServerError) return } // uuid 가 적합한지 확인 - domain, err := i.DomainControl.GetDomain(param.UUID, i.LibvirtInst) - if err != nil { - ERR := virerr.ErrorJoin(err, fmt.Errorf("error deleting vm, retreving Get domin error ")) - resp.ResponseWriteErr(w, ERR, http.StatusInternalServerError) - i.Logger.Error("failed to get domain for deleteVM", zap.String("uuid", param.UUID), zap.Error(ERR)) + + domain, err := i.DomainControl.GetDomain(param.UUID,i.LibvirtInst) + if err!=nil{ + resp.ResponseWriteErr(w,virerr.ErrorJoin(err,fmt.Errorf("error deleting vm, retreving Get domin error ")),http.StatusInternalServerError) return - //error handling + //error handling } - vcpu, err := domain.Domain.GetMaxVcpus() - if err != nil { - ERR := virerr.ErrorJoin(err, fmt.Errorf("error can't retreving vcpu count ")) - resp.ResponseWriteErr(w, ERR, http.StatusInternalServerError) - i.Logger.Error("failed to get vcpu count for deleteVM", zap.String("uuid", param.UUID), zap.Error(ERR)) - - vcpu = 2 - //return - //일단 지금은 해당 경우에 vcpu 숫자를 2로 설정 - } // 삭제된 도메인에서는 vcpu count 를 가져올 수 없으므로 미리 가져옴 . 맘에 안듦. 나중에 수정할 예정 - // TODO: GETMAXVCPU는 꺼진 도메인에 대해 동작하지 않음. DATADOG와 같은 인터페이스를 활용해서 상관없이 삭제할 수 있도록 - - DomainDeleter, _ := termination.DomainDeleterFactory(domain, param.DeletionType, param.UUID) - domDeleted, err := DomainDeleter.DeleteDomain() - if err != nil { - ERR := virerr.ErrorJoin(err, fmt.Errorf("error deleting vm, retreving Get domin error ")) - resp.ResponseWriteErr(w, ERR, http.StatusInternalServerError) - i.Logger.Error("failed to delete domain", zap.String("uuid", param.UUID), zap.Error(ERR)) + DomainDeleter,_:=termination.DomainDeleterFactory(domain, param.DeletionType, param.UUID) + domDeleted,err:=DomainDeleter.DeleteDomain() + if err!=nil{ + resp.ResponseWriteErr(w,virerr.ErrorJoin(err,fmt.Errorf("error deleting vm, retreving Get domin error ")),http.StatusInternalServerError) + fmt.Println(err) return } - i.DomainControl.DeleteDomain(domDeleted, param.UUID, int(vcpu)) + i.DomainControl.DeleteDomain(domDeleted,param.UUID) + - resp.ResponseWriteOK(w, nil) + resp.ResponseWriteOK(w,nil) } + diff --git a/api/Create.go b/api/Create.go index 70e760e..9aaf680 100755 --- a/api/Create.go +++ b/api/Create.go @@ -11,51 +11,16 @@ import ( "libvirt.org/go/libvirt" ) -func (i *InstHandler) BootVM(w http.ResponseWriter, r *http.Request) { - resp := ResponseGen[libvirt.DomainInfo]("BootVM") - param := &DomainBootRequest{} - - if err := HttpDecoder(r, param); err != nil { - resp.ResponseWriteErr(w, err, http.StatusBadRequest) - i.Logger.Error("error occured while decoding user's parameter of requested creation") - return - } - i.Logger.Info("Handling Boot VM", zap.String("uuid", param.UUID)) - - domCon, _ := i.domainConGetter() - - DomainExisting, _ := domCon.GetDomain(param.UUID, i.LibvirtInst) - if DomainExisting == nil { - resp.ResponseWriteErr(w, nil, http.StatusBadRequest) - i.Logger.Error("error handling booting vm, domain not found", zap.String("uuid", param.UUID)) - return - } - - err := DomainExisting.Domain.Create() - if err != nil { - newErr := virerr.ErrorGen(virerr.DomainGenerationError, fmt.Errorf(" %w error while booting domain, from BootVM", err)) - i.Logger.Error("error from booting vm", zap.Error(newErr)) - resp.ResponseWriteErr(w, newErr, http.StatusInternalServerError) - return - } - - vcpu, err := DomainExisting.Domain.GetMaxVcpus() - if err != nil { - resp.ResponseWriteErr(w, err, http.StatusInternalServerError) - return - } - i.DomainControl.DomainListStatus.TakeSleepingCPU(int(vcpu)) - - resp.ResponseWriteOK(w, nil) - i.Logger.Info("Boot VM request handled successfully", zap.String("uuid", param.UUID)) -} func (i *InstHandler) CreateVMFromBase(w http.ResponseWriter, r *http.Request) { resp := ResponseGen[libvirt.DomainInfo]("CreateVm") param := &parsor.VM_Init_Info{} - - domCon, _ := i.domainConGetter() + domCon,_:= i.domainConGetter() + if domCon==nil{ + fmt.Println("emrpy domcon") + } + if err := HttpDecoder(r, param); err != nil { resp.ResponseWriteErr(w, err, http.StatusBadRequest) @@ -64,31 +29,27 @@ func (i *InstHandler) CreateVMFromBase(w http.ResponseWriter, r *http.Request) { } i.Logger.Info("Handling Create VM", zap.String("uuid", param.UUID)) - domainExisting, _ := domCon.GetDomain(param.UUID, i.LibvirtInst) - if domainExisting != nil { + domainExisting,_:=domCon.GetDomain(param.UUID, i.LibvirtInst) + if (domainExisting!=nil){ + fmt.Println(domainExisting) resp.ResponseWriteErr(w, nil, http.StatusBadRequest) - i.Logger.Error("error handling creating vm, domain already exists", zap.String("uuid", param.UUID)) + i.Logger.Error("error handling creating vm, domain already exists", zap.String("uuid",param.UUID)) return } DomConf := creation.LocalConfFactory(param, i.Logger) - DomCreator := creation.LocalCreatorFactory(DomConf, i.LibvirtInst, i.Logger) - - newDomain, err := DomCreator.CreateVM() - if err != nil && newDomain == nil { - newErr := virerr.ErrorGen(virerr.DomainGenerationError, fmt.Errorf(" %w error while creating new domain, from CreateVM", err)) - i.Logger.Error("error from createvm", zap.Error(newErr)) + DomCreator:=creation.LocalCreatorFactory(DomConf, i.LibvirtInst,i.Logger) + + newDomain,err :=DomCreator.CreateVM() + if err!=nil&& newDomain==nil{ + newErr:=virerr.ErrorGen(virerr.DomainGenerationError, fmt.Errorf(" %w error while creating new domain, from CreateVM",err)) + i.Logger.Error("error from createvm" , zap.Error(newErr)) resp.ResponseWriteErr(w, err, http.StatusInternalServerError) - return - } - - err = domCon.AddNewDomain(newDomain, param.UUID) - if err != nil { - i.Logger.Error("error from createvm", zap.Error(err)) - resp.ResponseWriteErr(w, err, http.StatusInternalServerError) - return + return } + domCon.AddNewDomain(newDomain,param.UUID) + resp.ResponseWriteOK(w, nil) - + } diff --git a/api/control_model.go b/api/control_model.go deleted file mode 100644 index b130997..0000000 --- a/api/control_model.go +++ /dev/null @@ -1,8 +0,0 @@ -package api - -import "github.com/easy-cloud-Knet/KWS_Core/vm/service/termination" - -type DomainControlRequest struct { - UUID string `json:"UUID"` - DeletionType termination.DomainDeleteType `json:"DeleteType"` -} diff --git a/api/snapshot.go b/api/snapshot.go deleted file mode 100644 index dc42a00..0000000 --- a/api/snapshot.go +++ /dev/null @@ -1,171 +0,0 @@ -package api - -import ( - "fmt" - "net/http" - - virerr "github.com/easy-cloud-Knet/KWS_Core/error" - snapshotpkg "github.com/easy-cloud-Knet/KWS_Core/vm/service/snapshot" - "go.uber.org/zap" -) - -// CreateSnapshot creates a snapshot for the specified domain UUID -func (i *InstHandler) CreateSnapshot(w http.ResponseWriter, r *http.Request) { - param := &SnapshotRequest{} - resp := ResponseGen[string]("Create Snapshot") - - if err := HttpDecoder(r, param); err != nil { - resp.ResponseWriteErr(w, err, http.StatusInternalServerError) - i.Logger.Error("snapshot create decode failed", zap.Error(err)) - return - } - - if i.LibvirtInst == nil || i.DomainControl == nil { - resp.ResponseWriteErr(w, virerr.ErrorGen(virerr.InvalidParameter, fmt.Errorf("libvirt not initialized")), http.StatusInternalServerError) - i.Logger.Error("libvirt not initialized") - return - } - - name := param.Name - if name == "" { - name = param.UUID + "-snap" - } - - i.Logger.Info("snapshot create start", zap.String("uuid", param.UUID), zap.String("snapshot_name", name)) - - dom, err := i.DomainControl.GetDomain(param.UUID, i.LibvirtInst) - if err != nil { - resp.ResponseWriteErr(w, err, http.StatusInternalServerError) - i.Logger.Error("snapshot create failed - domain not found", zap.String("uuid", param.UUID), zap.Error(err)) - return - } - - snapName, err := snapshotpkg.CreateSnapshot(dom, name) - if err != nil { - resp.ResponseWriteErr(w, err, http.StatusInternalServerError) - i.Logger.Error("snapshot create failed", zap.String("uuid", param.UUID), zap.String("snapshot_name", name), zap.Error(err)) - return - } - - i.Logger.Info("snapshot create success", zap.String("uuid", param.UUID), zap.String("snapshot_name", snapName)) - resp.ResponseWriteOK(w, &snapName) -} - -// ListSnapshots returns all snapshot names for the specified domain UUID -func (i *InstHandler) ListSnapshots(w http.ResponseWriter, r *http.Request) { - param := &SnapshotRequest{} - resp := ResponseGen[[]string]("List Snapshots") - - if err := HttpDecoder(r, param); err != nil { - resp.ResponseWriteErr(w, err, http.StatusInternalServerError) - i.Logger.Error("snapshot list decode failed", zap.Error(err)) - return - } - - if i.LibvirtInst == nil || i.DomainControl == nil { - resp.ResponseWriteErr(w, virerr.ErrorGen(virerr.InvalidParameter, fmt.Errorf("libvirt not initialized")), http.StatusInternalServerError) - i.Logger.Error("libvirt not initialized") - return - } - - i.Logger.Info("snapshot list start", zap.String("uuid", param.UUID)) - - dom, err := i.DomainControl.GetDomain(param.UUID, i.LibvirtInst) - if err != nil { - resp.ResponseWriteErr(w, err, http.StatusInternalServerError) - i.Logger.Error("snapshot list failed - domain not found", zap.String("uuid", param.UUID), zap.Error(err)) - return - } - - names, err := snapshotpkg.ListSnapshots(dom) - if err != nil { - resp.ResponseWriteErr(w, err, http.StatusInternalServerError) - i.Logger.Error("snapshot list failed", zap.String("uuid", param.UUID), zap.Error(err)) - return - } - - i.Logger.Info("snapshot list success", zap.String("uuid", param.UUID), zap.Int("snapshot_count", len(names))) - resp.ResponseWriteOK(w, &names) -} - -// RevertSnapshot reverts the domain to a named snapshot -func (i *InstHandler) RevertSnapshot(w http.ResponseWriter, r *http.Request) { - param := &SnapshotRequest{} - resp := ResponseGen[any]("Revert Snapshot") - - if err := HttpDecoder(r, param); err != nil { - resp.ResponseWriteErr(w, err, http.StatusInternalServerError) - i.Logger.Error("snapshot revert decode failed", zap.Error(err)) - return - } - - if i.LibvirtInst == nil || i.DomainControl == nil { - resp.ResponseWriteErr(w, virerr.ErrorGen(virerr.InvalidParameter, fmt.Errorf("libvirt not initialized")), http.StatusInternalServerError) - i.Logger.Error("libvirt not initialized") - return - } - - if param.Name == "" { - resp.ResponseWriteErr(w, virerr.ErrorGen(virerr.InvalidParameter, fmt.Errorf("snapshot name required")), http.StatusBadRequest) - return - } - - i.Logger.Info("snapshot revert start", zap.String("uuid", param.UUID), zap.String("snapshot_name", param.Name)) - - dom, err := i.DomainControl.GetDomain(param.UUID, i.LibvirtInst) - if err != nil { - resp.ResponseWriteErr(w, err, http.StatusInternalServerError) - i.Logger.Error("snapshot revert failed - domain not found", zap.String("uuid", param.UUID), zap.Error(err)) - return - } - - if err := snapshotpkg.RevertToSnapshot(dom, param.Name); err != nil { - resp.ResponseWriteErr(w, err, http.StatusInternalServerError) - i.Logger.Error("snapshot revert failed", zap.String("uuid", param.UUID), zap.String("snapshot_name", param.Name), zap.Error(err)) - return - } - - i.Logger.Info("snapshot revert success", zap.String("uuid", param.UUID), zap.String("snapshot_name", param.Name)) - resp.ResponseWriteOK(w, nil) -} - -// DeleteSnapshot deletes a snapshot by name -func (i *InstHandler) DeleteSnapshot(w http.ResponseWriter, r *http.Request) { - param := &SnapshotRequest{} - resp := ResponseGen[any]("Delete Snapshot") - - if err := HttpDecoder(r, param); err != nil { - resp.ResponseWriteErr(w, err, http.StatusInternalServerError) - i.Logger.Error("snapshot delete decode failed", zap.Error(err)) - return - } - - if i.LibvirtInst == nil || i.DomainControl == nil { - resp.ResponseWriteErr(w, virerr.ErrorGen(virerr.InvalidParameter, fmt.Errorf("libvirt not initialized")), http.StatusInternalServerError) - i.Logger.Error("libvirt not initialized") - return - } - - if param.Name == "" { - resp.ResponseWriteErr(w, virerr.ErrorGen(virerr.InvalidParameter, fmt.Errorf("snapshot name required")), http.StatusBadRequest) - return - } - - i.Logger.Info("snapshot delete start", zap.String("uuid", param.UUID), zap.String("snapshot_name", param.Name)) - - dom, err := i.DomainControl.GetDomain(param.UUID, i.LibvirtInst) - if err != nil { - resp.ResponseWriteErr(w, err, http.StatusInternalServerError) - i.Logger.Error("snapshot delete failed - domain not found", zap.String("uuid", param.UUID), zap.Error(err)) - return - } - - if err := snapshotpkg.DeleteSnapshot(dom, param.Name); err != nil { - resp.ResponseWriteErr(w, err, http.StatusInternalServerError) - i.Logger.Error("snapshot delete failed", zap.String("uuid", param.UUID), zap.String("snapshot_name", param.Name), zap.Error(err)) - return - } - - i.Logger.Info("snapshot delete success", zap.String("uuid", param.UUID), zap.String("snapshot_name", param.Name)) - resp.ResponseWriteOK(w, nil) -} diff --git a/api/snapshot_model.go b/api/snapshot_model.go deleted file mode 100644 index 467e4bd..0000000 --- a/api/snapshot_model.go +++ /dev/null @@ -1,7 +0,0 @@ -package api - -// Snapshot API structures -type SnapshotRequest struct { - UUID string `json:"UUID"` - Name string `json:"Name,omitempty"` -} diff --git a/api/status.go b/api/status.go index b9c2ece..5c53cee 100755 --- a/api/status.go +++ b/api/status.go @@ -3,20 +3,17 @@ package api import ( "encoding/json" "errors" + "fmt" "net/http" + "reflect" virerr "github.com/easy-cloud-Knet/KWS_Core/error" "github.com/easy-cloud-Knet/KWS_Core/vm/service/status" "go.uber.org/zap" ) - - - - - func (i *InstHandler) ReturnStatusUUID(w http.ResponseWriter, r *http.Request) { - param := &DomainStatusRequest{} + param := &ReturnDomainFromUUID{} resp := ResponseGen[status.DataTypeHandler]("domain Status UUID") if err := HttpDecoder(r, param); err != nil { @@ -40,14 +37,13 @@ func (i *InstHandler) ReturnStatusUUID(w http.ResponseWriter, r *http.Request) { outputStruct.GetInfo(dom) DomainDetail.DataHandle = outputStruct + fmt.Println(outputStruct) resp.ResponseWriteOK(w, &DomainDetail.DataHandle) } - - func (i *InstHandler) ReturnStatusHost(w http.ResponseWriter, r *http.Request) { - param := &HostStatusRequest{} + param := &ReturnHostFromStatus{} resp := ResponseGen[status.HostDataTypeHandler]("Host Status Return") if err := HttpDecoder(r, param); err != nil { @@ -61,9 +57,8 @@ func (i *InstHandler) ReturnStatusHost(w http.ResponseWriter, r *http.Request) { resp.ResponseWriteErr(w, err, http.StatusInternalServerError) return } - - - host, err := status.HostInfoHandler(dataHandle, i.DomainControl.DomainListStatus) + fmt.Println("data sending", reflect.TypeOf(dataHandle)) + host, err := status.HostDetailFactory(dataHandle) if err != nil { resp.ResponseWriteErr(w, err, http.StatusInternalServerError) } @@ -72,7 +67,7 @@ func (i *InstHandler) ReturnStatusHost(w http.ResponseWriter, r *http.Request) { } func (i *InstHandler) ReturnInstAllInfo(w http.ResponseWriter, r *http.Request) { - param := &InstInfoRequest{} + param := &ReturnInstAllData{} resp := ResponseGen[status.InstDataTypeHandler]("Inst Hardware Return") if err := HttpDecoder(r, param); err != nil { @@ -86,6 +81,7 @@ func (i *InstHandler) ReturnInstAllInfo(w http.ResponseWriter, r *http.Request) resp.ResponseWriteErr(w, err, http.StatusInternalServerError) return } + fmt.Println("data sending", reflect.TypeOf(dataHandle)) inst, err := status.InstDetailFactory(dataHandle, i.LibvirtInst) if err != nil { resp.ResponseWriteErr(w, err, http.StatusInternalServerError) @@ -112,7 +108,7 @@ func (i *InstHandler) ReturnAllUUIDs(w http.ResponseWriter, r *http.Request) { ////////////////////////////////////////////////////////////////// -func (i *InstHandler) GetAllDomainStates() ([]DomainStateResponse, error) { +func (i *InstHandler) GetAllDomainStates() ([]DomainState_init, error) { domains, err := i.LibvirtInst.ListAllDomains(0) if err != nil { return nil, err @@ -123,7 +119,7 @@ func (i *InstHandler) GetAllDomainStates() ([]DomainStateResponse, error) { } }() - var result []DomainStateResponse + var result []DomainState_init for _, domain := range domains { uuid, err := domain.GetUUIDString() if err != nil { @@ -133,7 +129,7 @@ func (i *InstHandler) GetAllDomainStates() ([]DomainStateResponse, error) { if err != nil { continue // 상태 조회 실패 시 건너뜀 } - result = append(result, DomainStateResponse{ + result = append(result, DomainState_init{ UUID: uuid, DomainState: state, }) @@ -151,7 +147,7 @@ func (i *InstHandler) ReturnAllDomainStates(w http.ResponseWriter, r *http.Reque } resp := struct { - Domains []DomainStateResponse `json:"domains"` + Domains []DomainState_init `json:"domains"` }{Domains: states} w.Header().Set("Content-Type", "application/json") diff --git a/api/status_model.go b/api/status_model.go deleted file mode 100644 index 21337a7..0000000 --- a/api/status_model.go +++ /dev/null @@ -1,32 +0,0 @@ -package api - -import ( - "github.com/easy-cloud-Knet/KWS_Core/vm/service/status" - "libvirt.org/go/libvirt" -) - -type DomainBootRequest struct { - UUID string `json:"UUID"` -} - -type DomainStatusRequest struct { - DataType status.DomainDataType `json:"dataType"` - UUID string `json:"UUID"` -} - -type HostStatusRequest struct { - HostDataType status.HostDataType `json:"host_dataType"` -} - -type InstInfoRequest struct { - InstDataType status.InstDataType `json:"dataType"` -} - -type UUIDListResponse struct { - UUIDs []string `json:"uuids"` -} - -type DomainStateResponse struct { - DomainState libvirt.DomainState `json:"currentState"` - UUID string `json:"UUID"` -} diff --git a/api/type.go b/api/type.go index 0a8db41..6cd6ab8 100755 --- a/api/type.go +++ b/api/type.go @@ -2,6 +2,8 @@ package api import ( domCon "github.com/easy-cloud-Knet/KWS_Core/DomCon" + "github.com/easy-cloud-Knet/KWS_Core/vm/service/status" + "github.com/easy-cloud-Knet/KWS_Core/vm/service/termination" "go.uber.org/zap" "libvirt.org/go/libvirt" ) @@ -12,6 +14,45 @@ type InstHandler struct { Logger *zap.Logger } +// InstHandler 는 + type InstHandle interface { LibvirtConnection() } + +//// income api Structures + +type DeleteDomain struct { + UUID string `json:"UUID"` + DeletionType termination.DomainDeleteType `json:"DeleteType"` +} +type ShutDownDomain struct { + UUID string `json:"UUID"` +} +type StartDomain struct { + UUID string `json:"UUID"` +} + +type ReturnDomainFromUUID struct { + DataType status.DomainDataType `json:"dataType"` + UUID string `json:"UUID"` +} + +// host +type ReturnHostFromStatus struct { + HostDataType status.HostDataType `json:"host_dataType"` +} + +type ReturnInstAllData struct { + InstDataType status.InstDataType `json:"dataType"` +} + +// ////////////////////// +type UUIDListResponse struct { + UUIDs []string `json:"uuids"` +} + +type DomainState_init struct { + DomainState libvirt.DomainState `json:"currentState"` + UUID string `json:"UUID"` +} diff --git a/api/utils.go b/api/utils.go index 610adbe..f85e844 100755 --- a/api/utils.go +++ b/api/utils.go @@ -76,8 +76,9 @@ func (br *BaseResponse[T]) ResponseWriteOK(w http.ResponseWriter, info *T) { func (i *InstHandler) domainConGetter()(*domCon.DomListControl, error){ + fmt.Println(i) if(i.DomainControl == nil){ - return nil, virerr.ErrorGen(virerr.InvalidParameter, fmt.Errorf("domainController not initialled yet")) + return nil, fmt.Errorf("domainController not initialled yet") } return i.DomainControl,nil } diff --git a/build/node_exporter/LICENSE b/build/node_exporter/LICENSE deleted file mode 100644 index 261eeb9..0000000 --- a/build/node_exporter/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/build/node_exporter/NOTICE b/build/node_exporter/NOTICE deleted file mode 100644 index 970a9b2..0000000 --- a/build/node_exporter/NOTICE +++ /dev/null @@ -1,17 +0,0 @@ -Configurable modular Prometheus exporter for various node metrics. -Copyright 2013-2015 The Prometheus Authors - -This product includes software developed at -SoundCloud Ltd. (http://soundcloud.com/). - -The following components are included in this product: - -wifi -https://github.com/mdlayher/wifi -Copyright 2016-2017 Matt Layher -Licensed under the MIT License - -netlink -https://github.com/mdlayher/netlink -Copyright 2016-2017 Matt Layher -Licensed under the MIT License diff --git a/build/node_exporter/node_exporter b/build/node_exporter/node_exporter deleted file mode 100755 index 97db22e..0000000 Binary files a/build/node_exporter/node_exporter and /dev/null differ diff --git a/build/node_exporter/node_exporter-1.9.1.linux-amd64/LICENSE b/build/node_exporter/node_exporter-1.9.1.linux-amd64/LICENSE deleted file mode 100644 index 261eeb9..0000000 --- a/build/node_exporter/node_exporter-1.9.1.linux-amd64/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/build/node_exporter/node_exporter-1.9.1.linux-amd64/NOTICE b/build/node_exporter/node_exporter-1.9.1.linux-amd64/NOTICE deleted file mode 100644 index 970a9b2..0000000 --- a/build/node_exporter/node_exporter-1.9.1.linux-amd64/NOTICE +++ /dev/null @@ -1,17 +0,0 @@ -Configurable modular Prometheus exporter for various node metrics. -Copyright 2013-2015 The Prometheus Authors - -This product includes software developed at -SoundCloud Ltd. (http://soundcloud.com/). - -The following components are included in this product: - -wifi -https://github.com/mdlayher/wifi -Copyright 2016-2017 Matt Layher -Licensed under the MIT License - -netlink -https://github.com/mdlayher/netlink -Copyright 2016-2017 Matt Layher -Licensed under the MIT License diff --git a/build/node_exporter/node_exporter-1.9.1.linux-amd64/node_exporter b/build/node_exporter/node_exporter-1.9.1.linux-amd64/node_exporter deleted file mode 100755 index 97db22e..0000000 Binary files a/build/node_exporter/node_exporter-1.9.1.linux-amd64/node_exporter and /dev/null differ diff --git a/error/Error.go b/error/Error.go index d9bf317..4f4aeb5 100755 --- a/error/Error.go +++ b/error/Error.go @@ -27,8 +27,6 @@ const ( DeletionDomainError VirError= "Error Deleting Domain" DomainShutdownError VirError= "failed in Deleting domain" - - SnapshotError VirError = "Error in Snapshot Operation" ) diff --git a/go.mod b/go.mod index 668b39d..5ee1f5a 100755 --- a/go.mod +++ b/go.mod @@ -1,8 +1,6 @@ module github.com/easy-cloud-Knet/KWS_Core -go 1.24.0 - -toolchain go1.24.10 +go 1.22.6 require ( gopkg.in/yaml.v3 v3.0.1 @@ -13,7 +11,6 @@ require ( github.com/google/uuid v1.6.0 github.com/shirou/gopsutil v3.21.11+incompatible go.uber.org/zap v1.27.0 - libvirt.org/libvirt-go-xml v7.4.0+incompatible ) require ( @@ -22,5 +19,5 @@ require ( github.com/tklauser/numcpus v0.8.0 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sys v0.38.0 // indirect + golang.org/x/sys v0.29.0 // indirect ) diff --git a/go.sum b/go.sum index 0981a6e..3d3dff3 100644 --- a/go.sum +++ b/go.sum @@ -23,13 +23,11 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8 go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= libvirt.org/go/libvirt v1.10006.0 h1:VzbLKReneWBIiplgOvZHxMiLLJ0HxAyp4MMPcYTHJjY= libvirt.org/go/libvirt v1.10006.0/go.mod h1:1WiFE8EjZfq+FCVog+rvr1yatKbKZ9FaFMZgEqxEJqQ= -libvirt.org/libvirt-go-xml v7.4.0+incompatible h1:NaCRjbtz//xuTZOp1nDHbe0eu5BQlhIy5PPuc09EWtU= -libvirt.org/libvirt-go-xml v7.4.0+incompatible/go.mod h1:FL+H1+hKNWDdkKQGGS4sGCZJ3pGWcjt6VbxZvPlQJkY= diff --git a/logger/Readme.md b/logger/Readme.md deleted file mode 100644 index aaff057..0000000 --- a/logger/Readme.md +++ /dev/null @@ -1,88 +0,0 @@ -## Logging guidelines (syslogger) - -Purpose -------- -All application logs must be emitted through the `syslogger` package (zap-based). Do not use `fmt.Println`, `fmt.Printf`, or the standard `log` package for runtime/application logs. - -High level rules ----------------- -- Use structured logging (zap) and prefer typed fields over printf-style messages. -- Inject `*zap.Logger` into high-level components (for example, `InstHandler`) instead of using global `fmt`/`log` calls. -- Keep the logging depth limited: only the API/handler layer and service layer should produce informational logs. Lower-level libraries should return errors and let callers decide how to log them. -- Avoid logging raw pointers or whole internal structs. Log identifiers (UUID, request_id, name) or use `zap.Any` only when necessary. - -Log levels ----------- -- `Debug`: development-only details and verbose internal state. -- `Info`: normal operational events (resource created, request accepted). -- `Warn`: unexpected but recoverable situations. -- `Error`: errors that affect the operation or request handling. Include `zap.Error(err)`. -- `Fatal` / `Panic`: only for unrecoverable bootstrap failures. - -Standard fields ---------------- -When applicable, include these structured fields to make logs searchable and consistent: - -- `component` — short name of module (e.g. `vm.creator`). -- `uuid` / `request_id` — tracing identifiers. -- `error` — use `zap.Error(err)`. -- `user` / `tenant` — if multi-tenant context exists. - -Examples --------- -Preferred (structured): - -```go -logger.Info("vm created", - zap.String("uuid", uuid), - zap.String("component", "vm.creator"), -) - -logger.Error("failed to create vm", - zap.String("uuid", uuid), - zap.Error(err), -) -``` - -If you need printf-style messages for quick debugging, use the sugared logger sparingly: - -```go -logger.Sugar().Infof("vm created: uuid=%s", uuid) -``` - -Error handling --------------- -- Do not swallow errors. Return errors to caller layers and log them once at a boundary (typically in handlers/API layer) with context. -- When logging errors, add human-friendly prefix/context to indicate where the error occurred. - -Do not ------- -- Use `fmt.Println` / `fmt.Printf` for application logs. -- Print raw pointer addresses or entire internal objects. - -Suggested enforcement ---------------------- -- Add a quick code review checklist item to reject PRs that introduce `fmt.Println` or `log.Print*` in non-test code. -- Consider a static check (grep) in CI to detect stray `fmt.Println` usages. - -Notes about this document ------------------------- -- This file documents recommended logging style and patterns for the codebase. It is intentionally short — if you want, we can add a small example `logger.New()` wrapper and example of how to inject the logger into `InstHandler`. -### How to write log in this project. - -All log emmiting from the project should be taken by syslogger(this file. - via zap.logger) - -*zap.logger should be embedded to Insthandler and depth of logging should not passed more dipper than service layer. -which means, we don't print non-informational data for every instruction. - -info.log, info.warn, info.error will be only that we concern. -Info.panic only occures when there's critical error from bootstrap. - - -All error should be passed with err argument and must be reported at the end of the api handler. -For debugging we suggest adding prefixing comprehansible information of where the error occured. - -```bash -e.g) Error: From createvm: instanceCon: CheckInstancePersistance: Instance with the same name already exists. -``` - diff --git a/logger/log.go b/logger/log.go index 9f3b47d..28ba8de 100755 --- a/logger/log.go +++ b/logger/log.go @@ -25,7 +25,7 @@ func InitialLogger() *zap.Logger{ config:= zap.Config{ Level: zap.NewAtomicLevelAt(zapcore.DebugLevel), - Development: true, + Development: true, DisableCaller: true, DisableStacktrace: true, Encoding: "json", @@ -39,29 +39,19 @@ func InitialLogger() *zap.Logger{ } -type responseWriter struct { - http.ResponseWriter - statusCode int -} -func (rw *responseWriter) WriteHeader(code int) { - rw.statusCode = code - rw.ResponseWriter.WriteHeader(code) -} func LoggerMiddleware(next http.Handler, logger *zap.Logger) http.Handler{ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){ start:= time.Now() - wrapped := &responseWriter{ResponseWriter: w, statusCode: http.StatusOK} - next.ServeHTTP(wrapped, r) + next.ServeHTTP(w,r) elapsed := time.Since(start) - logger.Info("http response sent", - zap.String("method", r.Method), - zap.String("path", r.URL.Path), - zap.Int("status", wrapped.statusCode), - zap.Duration("duration", elapsed), - ) + logger.Info("http response sent",zap.Duration("time elapsed", elapsed)) }) } + + + + diff --git a/main.go b/main.go index 6b29ddb..afb9d57 100755 --- a/main.go +++ b/main.go @@ -23,10 +23,10 @@ func main() { } libvirtInst.LibvirtConnection() - libvirtInst.DomainControl.DomainListStatus.UpdateCPUTotal() libvirtInst.DomainControl.RetrieveAllDomain(libvirtInst.LibvirtInst, logger) - go server.InitServer(8080, &libvirtInst, logger) + go server.InitServer(8080, &libvirtInst, *logger) + defer func() { logger.Info("Shutting down gracefully...") // 종료 시 로깅 logger.Sync() diff --git a/server/server.go b/server/server.go index 5a7d951..f1e8a2a 100755 --- a/server/server.go +++ b/server/server.go @@ -1,6 +1,7 @@ package server import ( + "log" "net/http" "strconv" @@ -9,11 +10,10 @@ import ( "go.uber.org/zap" ) -func InitServer(portNum int, libvirtInst *api.InstHandler, logger *zap.Logger) { +func InitServer(portNum int, libvirtInst *api.InstHandler, logger zap.Logger) { logger.Sugar().Infof("Starting server on %d", portNum) mux := http.NewServeMux() - mux.HandleFunc("POST /BOOTVM", libvirtInst.BootVM) //post mux.HandleFunc("POST /createVM", libvirtInst.CreateVMFromBase) //post mux.HandleFunc("GET /getStatusUUID", libvirtInst.ReturnStatusUUID) //Get mux.HandleFunc("POST /forceShutDownUUID", libvirtInst.ForceShutDownVM) //POST @@ -23,16 +23,8 @@ func InitServer(portNum int, libvirtInst *api.InstHandler, logger *zap.Logger) { mux.HandleFunc("GET /getAllUUIDs", libvirtInst.ReturnAllUUIDs) //Get mux.HandleFunc("GET /getAll-uuidstatusList", libvirtInst.ReturnAllDomainStates) - // Snapshot operations - mux.HandleFunc("POST /CreateSnapshot", libvirtInst.CreateSnapshot) - mux.HandleFunc("GET /ListSnapshots", libvirtInst.ListSnapshots) - mux.HandleFunc("POST /RevertSnapshot", libvirtInst.RevertSnapshot) - mux.HandleFunc("POST /DeleteSnapshot", libvirtInst.DeleteSnapshot) + sysloggerHttp := syslogger.LoggerMiddleware(mux, &logger) - sysloggerHttp := syslogger.LoggerMiddleware(mux, logger) - - if err := http.ListenAndServe(":"+strconv.Itoa(portNum), sysloggerHttp); err != nil { - logger.Fatal("server failed", zap.Error(err)) - } + log.Fatal(http.ListenAndServe(":"+strconv.Itoa(portNum), sysloggerHttp)) } diff --git a/vm/parsor/XML_Parsor.go b/vm/parsor/XML_Parsor.go index f2fcfb3..6b5c63c 100755 --- a/vm/parsor/XML_Parsor.go +++ b/vm/parsor/XML_Parsor.go @@ -5,6 +5,7 @@ import ( ) func (XP *VM_CREATE_XML) XML_Parsor(spec *VM_Init_Info) error { + fmt.Println(spec.SDNUUID) *XP = VM_CREATE_XML{ Type: "kvm", Name: spec.DomName, @@ -92,7 +93,6 @@ func (XP *VM_CREATE_XML) XML_Parsor(spec *VM_Init_Info) error { InterfaceID: spec.SDNUUID, }, }, - MTU: MTU{ Size: 1450}, // MTU 설정 추가 Model: InterfaceModel{ Type: "virtio", }, diff --git a/vm/parsor/cloud-init/userConf.go b/vm/parsor/cloud-init/userConf.go index f3ffb8f..ca1334c 100755 --- a/vm/parsor/cloud-init/userConf.go +++ b/vm/parsor/cloud-init/userConf.go @@ -64,37 +64,16 @@ func (u *User_data_yaml) ParseData(param *parsor.VM_Init_Info) error { }) } File_Appendor := u.configNetworkIP(param.NetConf.Ips) - appending,err:= u.fetchos() - if err!=nil{ - _ = err - } - File_Appendor = append(File_Appendor,appending... ) + File_Appendor = u.newWaitDisable(File_Appendor) u.Users = Users_Detail u.Write_files = File_Appendor u.configNetworkCommand() u.configQEMU() u.configSsh() - return nil } -func (u *User_data_yaml) fetchos() ([]User_write_file,error){ - var fetchFile []User_write_file - - data, err := os.ReadFile("/var/lib/kws/baseimg/fetchos") - if err != nil { - return fetchFile,fmt.Errorf("fetchos parsing error, ingnorable but needs report%v",err) - } - - fetchFile= append(fetchFile, User_write_file{ - Path: "/etc/profile.d/99-my-motd.sh", - Permissions: "0644", - Content: string(data), - }) - return fetchFile,nil -} - func (u *User_data_yaml) configNetworkIP(ips []string) []User_write_file { var File_Appendor []User_write_file @@ -113,7 +92,16 @@ func (u *User_data_yaml) configNetworkIP(ips []string) []User_write_file { } +func (u *User_data_yaml) newWaitDisable(File_Appendor []User_write_file) []User_write_file { + File_Appendor = append(File_Appendor, User_write_file{ + Path: "/etc/systemd/system/systemd-networkd-wait-online.service.d/override.conf", + Permissions: "0644", + Content: fmt.Sprintf("[Service]\nExecStart=\nExecStart=/usr/bin/true\n"), + }) + + return File_Appendor +} func (u *User_data_yaml) configSsh(){ u.Runcmd = append(u.Runcmd, "sed -i 's/PasswordAuthentication no/PasswordAuthentication yes/g' /etc/ssh/sshd_config.d/60-cloudimg-settings.conf") diff --git a/vm/parsor/type.go b/vm/parsor/type.go index d75893c..ed44706 100755 --- a/vm/parsor/type.go +++ b/vm/parsor/type.go @@ -30,7 +30,6 @@ type User_info_VM struct { type HardwareInfo struct { CPU int `json:"cpu"` Memory int `json:"memory"` - Disk int `json:"disk"` } // gonna replace fields in VM_Init_Info @@ -153,12 +152,7 @@ type Interface struct { Virtualport VirPort `xml:"virtualport"` Model InterfaceModel `xml:"model"` MacAddress MacAddress `xml:"mac"` - MTU MTU `xml:"mtu"` } -type MTU struct { - Size int `xml:"size,attr"` -} - type VirPort struct { Type string `xml:"type,attr"` Parameter Parameter `xml:"parameters"` diff --git a/vm/service/creation/common.go b/vm/service/creation/common.go index 41ded9f..9adda9b 100755 --- a/vm/service/creation/common.go +++ b/vm/service/creation/common.go @@ -9,14 +9,14 @@ import ( ) -func (DB localConfigurer)CreateDiskImage(dirPath string, diskSize int) error { +func (DB localConfigurer)CreateDiskImage(dirPath string) error { baseImage := fmt.Sprintf("/var/lib/kws/baseimg/%s", DB.VMDescription.OS) targetImage := filepath.Join(dirPath, fmt.Sprintf("%s.qcow2", DB.VMDescription.UUID)) qemuImgCmd := exec.Command("qemu-img", "create", "-b", baseImage, "-f", "qcow2", "-F", "qcow2", - targetImage, fmt.Sprintf("%dG", diskSize), // 10G + targetImage, "15G", ) if err := qemuImgCmd.Run(); err != nil { errorDescription := fmt.Errorf("generating Disk image error, may have duplicdated uuid or lack of HD capacity %s, %v", dirPath, err) diff --git a/vm/service/creation/local_domain.go b/vm/service/creation/local_domain.go index 912f15b..76deae6 100755 --- a/vm/service/creation/local_domain.go +++ b/vm/service/creation/local_domain.go @@ -51,6 +51,7 @@ func (DCB *LocalCreator) CreateVM()(*domCon.Domain,error){ } domain,err :=CreateDomainWithXML(DCB.libvirtInst,output) + fmt.Println(string(output)) if err!=nil{ errDesc := virerr.ErrorGen(virerr.DomainGenerationError, fmt.Errorf("in domain-Creator, error occured from creating with libvirt: %w", err)) DCB.logger.Error(errDesc.Error()) @@ -95,7 +96,7 @@ func (DB localConfigurer) Generate(LibvirtInst *libvirt.Connect, logger *zap.Log } logger.Info("generating configuration file successfully done", zap.String("filePath", dirPath)) - if err := DB.CreateDiskImage(dirPath, DB.VMDescription.HardwardInfo.Disk); err != nil { + if err := DB.CreateDiskImage(dirPath); err != nil { errorEncapsed := virerr.ErrorJoin(err, fmt.Errorf("in domain-parsor,")) logger.Error(errorEncapsed.Error()) return errorEncapsed diff --git a/vm/service/snapshot/operations.go b/vm/service/snapshot/operations.go deleted file mode 100644 index 5068da7..0000000 --- a/vm/service/snapshot/operations.go +++ /dev/null @@ -1,125 +0,0 @@ -package snapshot - -import ( - "fmt" - - domCon "github.com/easy-cloud-Knet/KWS_Core/DomCon" - virerr "github.com/easy-cloud-Knet/KWS_Core/error" - "libvirt.org/go/libvirt" -) - -// CreateSnapshot creates a libvirt snapshot and records basic metadata. -func CreateSnapshot(domain *domCon.Domain, name string) (string, error) { - if domain == nil || domain.Domain == nil { - return "", virerr.ErrorGen(virerr.InvalidParameter, fmt.Errorf("nil domain")) - } - - snapXML := fmt.Sprintf(`%ssnapshot created by KWS`, name) - - snap, err := domain.Domain.CreateSnapshotXML(snapXML, 0) - if err != nil { - return "", virerr.ErrorGen(virerr.SnapshotError, fmt.Errorf("failed to create snapshot: %w", err)) - } - defer snap.Free() - - snapName, err := snap.GetName() - if err != nil { - return "", virerr.ErrorGen(virerr.SnapshotError, fmt.Errorf("snapshot created but failed to read name: %w", err)) - } - - return snapName, nil -} - -// ListSnapshots lists snapshot names for the domain. -func ListSnapshots(domain *domCon.Domain) ([]string, error) { - if domain == nil || domain.Domain == nil { - return nil, virerr.ErrorGen(virerr.InvalidParameter, fmt.Errorf("nil domain")) - } - - snaps, err := domain.Domain.ListAllSnapshots(0) - if err != nil { - return nil, virerr.ErrorGen(virerr.SnapshotError, fmt.Errorf("failed to list snapshots: %w", err)) - } - - names := make([]string, 0, len(snaps)) - for _, s := range snaps { - n, err := s.GetName() - if err == nil { - names = append(names, n) - } - s.Free() - } - - return names, nil -} - -// RevertToSnapshot reverts the domain to the given snapshot name. -func RevertToSnapshot(domain *domCon.Domain, snapName string) error { - if domain == nil || domain.Domain == nil { - return virerr.ErrorGen(virerr.InvalidParameter, fmt.Errorf("nil domain")) - } - - snaps, err := domain.Domain.ListAllSnapshots(0) - if err != nil { - return virerr.ErrorGen(virerr.SnapshotError, fmt.Errorf("failed to list snapshots: %w", err)) - } - defer func() { - for _, s := range snaps { - s.Free() - } - }() - - var target *libvirt.DomainSnapshot - for i := range snaps { - n, err := snaps[i].GetName() - if err != nil { - continue - } - if n == snapName { - target = &snaps[i] - break - } - } - - if target == nil { - return virerr.ErrorGen(virerr.SnapshotError, fmt.Errorf("snapshot %s not found", snapName)) - } - - if err := target.RevertToSnapshot(0); err != nil { - return virerr.ErrorGen(virerr.SnapshotError, fmt.Errorf("failed to revert to snapshot %s: %w", snapName, err)) - } - - return nil -} - -// DeleteSnapshot deletes a snapshot by name. -func DeleteSnapshot(domain *domCon.Domain, snapName string) error { - if domain == nil || domain.Domain == nil { - return virerr.ErrorGen(virerr.InvalidParameter, fmt.Errorf("nil domain")) - } - - snaps, err := domain.Domain.ListAllSnapshots(0) - if err != nil { - return virerr.ErrorGen(virerr.SnapshotError, fmt.Errorf("failed to list snapshots: %w", err)) - } - defer func() { - for _, s := range snaps { - s.Free() - } - }() - - for _, s := range snaps { - n, err := s.GetName() - if err != nil { - continue - } - if n == snapName { - if err := s.Delete(0); err != nil { - return virerr.ErrorGen(virerr.SnapshotError, fmt.Errorf("failed to delete snapshot %s: %w", snapName, err)) - } - return nil - } - } - - return virerr.ErrorGen(virerr.SnapshotError, fmt.Errorf("snapshot %s not found", snapName)) -} diff --git a/vm/service/status/Status.go b/vm/service/status/Status.go index e628bb7..48be9d6 100755 --- a/vm/service/status/Status.go +++ b/vm/service/status/Status.go @@ -2,7 +2,6 @@ package status import ( domCon "github.com/easy-cloud-Knet/KWS_Core/DomCon" - domStatus "github.com/easy-cloud-Knet/KWS_Core/DomCon/domain_status" "libvirt.org/go/libvirt" ) @@ -11,7 +10,7 @@ type HostDetail struct { } type HostDataTypeHandler interface { - GetHostInfo(*domStatus.DomainListStatus) error + GetHostInfo() error } type HostDataType uint @@ -29,7 +28,6 @@ type HostCpuInfo struct { System float64 `json:"system_time"` Idle float64 `json:"idle_time"` Usage float64 `json:"usage_percent"` - Desc *domStatus.VCPUStatus `json:"vcpu_status"` } type HostMemoryInfo struct { @@ -38,8 +36,6 @@ type HostMemoryInfo struct { Available uint64 `json:"available_gb"` UsedPercent float64 `json:"used_percent"` ReservedMemory uint64 `json:"reservedmem"` - Desc *domStatus.VCPUStatus `json:"vcpu_status"` - } type HostDiskInfo struct { @@ -47,8 +43,6 @@ type HostDiskInfo struct { Used uint64 `json:"used_gb"` Free uint64 `json:"free_gb"` UsedPercent float64 `json:"used_percent"` - Desc *domStatus.VCPUStatus `json:"vcpu_status"` - } type HostSystemInfo struct { diff --git a/vm/service/status/domain_status.go b/vm/service/status/domain_status.go index 278c11f..634bc45 100755 --- a/vm/service/status/domain_status.go +++ b/vm/service/status/domain_status.go @@ -2,7 +2,7 @@ package status import ( "errors" - "fmt" + "log" domCon "github.com/easy-cloud-Knet/KWS_Core/DomCon" virerr "github.com/easy-cloud-Knet/KWS_Core/error" @@ -44,7 +44,8 @@ func (DP *DomainState) GetInfo(domain *domCon.Domain) error { DP.UUID = string(uuidParsed.String()) userInfo, err := domain.Domain.GetGuestInfo(libvirt.DOMAIN_GUEST_INFO_USERS, 0) if err != nil { - return virerr.ErrorGen(virerr.DomainStatusError, fmt.Errorf("error retreving guest info: %w", err)) + log.Println("error retreving guest info") + return err } DP.Users = userInfo.Users return nil diff --git a/vm/service/status/host_status.go b/vm/service/status/host_status.go index 73d10a7..c1a5f0a 100755 --- a/vm/service/status/host_status.go +++ b/vm/service/status/host_status.go @@ -3,9 +3,9 @@ package status import ( "errors" "fmt" + "log" "time" - domStatus "github.com/easy-cloud-Knet/KWS_Core/DomCon/domain_status" virerr "github.com/easy-cloud-Knet/KWS_Core/error" "github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/disk" @@ -13,14 +13,16 @@ import ( "github.com/shirou/gopsutil/mem" ) -func (CI *HostCpuInfo) GetHostInfo(status *domStatus.DomainListStatus) error { +func (CI *HostCpuInfo) GetHostInfo() error { t, err := cpu.Times(false) //time if err != nil { + log.Println(err) return virerr.ErrorGen(virerr.HostStatusError, err) } p, err := cpu.Percent(time.Second, false) if err != nil { + log.Println(err) return virerr.ErrorGen(virerr.HostStatusError, err) } @@ -30,16 +32,13 @@ func (CI *HostCpuInfo) GetHostInfo(status *domStatus.DomainListStatus) error { } CI.Usage = p[0] - CI.Desc.EmitStatus(status) - - - return nil } -func (MI *HostMemoryInfo) GetHostInfo(status *domStatus.DomainListStatus) error { +func (MI *HostMemoryInfo) GetHostInfo() error { v, err := mem.VirtualMemory() if err != nil { + log.Println(err) return virerr.ErrorGen(virerr.HostStatusError, err) } @@ -52,9 +51,10 @@ func (MI *HostMemoryInfo) GetHostInfo(status *domStatus.DomainListStatus) error return nil } -func (HDI *HostDiskInfo) GetHostInfo(status *domStatus.DomainListStatus) error { +func (HDI *HostDiskInfo) GetHostInfo() error { d, err := disk.Usage("/") if err != nil { + log.Println(err) return virerr.ErrorGen(virerr.HostStatusError, err) } @@ -67,16 +67,16 @@ func (HDI *HostDiskInfo) GetHostInfo(status *domStatus.DomainListStatus) error { return nil } -func (SI *HostGeneralInfo) GetHostInfo(status *domStatus.DomainListStatus) error { - err:=SI.CPU.GetHostInfo(status) +func (SI *HostGeneralInfo) GetHostInfo() error { + err:=SI.CPU.GetHostInfo() if err!=nil{ return virerr.ErrorGen(virerr.HostStatusError, fmt.Errorf("general Status:error retreving host Status %w",err)) } - err=SI.Disk.GetHostInfo(status) + err=SI.Disk.GetHostInfo() if err!=nil{ return virerr.ErrorGen(virerr.HostStatusError, fmt.Errorf("general Status:error retreving host Status %w",err)) } - err=SI.Memory.GetHostInfo(status) + err=SI.Memory.GetHostInfo() if err!=nil{ return virerr.ErrorGen(virerr.HostStatusError, fmt.Errorf("general Status:error retreving host Status %w",err)) } @@ -88,15 +88,17 @@ func (SI *HostGeneralInfo) GetHostInfo(status *domStatus.DomainListStatus) error -func (HSI *HostSystemInfo) GetHostInfo(status *domStatus.DomainListStatus) error { +func (HSI *HostSystemInfo) GetHostInfo() error { u, err := host.Uptime() if err != nil { + log.Println(err) return virerr.ErrorGen(virerr.HostStatusError, err) } b, err := host.BootTime() if err != nil { + log.Println(err) return virerr.ErrorGen(virerr.HostStatusError, err) } @@ -119,22 +121,14 @@ func (HSI *HostSystemInfo) GetHostInfo(status *domStatus.DomainListStatus) error } func HostDataTypeRouter(types HostDataType) (HostDataTypeHandler, error) { - // implemeantation of factory pattern - // can be extened as DI pattern if there are more complex dependencies switch types { case CpuInfo: - return &HostCpuInfo{ - Desc: &domStatus.VCPUStatus{}, - }, nil + return &HostCpuInfo{}, nil case MemInfo: - return &HostMemoryInfo{ - Desc: &domStatus.VCPUStatus{},// --- IGNORE --- - }, nil + return &HostMemoryInfo{}, nil case DiskInfoHi: - return &HostDiskInfo{ - Desc: &domStatus.VCPUStatus{},// --- IGNORE --- - }, nil + return &HostDiskInfo{}, nil case SystemInfoHi: return &HostSystemInfo{}, nil case GeneralInfo: @@ -146,8 +140,9 @@ func HostDataTypeRouter(types HostDataType) (HostDataTypeHandler, error) { -func HostInfoHandler(handler HostDataTypeHandler, status *domStatus.DomainListStatus) (*HostDetail, error) { - if err := handler.GetHostInfo(status); err != nil { +func HostDetailFactory(handler HostDataTypeHandler) (*HostDetail, error) { + if err := handler.GetHostInfo(); err != nil { + fmt.Println(err) return nil, err } return &HostDetail{ diff --git a/vm/service/status/instStatus.go b/vm/service/status/instStatus.go index ddccba4..425ab3c 100644 --- a/vm/service/status/instStatus.go +++ b/vm/service/status/instStatus.go @@ -2,8 +2,8 @@ package status import ( "fmt" + "log" - virerr "github.com/easy-cloud-Knet/KWS_Core/error" "libvirt.org/go/libvirt" ) @@ -11,7 +11,7 @@ func (AII *AllInstInfo) GetAllinstInfo(LibvirtInst *libvirt.Connect) error { domains, err := LibvirtInst.ListAllDomains(0) //alldomain if err != nil { - return virerr.ErrorGen(virerr.HostStatusError, fmt.Errorf("failed to list all domains: %w", err)) + log.Println(err) } var totalMaxMem uint64 @@ -19,6 +19,7 @@ func (AII *AllInstInfo) GetAllinstInfo(LibvirtInst *libvirt.Connect) error { for _, dom := range domains { data, err := dom.GetInfo() if err != nil { + log.Println(err) dom.Free() continue } @@ -38,11 +39,12 @@ func InstDataTypeRouter(types InstDataType) (InstDataTypeHandler, error) { return &AllInstInfo{}, nil } - return nil, virerr.ErrorGen(virerr.InvalidParameter, fmt.Errorf("unsupported type")) + return nil, fmt.Errorf("unsupported type") } func InstDetailFactory(handler InstDataTypeHandler, LibvirtInst *libvirt.Connect) (*InstDetail, error) { if err := handler.GetAllinstInfo(LibvirtInst); err != nil { + fmt.Println(err) return nil, err } return &InstDetail{ diff --git a/vm/service/termination/delete_domain.go b/vm/service/termination/delete_domain.go index f1af15a..9d6a619 100755 --- a/vm/service/termination/delete_domain.go +++ b/vm/service/termination/delete_domain.go @@ -7,7 +7,6 @@ import ( "path/filepath" domCon "github.com/easy-cloud-Knet/KWS_Core/DomCon" - virerr "github.com/easy-cloud-Knet/KWS_Core/error" "libvirt.org/go/libvirt" ) @@ -25,13 +24,13 @@ func (DD *DomainDeleter) DeleteDomain() (*libvirt.Domain,error){ isRunning, _ := dom.Domain.IsActive() if isRunning && DD.DeletionType == SoftDelete { - - return nil,virerr.ErrorGen(virerr.DeletionDomainError, fmt.Errorf("domain is running, cannot softDelete running domain")) + + return nil,fmt.Errorf("domain Is Running %w, cannot softDelete running Domain", nil) } else if isRunning && DD.DeletionType == HardDelete { DomainTerminator := &DomainTerminator{domain: dom} _,err := DomainTerminator.TerminateDomain() if err != nil { - return nil,virerr.ErrorGen(virerr.DeletionDomainError, fmt.Errorf("failed deleting domain in libvirt instance: %w", err)) + return nil,fmt.Errorf("%w, failed deleting Domain in libvirt Instance, ", err) } } basicFilePath := "/var/lib/kws/" @@ -41,13 +40,15 @@ func (DD *DomainDeleter) DeleteDomain() (*libvirt.Domain,error){ deleteCmd.Stderr = os.Stderr if err := deleteCmd.Run(); err != nil { - return nil,virerr.ErrorGen(virerr.DeletionDomainError, fmt.Errorf("failed deleting files in %s: %w", FilePath, err)) + return nil,fmt.Errorf("%w failed deleteing files in %s", err, FilePath) } if err := dom.Domain.Undefine(); err != nil { - return nil,virerr.ErrorGen(virerr.DeletionDomainError, fmt.Errorf("failed deleting domain in libvirt instance: %w", err)) + return nil,fmt.Errorf("%w, failed deleting Domain in libvirt Instance, ", err) } - + return dom.Domain,nil } + + diff --git a/vm/service/termination/terminate_domain.go b/vm/service/termination/terminate_domain.go index 4ef8b6c..fdd8f2c 100755 --- a/vm/service/termination/terminate_domain.go +++ b/vm/service/termination/terminate_domain.go @@ -23,6 +23,7 @@ func (DD *DomainTerminator) TerminateDomain() (*libvirt.Domain, error) { } if err := dom.Domain.Destroy(); err != nil { + fmt.Println("error occured while deleting Domain") return nil,virerr.ErrorGen(virerr.DomainShutdownError, fmt.Errorf("error shutting down domain, from libvirt. %w, %v", err,DD)) }