diff --git a/DomCon/domain_list.go b/DomCon/domain_list.go index 5302155..f5fcbef 100755 --- a/DomCon/domain_list.go +++ b/DomCon/domain_list.go @@ -146,7 +146,7 @@ func (DC *DomListControl) RetrieveAllDomain(logger *zap.Logger) error { return err } - logger.Info("retreiving intital vm", zap.Int("number", len(DC.DomainList))) + logger.Info("retrieving initial vm", zap.Int("number", len(DC.DomainList))) return nil } diff --git a/api/Control/Control.go b/api/Control/Control.go index 9aedae9..d2e1b3b 100644 --- a/api/Control/Control.go +++ b/api/Control/Control.go @@ -23,7 +23,7 @@ func (h *Handler) ForceShutDownVM(w http.ResponseWriter, r *http.Request) { dom, err := h.DomainControl.GetDomain(param.UUID) if err != nil { - ERR := virerr.ErrorJoin(err, fmt.Errorf("error shutting down vm, retreving Get domin error ")) + ERR := virerr.ErrorJoin(err, fmt.Errorf("error shutting down vm, retrieving domain")) resp.ResponseWriteErr(w, ERR, http.StatusInternalServerError) h.Logger.Error("failed to get domain for forceShutdown", zap.String("uuid", param.UUID), zap.Error(ERR)) return @@ -57,7 +57,7 @@ func (h *Handler) DeleteVM(w http.ResponseWriter, r *http.Request) { domain, err := h.DomainControl.GetDomain(param.UUID) if err != nil { - ERR := virerr.ErrorJoin(err, fmt.Errorf("error deleting vm, retreving Get domin error ")) + ERR := virerr.ErrorJoin(err, fmt.Errorf("error deleting vm, retrieving domain")) resp.ResponseWriteErr(w, ERR, http.StatusInternalServerError) h.Logger.Error("failed to get domain for deleteVM", zap.String("uuid", param.UUID), zap.Error(ERR)) return diff --git a/api/Create/Create.go b/api/Create/Create.go index 46fb6d1..094462e 100755 --- a/api/Create/Create.go +++ b/api/Create/Create.go @@ -35,11 +35,9 @@ func (h *Handler) BootVM(w http.ResponseWriter, r *http.Request) { return } - err := DomainExisting.Domain.Create() - if err != nil { - newErr := virerr.ErrorGen(virerr.DomainGenerationError, fmt.Errorf(" %w error while booting domain, from BootVM", err)) - h.Logger.Error("error from booting vm", zap.Error(newErr)) - resp.ResponseWriteErr(w, newErr, http.StatusInternalServerError) + if err := creation.BootExistingVM(DomainExisting); err != nil { + h.Logger.Error("error booting vm", zap.Error(err)) + resp.ResponseWriteErr(w, err, http.StatusInternalServerError) return } diff --git a/api/Create/model.go b/api/Create/model.go index 18a3c52..c35619c 100644 --- a/api/Create/model.go +++ b/api/Create/model.go @@ -9,7 +9,7 @@ type CreateVMRequest struct { DomName string `json:"domName"` UUID string `json:"uuid"` OS string `json:"os"` - HardwardInfo vmtypes.HardwareInfo `json:"HWInfo"` + HardwareInfo vmtypes.HardwareInfo `json:"HWInfo"` NetConf network.NetDefine `json:"network"` Users []vmtypes.User_info_VM `json:"users"` SDNUUID string `json:"sdnUUID"` @@ -21,7 +21,7 @@ func (r *CreateVMRequest) toVMInitInfo() *vmtypes.VM_Init_Info { DomName: r.DomName, UUID: r.UUID, OS: r.OS, - HardwardInfo: r.HardwardInfo, + HardwareInfo: r.HardwareInfo, NetConf: r.NetConf, Users: r.Users, SDNUUID: r.SDNUUID, diff --git a/api/Status/Status.go b/api/Status/Status.go index 960b120..e35fc6d 100644 --- a/api/Status/Status.go +++ b/api/Status/Status.go @@ -18,7 +18,7 @@ func (h *Handler) ReturnStatusUUID(w http.ResponseWriter, r *http.Request) { resp.ResponseWriteErr(w, err, http.StatusBadRequest) return } - h.Logger.Info("retreving domain status", zap.String("uuid", param.UUID)) + h.Logger.Info("retrieving domain status", zap.String("uuid", param.UUID)) outputStruct, err := svcstatus.DataTypeRouter(param.DataType) if err != nil { @@ -99,41 +99,12 @@ func (h *Handler) ReturnAllUUIDs(w http.ResponseWriter, r *http.Request) { resp.ResponseWriteOK(w, &respData) } -func (h *Handler) getAllDomainStates() ([]DomainStateResponse, error) { - domains, err := h.LibvirtConn.ListAllDomains(0) - if err != nil { - return nil, err - } - defer func() { - for _, d := range domains { - d.Free() - } - }() - - var result []DomainStateResponse - for _, d := range domains { - uuid, err := d.GetUUIDString() - if err != nil { - continue - } - state, _, err := d.GetState() - if err != nil { - continue - } - result = append(result, DomainStateResponse{ - UUID: uuid, - DomainState: state, - }) - } - return result, nil -} - func (h *Handler) ReturnAllDomainStates(w http.ResponseWriter, r *http.Request) { h.Logger.Info("ReturnAllDomainStates handler entered") - resp := httputil.ResponseGen[[]DomainStateResponse]("Get All Domain States") + resp := httputil.ResponseGen[[]svcstatus.DomainStateInfo]("Get All Domain States") - states, err := h.getAllDomainStates() + states, err := svcstatus.ListAllDomainStates(h.LibvirtConn) if err != nil { resp.ResponseWriteErr(w, err, http.StatusInternalServerError) return diff --git a/api/Status/model.go b/api/Status/model.go index ce2e1dd..514a5aa 100644 --- a/api/Status/model.go +++ b/api/Status/model.go @@ -2,7 +2,6 @@ package status import ( svcstatus "github.com/easy-cloud-Knet/KWS_Core/services/status" - "libvirt.org/go/libvirt" ) type DomainStatusRequest struct { @@ -22,7 +21,3 @@ type UUIDListResponse struct { UUIDs []string `json:"uuids"` } -type DomainStateResponse struct { - DomainState libvirt.DomainState `json:"currentState"` - UUID string `json:"UUID"` -} diff --git a/api/Status/status_test.go b/api/Status/status_test.go index db90d75..5c52bc6 100644 --- a/api/Status/status_test.go +++ b/api/Status/status_test.go @@ -2,6 +2,7 @@ package status import ( "bytes" + "fmt" "net/http" "net/http/httptest" "testing" @@ -12,6 +13,7 @@ import ( svcstatus "github.com/easy-cloud-Knet/KWS_Core/services/status" testutil "github.com/easy-cloud-Knet/KWS_Core/test" "go.uber.org/zap" + "libvirt.org/go/libvirt" ) // ─── mock ─────────────────────────────────────────────────────────────────── @@ -175,3 +177,46 @@ func TestReturnAllUUIDs_WithUUIDs(t *testing.T) { t.Errorf("expected %d, got %d", http.StatusOK, w.Code) } } + +// ─── ReturnAllDomainStates ─────────────────────────────────────────────────── + +type mockConnect struct { + domains []libvirt.Domain + err error +} + +func (m *mockConnect) ListAllDomains(_ libvirt.ConnectListAllDomainsFlags) ([]libvirt.Domain, error) { + return m.domains, m.err +} + +func TestReturnAllDomainStates_ConnectError(t *testing.T) { + h := &Handler{ + LibvirtConn: &mockConnect{err: fmt.Errorf("connect error")}, + DomainControl: &mockDomainController{}, + Logger: zap.NewNop(), + } + r := httptest.NewRequest(http.MethodGet, "/getAll-uuidstatusList", nil) + w := httptest.NewRecorder() + + h.ReturnAllDomainStates(w, r) + + if w.Code != http.StatusInternalServerError { + t.Errorf("expected %d, got %d", http.StatusInternalServerError, w.Code) + } +} + +func TestReturnAllDomainStates_Empty(t *testing.T) { + h := &Handler{ + LibvirtConn: &mockConnect{domains: []libvirt.Domain{}}, + DomainControl: &mockDomainController{}, + Logger: zap.NewNop(), + } + r := httptest.NewRequest(http.MethodGet, "/getAll-uuidstatusList", nil) + w := httptest.NewRecorder() + + h.ReturnAllDomainStates(w, r) + + if w.Code != http.StatusOK { + t.Errorf("expected %d, got %d", http.StatusOK, w.Code) + } +} diff --git a/internal/domain/domain.go b/internal/domain/domain.go index 8875fd6..9c577cb 100644 --- a/internal/domain/domain.go +++ b/internal/domain/domain.go @@ -103,7 +103,7 @@ func (DP *State) GetInfo(domain Domain) error { DP.UUID = uuidParsed.String() userInfo, err := domain.GetGuestInfo(libvirt.DOMAIN_GUEST_INFO_USERS, 0) if err != nil { - return virerr.ErrorGen(virerr.DomainStatusError, fmt.Errorf("error retreving guest info: %w", err)) + return virerr.ErrorGen(virerr.DomainStatusError, fmt.Errorf("error retrieving guest info: %w", err)) } DP.Users = userInfo.Users return nil diff --git a/internal/error/Error.go b/internal/error/Error.go index d64b29b..d72dd30 100755 --- a/internal/error/Error.go +++ b/internal/error/Error.go @@ -8,7 +8,7 @@ import ( type VirError string const ( - FaildDeEncoding VirError = "Error Not Found" + FailedDecoding VirError = "Error Not Found" DomainSearchError VirError = "Error Serching Domain" NoSuchDomain VirError = "Domain Not Found" @@ -22,8 +22,8 @@ const ( InvalidParameter VirError = "Invalid parameter entered" WrongParameter VirError = "Not validated parameter In" - DomainStatusError VirError = "Error Retreving Domain Status" - HostStatusError VirError = "Error Retreving Host Status" + DomainStatusError VirError = "Error Retrieving Domain Status" + HostStatusError VirError = "Error Retrieving Host Status" DeletionDomainError VirError = "Error Deleting Domain" DomainShutdownError VirError = "failed in Deleting domain" diff --git a/internal/host/host.go b/internal/host/host.go index f5c387f..3789dfc 100644 --- a/internal/host/host.go +++ b/internal/host/host.go @@ -113,13 +113,13 @@ func (HDI *DiskInfo) GetHostInfo(_ *domStatus.DomainListStatus) error { func (SI *GeneralInfo) GetHostInfo(status *domStatus.DomainListStatus) error { if err := SI.CPU.GetHostInfo(status); err != nil { - return virerr.ErrorGen(virerr.HostStatusError, fmt.Errorf("general Status:error retreving host Status %w", err)) + return virerr.ErrorGen(virerr.HostStatusError, fmt.Errorf("general Status:error retrieving host status %w", err)) } if err := SI.Disk.GetHostInfo(status); err != nil { - return virerr.ErrorGen(virerr.HostStatusError, fmt.Errorf("general Status:error retreving host Status %w", err)) + return virerr.ErrorGen(virerr.HostStatusError, fmt.Errorf("general Status:error retrieving host status %w", err)) } if err := SI.Memory.GetHostInfo(status); err != nil { - return virerr.ErrorGen(virerr.HostStatusError, fmt.Errorf("general Status:error retreving host Status %w", err)) + return virerr.ErrorGen(virerr.HostStatusError, fmt.Errorf("general Status:error retrieving host status %w", err)) } return nil } diff --git a/internal/server/middleware/libvirt.go b/internal/server/middleware/libvirt.go index 66b685e..ddd2644 100644 --- a/internal/server/middleware/libvirt.go +++ b/internal/server/middleware/libvirt.go @@ -10,10 +10,7 @@ func LibvirtMiddleware(check func() bool, logger *zap.Logger) func(http.Handler) return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if !check() { - // find a way for graceful shutdown of server when libvirt connection is unavailable logger.Panic("libvirt connection unavailable", zap.String("path", r.URL.Path)) - http.Error(w, "service unavailable", http.StatusServiceUnavailable) - return } next.ServeHTTP(w, r) }) diff --git a/pkg/httputil/utils.go b/pkg/httputil/utils.go index 7549eeb..d8460d7 100644 --- a/pkg/httputil/utils.go +++ b/pkg/httputil/utils.go @@ -13,7 +13,7 @@ type BaseResponse[T any] struct { Information *T `json:"information,omitempty"` Message string `json:"message"` Errors *virerr.ErrorDescriptor `json:"errors,omitempty"` - ErrorDebug string `json:"errrorDebug,omitempty"` + ErrorDebug string `json:"errorDebug,omitempty"` } func ResponseGen[T any](message string) *BaseResponse[T] { @@ -25,25 +25,24 @@ func ResponseGen[T any](message string) *BaseResponse[T] { func HttpDecoder[T any](r *http.Request, param *T) error { body, err := io.ReadAll(r.Body) if err != nil { - return virerr.ErrorGen(virerr.FaildDeEncoding, fmt.Errorf("%w error unmarshaling body into Structure", err)) + return virerr.ErrorGen(virerr.FailedDecoding, fmt.Errorf("%w error unmarshaling body into Structure", err)) } defer r.Body.Close() if err := json.Unmarshal(body, param); err != nil { - return virerr.ErrorGen(virerr.FaildDeEncoding, fmt.Errorf("%w error unmarshaling body into Structure", err)) + return virerr.ErrorGen(virerr.FailedDecoding, fmt.Errorf("%w error unmarshaling body into Structure", err)) } return nil } func (br *BaseResponse[T]) ResponseWriteErr(w http.ResponseWriter, err error, statusCode int) { br.Message += " failed" - errDesc, ok := err.(virerr.ErrorDescriptor) - if !ok { - http.Error(w, br.Message, http.StatusInternalServerError) - return + if errDesc, ok := err.(virerr.ErrorDescriptor); ok { + br.Errors = &errDesc + br.ErrorDebug = errDesc.Error() + } else { + br.ErrorDebug = err.Error() } - br.Errors = &errDesc - br.ErrorDebug = errDesc.Error() data, marshalErr := json.Marshal(br) if marshalErr != nil { http.Error(w, "failed to marshal error response", http.StatusInternalServerError) diff --git a/pkg/parsor/XML_Parsor.go b/pkg/parsor/XML_Parsor.go index 667adac..87d287c 100755 --- a/pkg/parsor/XML_Parsor.go +++ b/pkg/parsor/XML_Parsor.go @@ -40,11 +40,11 @@ func (XP *VM_CREATE_XML) XML_Parsor(spec *vmtypes.VM_Init_Info) error { UUID: spec.UUID, Memory: Memory{ Unit: "GiB", - Size: spec.HardwardInfo.Memory, + Size: spec.HardwareInfo.Memory, }, VCPU: VCPU{ Placement: "static", - Count: spec.HardwardInfo.CPU, + Count: spec.HardwareInfo.CPU, }, Features: Features{ ACPI: ACPI{}, diff --git a/pkg/parsor/xml_parsor_test.go b/pkg/parsor/xml_parsor_test.go index e91e630..7ee6f8a 100644 --- a/pkg/parsor/xml_parsor_test.go +++ b/pkg/parsor/xml_parsor_test.go @@ -13,7 +13,7 @@ var testSpec = &vmtypes.VM_Init_Info{ DomName: "test-vm", UUID: "123e4567-e89b-12d3-a456-426614174000", OS: "debian", - HardwardInfo: vmtypes.HardwareInfo{ + HardwareInfo: vmtypes.HardwareInfo{ CPU: 2, Memory: 4, Disk: 20, @@ -99,11 +99,11 @@ func TestXMLParsor(t *testing.T) { if xp.UUID != testSpec.UUID { t.Errorf("uuid: expected %s, got %s", testSpec.UUID, xp.UUID) } - if xp.Memory.Size != testSpec.HardwardInfo.Memory { - t.Errorf("memory: expected %d, got %d", testSpec.HardwardInfo.Memory, xp.Memory.Size) + if xp.Memory.Size != testSpec.HardwareInfo.Memory { + t.Errorf("memory: expected %d, got %d", testSpec.HardwareInfo.Memory, xp.Memory.Size) } - if xp.VCPU.Count != testSpec.HardwardInfo.CPU { - t.Errorf("vcpu: expected %d, got %d", testSpec.HardwardInfo.CPU, xp.VCPU.Count) + if xp.VCPU.Count != testSpec.HardwareInfo.CPU { + t.Errorf("vcpu: expected %d, got %d", testSpec.HardwareInfo.CPU, xp.VCPU.Count) } if len(xp.Devices.Disks) != 2 { t.Errorf("disks: expected 2, got %d", len(xp.Devices.Disks)) diff --git a/pkg/types/vm.go b/pkg/types/vm.go index 315c714..26ab361 100644 --- a/pkg/types/vm.go +++ b/pkg/types/vm.go @@ -6,7 +6,7 @@ type VM_Init_Info struct { DomName string `json:"domName"` UUID string `json:"uuid"` OS string `json:"os"` - HardwardInfo HardwareInfo `json:"HWInfo"` + HardwareInfo HardwareInfo `json:"HWInfo"` NetConf network.NetDefine `json:"network"` Users []User_info_VM `json:"users"` SDNUUID string `json:"sdnUUID"` diff --git a/services/creation/boot_domain.go b/services/creation/boot_domain.go new file mode 100644 index 0000000..6dd35d8 --- /dev/null +++ b/services/creation/boot_domain.go @@ -0,0 +1,14 @@ +package creation + +import ( + "fmt" + + virerr "github.com/easy-cloud-Knet/KWS_Core/internal/error" +) + +func BootExistingVM(d BootableDomain) error { + if err := d.Create(); err != nil { + return virerr.ErrorGen(virerr.DomainGenerationError, fmt.Errorf("error starting domain: %w", err)) + } + return nil +} diff --git a/services/creation/creation_test.go b/services/creation/creation_test.go index 79cbfc1..380a7ef 100644 --- a/services/creation/creation_test.go +++ b/services/creation/creation_test.go @@ -58,3 +58,34 @@ func TestCreateVM_DomainDefineXMLError(t *testing.T) { // TODO: processCloudInitFiles, GenerateXML 내부 로직 테스트는 // YamlParsor, XMLDefiner 인터페이스 + VM_CREATE_XML.MarshalXML() 추가 후 가능. + +type mockBootableDomain struct { + createErr error + called bool +} + +func (m *mockBootableDomain) Create() error { + m.called = true + return m.createErr +} + +func TestBootExistingVM_Success(t *testing.T) { + mock := &mockBootableDomain{} + if err := BootExistingVM(mock); err != nil { + t.Errorf("expected nil, got %v", err) + } + if !mock.called { + t.Error("Create not called") + } +} + +func TestBootExistingVM_Error(t *testing.T) { + mock := &mockBootableDomain{createErr: fmt.Errorf("libvirt error")} + err := BootExistingVM(mock) + if err == nil { + t.Fatal("expected error, got nil") + } + if !errors.Is(err, virerr.DomainGenerationError) { + t.Errorf("expected DomainGenerationError, got %v", err) + } +} diff --git a/services/creation/domain.go b/services/creation/domain.go index 001052c..d527997 100644 --- a/services/creation/domain.go +++ b/services/creation/domain.go @@ -17,3 +17,9 @@ type Configurer interface { type LibvirtConnect interface { DomainDefineXML(xmlConfig string) (*libvirt.Domain, error) } + +// BootableDomain abstracts domain boot for testing. +// *libvirt.Domain satisfies this via structural typing. +type BootableDomain interface { + Create() error +} diff --git a/services/creation/generate_files.go b/services/creation/generate_files.go index c734853..62c66e7 100755 --- a/services/creation/generate_files.go +++ b/services/creation/generate_files.go @@ -19,7 +19,7 @@ func (DB localConfigurer) CreateDiskImage(dirPath string, diskSize int) error { targetImage, fmt.Sprintf("%dG", diskSize), // 10G ) if err := qemuImgCmd.Run(); err != nil { - errorDescription := fmt.Errorf("generating Disk image error, check duplicdated uuid or lack of HD capacity, or validity for base img %s, %v", dirPath, err) + errorDescription := fmt.Errorf("generating Disk image error, check duplicated uuid or lack of HD capacity, or validity for base img %s, %v", dirPath, err) return virerr.ErrorGen(virerr.DomainGenerationError, errorDescription) } @@ -40,7 +40,7 @@ func (DB localConfigurer) CreateISOFile(dirPath string) error { ) if err := genisoCmd.Run(); err != nil { - errorDescription := fmt.Errorf("generating ISO image error, may have duplicdated uuid or wrong format of yaml file %s, %v", dirPath, err) + errorDescription := fmt.Errorf("generating ISO image error, may have duplicated uuid or wrong format of yaml file %s, %v", dirPath, err) return virerr.ErrorGen(virerr.DomainGenerationError, errorDescription) } return nil diff --git a/services/creation/local_domain.go b/services/creation/local_domain.go index 9376d01..cd2a954 100755 --- a/services/creation/local_domain.go +++ b/services/creation/local_domain.go @@ -114,7 +114,7 @@ func (DB localConfigurer) Generate(logger *zap.Logger) error { } 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, DB.VMDescription.HardwareInfo.Disk); err != nil { errorEncapsed := virerr.ErrorJoin(err, fmt.Errorf("in domain-parsor,")) logger.Error(errorEncapsed.Error()) return cleanup(errorEncapsed) diff --git a/services/status/service.go b/services/status/service.go index 2edec27..a1f8f60 100644 --- a/services/status/service.go +++ b/services/status/service.go @@ -1,9 +1,13 @@ package status import ( + "fmt" + domStatus "github.com/easy-cloud-Knet/KWS_Core/DomCon/domainList_status" "github.com/easy-cloud-Knet/KWS_Core/internal/domain" + virerr "github.com/easy-cloud-Knet/KWS_Core/internal/error" "github.com/easy-cloud-Knet/KWS_Core/internal/host" + "libvirt.org/go/libvirt" ) type ( @@ -53,3 +57,33 @@ func InstDataTypeRouter(t InstDataType) (InstDataTypeHandler, error) { func InstDetailFactory(handler InstDataTypeHandler, conn Connect) (*InstDetail, error) { return domain.InstDetailFactory(handler, conn) } + +type DomainStateInfo struct { + UUID string `json:"UUID"` + DomainState libvirt.DomainState `json:"currentState"` +} + +func ListAllDomainStates(conn Connect) ([]DomainStateInfo, error) { + domains, err := conn.ListAllDomains(0) + if err != nil { + return nil, virerr.ErrorGen(virerr.DomainStatusError, fmt.Errorf("failed to list domains: %w", err)) + } + defer func() { + for i := range domains { + domains[i].Free() + } + }() + result := make([]DomainStateInfo, 0, len(domains)) + for i := range domains { + uuid, err := domains[i].GetUUIDString() + if err != nil { + continue + } + state, _, err := domains[i].GetState() + if err != nil { + continue + } + result = append(result, DomainStateInfo{UUID: uuid, DomainState: state}) + } + return result, nil +} diff --git a/services/status/status_test.go b/services/status/status_test.go new file mode 100644 index 0000000..45327dd --- /dev/null +++ b/services/status/status_test.go @@ -0,0 +1,36 @@ +package status + +import ( + "fmt" + "testing" + + "libvirt.org/go/libvirt" +) + +type mockConnect struct { + domains []libvirt.Domain + err error +} + +func (m *mockConnect) ListAllDomains(_ libvirt.ConnectListAllDomainsFlags) ([]libvirt.Domain, error) { + return m.domains, m.err +} + +func TestListAllDomainStates_ConnectError(t *testing.T) { + mock := &mockConnect{err: fmt.Errorf("connect error")} + _, err := ListAllDomainStates(mock) + if err == nil { + t.Fatal("expected error, got nil") + } +} + +func TestListAllDomainStates_Empty(t *testing.T) { + mock := &mockConnect{domains: []libvirt.Domain{}} + result, err := ListAllDomainStates(mock) + if err != nil { + t.Fatalf("expected nil error, got %v", err) + } + if len(result) != 0 { + t.Errorf("expected empty result, got %d items", len(result)) + } +} diff --git a/services/termination/delete_domain.go b/services/termination/delete_domain.go index c60bfe6..69aac9b 100755 --- a/services/termination/delete_domain.go +++ b/services/termination/delete_domain.go @@ -3,7 +3,6 @@ package termination import ( "fmt" "os" - "os/exec" "path/filepath" "github.com/easy-cloud-Knet/KWS_Core/internal/config" @@ -30,11 +29,7 @@ func (DD *DomainDeleter) DeleteDomain() error { } FilePath := filepath.Join(config.StorageBase, DD.uuid) - deleteCmd := exec.Command("rm", "-rf", FilePath) - deleteCmd.Stdout = os.Stdout - deleteCmd.Stderr = os.Stderr - - if err := deleteCmd.Run(); err != nil { + if err := os.RemoveAll(FilePath); err != nil { return virerr.ErrorGen(virerr.DeletionDomainError, fmt.Errorf("failed deleting files in %s: %w", FilePath, err)) }