From 05893582407ff0c5daf4dc137518130d7ca778cb Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Thu, 14 Mar 2024 16:53:38 +0100 Subject: [PATCH 1/4] Use gocleanup package pkg/vf/virtionet.go uses local adhoc solution to run cleanup tasks when vfkit exits. github.com/onsi/gocleanup achieves the same result in more generic code. Since there are more things I'd like to cleanup at exit time, let's make use of this package. It hasn't been changed in a long time, but its code is a short single file, at worse we can import this file in vfkit repository and make the changes we need. Signed-off-by: Christophe Fergeau --- cmd/vfkit/root.go | 4 ++- go.mod | 2 ++ go.sum | 70 +++++++++++++++++++++++++++++++++++++++++++++ pkg/vf/virtionet.go | 16 ++--------- 4 files changed, 77 insertions(+), 15 deletions(-) diff --git a/cmd/vfkit/root.go b/cmd/vfkit/root.go index eea2f9f2..18716f62 100644 --- a/cmd/vfkit/root.go +++ b/cmd/vfkit/root.go @@ -5,6 +5,7 @@ import ( "os" "github.com/crc-org/vfkit/pkg/cmdline" + "github.com/onsi/gocleanup" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -57,10 +58,11 @@ func getLogLevel() (logrus.Level, error) { func Execute() { if err := rootCmd.Execute(); err != nil { fmt.Fprintln(os.Stderr, err) - os.Exit(1) + gocleanup.Exit(1) } } func main() { Execute() + gocleanup.Exit(0) } diff --git a/go.mod b/go.mod index 45f9afc5..49b4b235 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/containers/common v0.58.0 github.com/crc-org/crc/v2 v2.33.0 github.com/gin-gonic/gin v1.9.1 + github.com/onsi/gocleanup v0.0.0-20140331211545-c1a5478700b5 github.com/prashantgupta24/mac-sleep-notifier v1.0.1 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.8.0 @@ -49,6 +50,7 @@ require ( github.com/mattn/go-runewidth v0.0.15 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/onsi/ginkgo v1.16.5 // indirect github.com/pelletier/go-toml/v2 v2.1.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect diff --git a/go.sum b/go.sum index 5f69122b..24c3e60a 100644 --- a/go.sum +++ b/go.sum @@ -35,6 +35,9 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= @@ -50,8 +53,19 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.17.0 h1:SmVVlfAOtlZncTxRuinDPomC2DkXJ4E5T9gDA0AIH74= github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= @@ -59,6 +73,7 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -85,6 +100,18 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/gocleanup v0.0.0-20140331211545-c1a5478700b5 h1:uuhPqmc+m7Nj7btxZEjdEUv+uFoBHNf2Tk/E7gGM+kY= +github.com/onsi/gocleanup v0.0.0-20140331211545-c1a5478700b5/go.mod h1:tHaogb+iP6wJXwCqVUlmxYuJb4XDyEKxxs3E4DvMBK0= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo= github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -116,6 +143,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -134,20 +162,42 @@ github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65E github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -159,15 +209,35 @@ golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/vf/virtionet.go b/pkg/vf/virtionet.go index 72fd73c2..d0f8d9a9 100644 --- a/pkg/vf/virtionet.go +++ b/pkg/vf/virtionet.go @@ -4,13 +4,13 @@ import ( "fmt" "net" "os" - "os/signal" "path/filepath" "syscall" "github.com/crc-org/vfkit/pkg/config" "github.com/Code-Hex/vz/v3" + "github.com/onsi/gocleanup" log "github.com/sirupsen/logrus" ) @@ -89,7 +89,7 @@ func (dev *VirtioNet) connectUnixPath() error { dev.Socket = fd dev.localAddr = &localAddr dev.UnixSocketPath = "" - registerExitHandler(func() { _ = dev.Shutdown() }) + gocleanup.Register(func() { _ = dev.Shutdown() }) return nil } @@ -160,15 +160,3 @@ func (dev *VirtioNet) Shutdown() error { return nil } - -func registerExitHandler(handler func()) { - sigChan := make(chan os.Signal, 2) - signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM, syscall.SIGINT) - go func() { - for sig := range sigChan { - log.Printf("captured %v, calling exit handlers and exiting..", sig) - handler() - os.Exit(1) - } - }() -} From 99898504b5514edf37f0b1a135aaa409d43b66de Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Thu, 14 Mar 2024 16:57:50 +0100 Subject: [PATCH 2/4] rest: Use gocleanup When using the REST API over a unix socket, this ensures the unix socket is removed from the filesystem when vfkit exits. --- pkg/rest/rest.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/rest/rest.go b/pkg/rest/rest.go index 3db945c0..17ebef82 100644 --- a/pkg/rest/rest.go +++ b/pkg/rest/rest.go @@ -4,11 +4,13 @@ import ( "errors" "fmt" "net/url" + "os" "strings" "syscall" "github.com/crc-org/vfkit/pkg/cmdline" "github.com/gin-gonic/gin" + "github.com/onsi/gocleanup" "github.com/sirupsen/logrus" ) @@ -73,6 +75,7 @@ func (v *VFKitService) Start() { case TCP: err = v.router.Run(v.Host) case Unix: + gocleanup.Register(func() { os.Remove(v.Path) }) err = v.router.RunUnix(v.Path) } logrus.Fatal(err) From 6836da56fe54c00e2b8f8a1b4a619b3b3a790d7d Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Wed, 28 Jun 2023 15:51:47 +0200 Subject: [PATCH 3/4] serial: Add --device virtio-serial,pty support This new virtio-serial option allocates a pseudo-tty for the VM console. It can then be accessed using `screen` for example. This is a bit similar to the `--device virtio-serial,stdio` option, except that the console is not tied to the terminal running vfkit, it's possible to connect/disconnect from the pseudo-tty from any terminal. This fixes https://github.com/crc-org/vfkit/issues/48 Signed-off-by: Christophe Fergeau --- doc/usage.md | 15 ++++++++++++- go.mod | 1 + go.sum | 3 +++ pkg/config/json_test.go | 2 +- pkg/config/virtio.go | 33 +++++++++++++++++++++++----- pkg/config/virtio_test.go | 7 ++++++ pkg/vf/virtio.go | 45 ++++++++++++++++++++++++++++++++------- test/vm_test.go | 42 +++++++++++++++++++++++++++++++++--- 8 files changed, 130 insertions(+), 18 deletions(-) diff --git a/doc/usage.md b/doc/usage.md index 38887f96..f8d06c81 100644 --- a/doc/usage.md +++ b/doc/usage.md @@ -225,11 +225,12 @@ This is useful in combination with usermode networking stacks such as [gvisor-ta #### Description The `--device virtio-serial` option adds a serial device to the virtual machine. This is useful to redirect text output from the virtual machine to a log file. -The `logFilePath` and `stdio` arguments are mutually exclusive. +The `logFilePath`, `stdio`, `pty` arguments are mutually exclusive. #### Arguments - `logFilePath`: path where the serial port output should be written. - `stdio`: uses stdin/stdout for the serial console input/output. +- `pty`: allocates a pseudo-terminal for the serial console input/output. #### Example @@ -244,6 +245,18 @@ launched from will be used as an interactive serial console for that device: --device virtio-serial,stdio ``` +This adds a virtio-serial device to the VM, and creates a pseudo-terminal for +the console for that device: +``` +--device virtio-serial,pty +``` +Once the VM is running, you can connect to its console with: +``` +screen /dev/ttys002 +``` +`/dev/ttys002` will vary between `vfkit` runs. +The `/dev/ttys???` path to the pty is printed during vfkit startup. +It's also available through the `/vm/inspect` endpoint of [REST API](#restful-service) in the `ptyName` field of the `virtio-serial` device. ### Random Number Generator diff --git a/go.mod b/go.mod index 49b4b235..09f4d7c6 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/crc-org/crc/v2 v2.33.0 github.com/gin-gonic/gin v1.9.1 github.com/onsi/gocleanup v0.0.0-20140331211545-c1a5478700b5 + github.com/pkg/term v1.1.0 github.com/prashantgupta24/mac-sleep-notifier v1.0.1 github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.8.0 diff --git a/go.sum b/go.sum index 24c3e60a..599179ca 100644 --- a/go.sum +++ b/go.sum @@ -116,6 +116,8 @@ github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOS github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/term v1.1.0 h1:xIAAdCMh3QIAy+5FrE8Ad8XoDhEU4ufwbaSozViP9kk= +github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -195,6 +197,7 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/pkg/config/json_test.go b/pkg/config/json_test.go index 72763f1f..88b3480f 100644 --- a/pkg/config/json_test.go +++ b/pkg/config/json_test.go @@ -232,7 +232,7 @@ var jsonStabilityTests = map[string]jsonStabilityTest{ }, "VirtioSerial": { obj: &VirtioSerial{}, - expectedJSON: `{"kind":"virtioserial","logFile":"LogFile","usesStdio":true}`, + expectedJSON: `{"kind":"virtioserial","logFile":"LogFile","ptyName":"PtyName","usesPty":true,"usesStdio":true}`, }, "VirtioVsock": { obj: &VirtioVsock{}, diff --git a/pkg/config/virtio.go b/pkg/config/virtio.go index 5523cf9a..10ddc92e 100644 --- a/pkg/config/virtio.go +++ b/pkg/config/virtio.go @@ -104,6 +104,10 @@ type VirtioNet struct { type VirtioSerial struct { LogFile string `json:"logFile,omitempty"` UsesStdio bool `json:"usesStdio,omitempty"` + UsesPty bool `json:"usesPty,omitempty"` + // PtyName must not be set when creating the VM, from a user perspective, it's read-only, + // vfkit will set it during VM startup. + PtyName string `json:"ptyName,omitempty"` } // TODO: Add VirtioBalloon @@ -195,12 +199,24 @@ func VirtioSerialNewStdio() (VirtioDevice, error) { }, nil } +func VirtioSerialNewPty() (VirtioDevice, error) { + return &VirtioSerial{ + UsesPty: true, + }, nil +} + func (dev *VirtioSerial) validate() error { if dev.LogFile != "" && dev.UsesStdio { return fmt.Errorf("'logFilePath' and 'stdio' cannot be set at the same time") } - if dev.LogFile == "" && !dev.UsesStdio { - return fmt.Errorf("one of 'logFilePath' or 'stdio' must be set") + if dev.LogFile != "" && dev.UsesPty { + return fmt.Errorf("'logFilePath' and 'pty' cannot be set at the same time") + } + if dev.UsesStdio && dev.UsesPty { + return fmt.Errorf("'stdio' and 'pty' cannot be set at the same time") + } + if dev.LogFile == "" && !dev.UsesStdio && !dev.UsesPty { + return fmt.Errorf("one of 'logFilePath', 'stdio' or 'pty' must be set") } return nil @@ -210,11 +226,16 @@ func (dev *VirtioSerial) ToCmdLine() ([]string, error) { if err := dev.validate(); err != nil { return nil, err } - if dev.UsesStdio { + switch { + case dev.UsesStdio: return []string{"--device", "virtio-serial,stdio"}, nil + case dev.UsesPty: + return []string{"--device", "virtio-serial,pty"}, nil + case dev.LogFile != "": + fallthrough + default: + return []string{"--device", fmt.Sprintf("virtio-serial,logFilePath=%s", dev.LogFile)}, nil } - - return []string{"--device", fmt.Sprintf("virtio-serial,logFilePath=%s", dev.LogFile)}, nil } func (dev *VirtioSerial) FromOptions(options []option) error { @@ -227,6 +248,8 @@ func (dev *VirtioSerial) FromOptions(options []option) error { return fmt.Errorf("unexpected value for virtio-serial 'stdio' option: %s", option.value) } dev.UsesStdio = true + case "pty": + dev.UsesPty = true default: return fmt.Errorf("unknown option for virtio-serial devices: %s", option.key) } diff --git a/pkg/config/virtio_test.go b/pkg/config/virtio_test.go index 371c1875..149ffd97 100644 --- a/pkg/config/virtio_test.go +++ b/pkg/config/virtio_test.go @@ -120,6 +120,13 @@ var virtioDevTests = map[string]virtioDevTest{ }, expectedCmdLine: []string{"--device", "virtio-serial,stdio"}, }, + "NewVirtioSerialPty": { + newDev: VirtioSerialNewPty, + expectedDev: &VirtioSerial{ + UsesPty: true, + }, + expectedCmdLine: []string{"--device", "virtio-serial,pty"}, + }, "NewVirtioNet": { newDev: func() (VirtioDevice, error) { return VirtioNetNew("") }, expectedDev: &VirtioNet{ diff --git a/pkg/vf/virtio.go b/pkg/vf/virtio.go index 38cec7a9..ec52689f 100644 --- a/pkg/vf/virtio.go +++ b/pkg/vf/virtio.go @@ -7,10 +7,12 @@ import ( "syscall" "github.com/crc-org/vfkit/pkg/config" + "github.com/onsi/gocleanup" + "golang.org/x/sys/unix" "github.com/Code-Hex/vz/v3" + "github.com/pkg/term/termios" log "github.com/sirupsen/logrus" - "golang.org/x/sys/unix" ) type RosettaShare config.RosettaShare @@ -221,17 +223,38 @@ func setRawMode(f *os.File) error { func (dev *VirtioSerial) toVz() (*vz.VirtioConsoleDeviceSerialPortConfiguration, error) { var serialPortAttachment vz.SerialPortAttachment - var err error - if dev.UsesStdio { + var retErr error + switch { + case dev.UsesStdio: if err := setRawMode(os.Stdin); err != nil { return nil, err } - serialPortAttachment, err = vz.NewFileHandleSerialPortAttachment(os.Stdin, os.Stdout) - } else { - serialPortAttachment, err = vz.NewFileSerialPortAttachment(dev.LogFile, false) + serialPortAttachment, retErr = vz.NewFileHandleSerialPortAttachment(os.Stdin, os.Stdout) + case dev.UsesPty: + master, slave, err := termios.Pty() + if err != nil { + return nil, err + } + // as far as I can tell, we have no use for the slave fd in the + // vfkit process, the user will open minicom/screen/... /dev/ttys00? + // when needed + defer slave.Close() + + // the master fd must stay open for vfkit's lifetime + gocleanup.Register(func() { _ = master.Close() }) + + dev.PtyName = slave.Name() + + if err := setRawMode(master); err != nil { + return nil, err + } + serialPortAttachment, retErr = vz.NewFileHandleSerialPortAttachment(master, master) + + default: + serialPortAttachment, retErr = vz.NewFileSerialPortAttachment(dev.LogFile, false) } - if err != nil { - return nil, err + if retErr != nil { + return nil, retErr } return vz.NewVirtioConsoleDeviceSerialPortConfiguration(serialPortAttachment) @@ -244,11 +267,17 @@ func (dev *VirtioSerial) AddToVirtualMachineConfig(vmConfig *VirtualMachineConfi if dev.UsesStdio { log.Infof("Adding stdio console") } + if dev.PtyName != "" { + return fmt.Errorf("VirtioSerial.PtyName must be empty (current value: %s)", dev.PtyName) + } consoleConfig, err := dev.toVz() if err != nil { return err } + if dev.UsesPty { + log.Infof("Using PTY (pty path: %s)", dev.PtyName) + } vmConfig.serialPortsConfiguration = append(vmConfig.serialPortsConfiguration, consoleConfig) return nil diff --git a/test/vm_test.go b/test/vm_test.go index 336ecea0..d63a3632 100644 --- a/test/vm_test.go +++ b/test/vm_test.go @@ -15,6 +15,7 @@ import ( "github.com/crc-org/vfkit/pkg/config" log "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -272,7 +273,7 @@ var pciidVersionedTests = map[int]map[string]pciidTest{ 14: pciidMacOS14Tests, } -func checkRestDevices(t *testing.T, vm *testVM) { +func restInspect(t *testing.T, vm *testVM) *config.VirtualMachine { tr := &http.Transport{ Dial: func(_, _ string) (conn net.Conn, err error) { return net.Dial("unix", vm.restSocketPath) @@ -287,7 +288,7 @@ func checkRestDevices(t *testing.T, vm *testVM) { var unmarshalledVM config.VirtualMachine err = json.Unmarshal(body, &unmarshalledVM) require.NoError(t, err) - require.Equal(t, vm.config, &unmarshalledVM) + return &unmarshalledVM } func testPCIId(t *testing.T, test pciidTest, provider OsProvider) { @@ -303,7 +304,9 @@ func testPCIId(t *testing.T, test pciidTest, provider OsProvider) { vm.Start(t) vm.WaitForSSH(t) checkPCIDevice(t, vm, test.vendorID, test.deviceID) - checkRestDevices(t, vm) + + unmarshalledVM := restInspect(t, vm) + require.Equal(t, vm.config, unmarshalledVM) vm.Stop(t) } @@ -334,6 +337,39 @@ func TestPCIIds(t *testing.T) { } } +func TestVirtioSerialPTY(t *testing.T) { + puipuiProvider := NewPuipuiProvider() + log.Info("fetching os image") + tempDir := t.TempDir() + err := puipuiProvider.Fetch(tempDir) + require.NoError(t, err) + + vm := NewTestVM(t, puipuiProvider) + defer vm.Close(t) + require.NotNil(t, vm) + + vm.AddSSH(t, "tcp") + dev, err := config.VirtioSerialNewPty() + require.NoError(t, err) + vm.AddDevice(t, dev) + + vm.Start(t) + vm.WaitForSSH(t) + runtimeVM := restInspect(t, vm) + var foundVirtioSerial bool + for _, dev := range runtimeVM.Devices { + runtimeDev, ok := dev.(*config.VirtioSerial) + if ok { + assert.NotEmpty(t, runtimeDev.PtyName) + foundVirtioSerial = true + break + } + } + require.True(t, foundVirtioSerial) + + vm.Stop(t) +} + func checkPCIDevice(t *testing.T, vm *testVM, vendorID, deviceID int) { re := regexp.MustCompile(fmt.Sprintf("(?m)[[:blank:]]%04x:%04x\n", vendorID, deviceID)) lspci, err := vm.SSHCombinedOutput(t, "lspci") From a570c1b0d0f4ae0e8f5c1d650d1466229d5fa13d Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Fri, 15 Mar 2024 10:54:18 +0100 Subject: [PATCH 4/4] virtio: Simplify setRawMode This uses more helper APIs from github.com/pkg/term/termios, and makes the code closer to Apple's recommendations in https://developer.apple.com/documentation/virtualization/running_linux_in_a_virtual_machine?language=objc#:~:text=Configure%20the%20Serial%20Port%20Device%20for%20Standard%20In%20and%20Out This also removes direct use of `syscall` in pkg/vf/virtio.go Signed-off-by: Christophe Fergeau --- pkg/vf/virtio.go | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/pkg/vf/virtio.go b/pkg/vf/virtio.go index ec52689f..5f80219d 100644 --- a/pkg/vf/virtio.go +++ b/pkg/vf/virtio.go @@ -4,7 +4,6 @@ import ( "fmt" "os" "path/filepath" - "syscall" "github.com/crc-org/vfkit/pkg/config" "github.com/onsi/gocleanup" @@ -203,22 +202,18 @@ func (dev *VirtioRng) AddToVirtualMachineConfig(vmConfig *VirtualMachineConfigur // https://developer.apple.com/documentation/virtualization/running_linux_in_a_virtual_machine?language=objc#:~:text=Configure%20the%20Serial%20Port%20Device%20for%20Standard%20In%20and%20Out func setRawMode(f *os.File) error { - // Get settings for terminal - attr, _ := unix.IoctlGetTermios(int(f.Fd()), unix.TIOCGETA) + var attr unix.Termios + err := termios.Tcgetattr(f.Fd(), &attr) + if err != nil { + return err + } // Put stdin into raw mode, disabling local echo, input canonicalization, // and CR-NL mapping. - attr.Iflag &^= syscall.ICRNL - attr.Lflag &^= syscall.ICANON | syscall.ECHO - - // Set minimum characters when reading = 1 char - attr.Cc[syscall.VMIN] = 1 - - // set timeout when reading as non-canonical mode - attr.Cc[syscall.VTIME] = 0 + attr.Iflag &^= unix.ICRNL + attr.Lflag &^= unix.ICANON | unix.ECHO - // reflects the changed settings - return unix.IoctlSetTermios(int(f.Fd()), unix.TIOCSETA, attr) + return termios.Tcsetattr(f.Fd(), termios.TCSANOW, &attr) } func (dev *VirtioSerial) toVz() (*vz.VirtioConsoleDeviceSerialPortConfiguration, error) {