github.com/rkt/rkt@v1.30.1-0.20200224141603-171c416fac02/stage0/app_rm.go (about) 1 // Copyright 2016 The rkt Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //+build linux 16 17 package stage0 18 19 import ( 20 "errors" 21 "fmt" 22 "io/ioutil" 23 "os" 24 "path/filepath" 25 "syscall" 26 27 "github.com/appc/spec/schema/types" 28 "github.com/hashicorp/errwrap" 29 "github.com/rkt/rkt/common" 30 pkgPod "github.com/rkt/rkt/pkg/pod" 31 ) 32 33 type RmConfig struct { 34 *CommonConfig 35 PodPath string 36 UsesOverlay bool 37 AppName *types.ACName 38 PodPID int 39 } 40 41 func RmApp(cfg RmConfig) error { 42 pod, err := pkgPod.PodFromUUIDString(cfg.DataDir, cfg.UUID.String()) 43 if err != nil { 44 return errwrap.Wrap(errors.New("error loading pod"), err) 45 } 46 defer pod.Close() 47 48 debug("locking sandbox manifest") 49 if err := pod.ExclusiveLockManifest(); err != nil { 50 return errwrap.Wrap(errors.New("failed to lock sandbox manifest"), err) 51 } 52 defer pod.UnlockManifest() 53 54 pm, err := pod.SandboxManifest() 55 if err != nil { 56 return errwrap.Wrap(errors.New("cannot remove application, sandbox validation failed"), err) 57 } 58 59 app := pm.Apps.Get(*cfg.AppName) 60 if app == nil { 61 return fmt.Errorf("error: nonexistent app %q", *cfg.AppName) 62 } 63 64 if cfg.PodPID > 0 { 65 // Call app-stop and app-rm entrypoint only if the pod is still running. 66 // Otherwise, there's not much we can do about it except unmounting/removing 67 // the file system. 68 args := []string{ 69 fmt.Sprintf("--debug=%t", cfg.Debug), 70 fmt.Sprintf("--app=%s", cfg.AppName), 71 } 72 73 ce := CrossingEntrypoint{ 74 PodPath: cfg.PodPath, 75 PodPID: cfg.PodPID, 76 AppName: cfg.AppName.String(), 77 EntrypointName: appStopEntrypoint, 78 EntrypointArgs: args, 79 Interactive: false, 80 } 81 if err := ce.Run(); err != nil { 82 status, err := common.GetExitStatus(err) 83 // ignore nonexistent units failing to stop. Exit status 5 84 // comes from systemctl and means the unit doesn't exist 85 if err != nil { 86 return err 87 } else if status != 5 { 88 return fmt.Errorf("exit status %d", status) 89 } 90 } 91 92 ce.EntrypointName = appRmEntrypoint 93 if err := ce.Run(); err != nil { 94 return err 95 } 96 } 97 98 if cfg.UsesOverlay { 99 treeStoreID, err := ioutil.ReadFile(common.AppTreeStoreIDPath(cfg.PodPath, *cfg.AppName)) 100 if err != nil { 101 return err 102 } 103 104 appRootfs := common.AppRootfsPath(cfg.PodPath, *cfg.AppName) 105 // if the system reboots stage1 won't be mounted and appRootfs won't 106 // exist, ignore this error 107 if err := syscall.Unmount(appRootfs, 0); err != nil && !os.IsNotExist(err) { 108 return err 109 } 110 111 ts := filepath.Join(cfg.PodPath, "overlay", string(treeStoreID)) 112 if err := os.RemoveAll(ts); err != nil { 113 return errwrap.Wrap(errors.New("error removing app info directory"), err) 114 } 115 } 116 117 appInfoDir := common.AppInfoPath(cfg.PodPath, *cfg.AppName) 118 if err := os.RemoveAll(appInfoDir); err != nil { 119 return errwrap.Wrap(errors.New("error removing app info directory"), err) 120 } 121 122 if err := os.RemoveAll(common.AppPath(cfg.PodPath, *cfg.AppName)); err != nil { 123 return err 124 } 125 126 stage1RootfsPath, err := pod.Stage1RootfsPath() 127 if err != nil { 128 return err 129 } 130 131 appStatusPath := filepath.Join(stage1RootfsPath, "rkt", "status", cfg.AppName.String()) 132 if err := os.Remove(appStatusPath); err != nil && !os.IsNotExist(err) { 133 return err 134 } 135 136 envPath := filepath.Join(stage1RootfsPath, "rkt", "env", cfg.AppName.String()) 137 if err := os.Remove(envPath); err != nil && !os.IsNotExist(err) { 138 return err 139 } 140 141 for i, app := range pm.Apps { 142 if app.Name == *cfg.AppName { 143 pm.Apps = append(pm.Apps[:i], pm.Apps[i+1:]...) 144 break 145 } 146 } 147 148 return pod.UpdateManifest(pm, cfg.PodPath) 149 }