github.com/Equinix-Metal/virtlet@v1.5.2-0.20210807010419-342346535dc5/tests/integration/manager.go (about) 1 /* 2 Copyright 2017 Mirantis 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package integration 18 19 import ( 20 "fmt" 21 "io/ioutil" 22 "net" 23 "net/http" 24 "net/http/httptest" 25 "os" 26 "path/filepath" 27 "testing" 28 "time" 29 30 "google.golang.org/grpc" 31 32 "github.com/Equinix-Metal/virtlet/pkg/api/virtlet.k8s/v1" 33 "github.com/Equinix-Metal/virtlet/pkg/config" 34 "github.com/Equinix-Metal/virtlet/pkg/diag" 35 "github.com/Equinix-Metal/virtlet/pkg/manager" 36 "github.com/Equinix-Metal/virtlet/pkg/tapmanager" 37 ) 38 39 const ( 40 virtletSocket = "/tmp/virtlet.sock" 41 disableKvmEnvVar = "VIRTLET_DISABLE_KVM" 42 ) 43 44 type fakeFDManager struct{} 45 46 var fdManager tapmanager.FDManager 47 48 func (m *fakeFDManager) AddFDs(key string, data interface{}) ([]byte, error) { 49 return nil, nil 50 } 51 52 func (m *fakeFDManager) ReleaseFDs(key string) error { 53 return nil 54 } 55 56 func (m *fakeFDManager) Recover(key string, data interface{}) error { 57 return nil 58 } 59 60 type fakeImageFileSystem struct { 61 t *testing.T 62 inner http.FileSystem 63 } 64 65 func newFakeImageFileSystem(t *testing.T) http.FileSystem { 66 return &fakeImageFileSystem{t: t, inner: http.Dir("/images")} 67 } 68 69 func (fs *fakeImageFileSystem) Open(name string) (http.File, error) { 70 if name != "/cirros.img" && name != "/copy/cirros.img" { 71 fs.t.Errorf("bad file name %q", name) 72 return nil, fmt.Errorf("bad file name %q", name) 73 } 74 return fs.inner.Open("/cirros.img") 75 } 76 77 type VirtletManager struct { 78 t *testing.T 79 ts *httptest.Server 80 tempDir string 81 manager *manager.VirtletManager 82 conn *grpc.ClientConn 83 doneCh chan struct{} 84 } 85 86 func NewVirtletManager(t *testing.T) *VirtletManager { 87 return &VirtletManager{t: t} 88 } 89 90 func (v *VirtletManager) startImageServer() { 91 l, err := net.Listen("tcp", "127.0.0.1:80") 92 if err != nil { 93 v.t.Fatalf("can't listen on port 80: %v", err) 94 } 95 v.ts = httptest.NewUnstartedServer(http.FileServer(newFakeImageFileSystem(v.t))) 96 v.ts.Listener = l 97 v.ts.Start() 98 } 99 100 func (v *VirtletManager) Run() { 101 if v.manager != nil { 102 v.t.Fatalf("virtlet manager already started") 103 } 104 105 v.startImageServer() 106 107 var err error 108 v.tempDir, err = ioutil.TempDir("", "virtlet-manager") 109 if err != nil { 110 v.t.Fatalf("Can't create temp directory: %v", err) 111 } 112 113 os.Setenv("KUBERNETES_CLUSTER_URL", "") 114 pstr := func(s string) *string { return &s } 115 pbool := func(b bool) *bool { return &b } 116 cfg := config.GetDefaultConfig() 117 config.Override(cfg, &v1.VirtletConfig{ 118 DatabasePath: pstr(filepath.Join(v.tempDir, "virtlet.db")), 119 DownloadProtocol: pstr("http"), 120 ImageDir: pstr(filepath.Join(v.tempDir, "images")), 121 SkipImageTranslation: pbool(true), 122 LibvirtURI: pstr(libvirtURI), 123 RawDevices: pstr("loop*"), 124 CRISocketPath: pstr(virtletSocket), 125 DisableLogging: pbool(true), 126 DisableKVM: pbool(os.Getenv(disableKvmEnvVar) != ""), 127 }) 128 v.manager = manager.NewVirtletManager(cfg, &fakeFDManager{}, nil, diag.NewDiagSet()) 129 v.doneCh = make(chan struct{}) 130 go func() { 131 if err := v.manager.Run(); err != nil { 132 v.t.Logf("VirtletManager result (expect closed network connection error): %v", err) 133 } 134 v.manager = nil 135 close(v.doneCh) 136 }() 137 138 if err := waitForSocket(virtletSocket); err != nil { 139 v.t.Fatalf("Couldn't connect to virtlet socket: %v", err) 140 } 141 142 v.conn, err = grpc.Dial(virtletSocket, grpc.WithInsecure(), grpc.WithDialer(Dial)) 143 if err != nil { 144 v.t.Fatalf("Couldn't connect to virtlet socket: %v", err) 145 } 146 } 147 148 func (v *VirtletManager) Close() { 149 if v.manager == nil { 150 v.t.Fatalf("virtlet manager not started") 151 } 152 v.manager.Stop() 153 os.RemoveAll(v.tempDir) 154 v.ts.Close() 155 <-v.doneCh 156 } 157 158 func Dial(socket string, timeout time.Duration) (net.Conn, error) { 159 return net.DialTimeout("unix", socket, timeout) 160 }