@@ -96,17 +96,45 @@ func newLocal(ic *plugin.InitContext) (*local, error) {
9696func (s * local ) CreateVM (requestCtx context.Context , req * proto.CreateVMRequest ) (* proto.CreateVMResponse , error ) {
9797 var err error
9898
99- id := req .GetVMID ()
100- if err := identifiers .Validate (id ); err != nil {
99+ // Create shim
100+ _ , err = s .CreateShim (requestCtx , req .GetVMID ())
101+ if err != nil {
102+ return nil , err
103+ }
104+
105+ client , err := s .shimFirecrackerClient (requestCtx , req .GetVMID ())
106+ if err != nil {
107+ err = errors .Wrap (err , "failed to create firecracker shim client" )
101108 s .logger .WithError (err ).Error ()
102109 return nil , err
103110 }
104111
112+ defer client .Close ()
113+
114+ resp , err := client .CreateVM (requestCtx , req )
115+ if err != nil {
116+ s .logger .WithError (err ).Error ("shim CreateVM returned error" )
117+ return nil , err
118+ }
119+
120+ return resp , nil
121+ }
122+
123+ func (s * local ) CreateShim (requestCtx context.Context , id string ) (codes.Code , error ) {
124+ var err error
125+
126+ // Validate VM id
127+ if err := identifiers .Validate (id ); err != nil {
128+ s .logger .WithError (err ).Error ()
129+ return codes .Unknown , err
130+ }
131+
132+ // Validate namespace
105133 ns , err := namespaces .NamespaceRequired (requestCtx )
106134 if err != nil {
107135 err = errors .Wrap (err , "error retrieving namespace of request" )
108136 s .logger .WithError (err ).Error ()
109- return nil , err
137+ return codes . Unknown , err
110138 }
111139
112140 s .logger .Debugf ("using namespace: %s" , ns )
@@ -118,36 +146,36 @@ func (s *local) CreateVM(requestCtx context.Context, req *proto.CreateVMRequest)
118146 if err != nil {
119147 err = errors .Wrap (err , "failed to obtain shim socket address" )
120148 s .logger .WithError (err ).Error ()
121- return nil , err
149+ return codes . Unknown , err
122150 }
123151
124152 shimSocket , err := shim .NewSocket (shimSocketAddress )
125153 if shim .SocketEaddrinuse (err ) {
126- return nil , status .Errorf (codes .AlreadyExists , "VM with ID %q already exists (socket: %q)" , id , shimSocketAddress )
154+ return codes . AlreadyExists , status .Errorf (codes .AlreadyExists , "VM with ID %q already exists (socket: %q)" , id , shimSocketAddress )
127155 } else if err != nil {
128156 err = errors .Wrapf (err , "failed to open shim socket at address %q" , shimSocketAddress )
129157 s .logger .WithError (err ).Error ()
130- return nil , err
158+ return codes . Unknown , err
131159 }
132160
133161 // If we're here, there is no pre-existing shim for this VMID, so we spawn a new one
134162 if err := os .Mkdir (s .config .ShimBaseDir , 0700 ); err != nil && ! os .IsExist (err ) {
135163 s .logger .WithError (err ).Error ()
136- return nil , errors .Wrapf (err , "failed to make shim base directory: %s" , s .config .ShimBaseDir )
164+ return codes . Unknown , errors .Wrapf (err , "failed to make shim base directory: %s" , s .config .ShimBaseDir )
137165 }
138166
139167 shimDir , err := vm .ShimDir (s .config .ShimBaseDir , ns , id )
140168 if err != nil {
141169 err = errors .Wrapf (err , "failed to build shim path" )
142170 s .logger .WithError (err ).Error ()
143- return nil , err
171+ return codes . Unknown , err
144172 }
145173
146174 err = shimDir .Mkdir ()
147175 if err != nil {
148176 err = errors .Wrapf (err , "failed to create VM dir %q" , shimDir .RootPath ())
149177 s .logger .WithError (err ).Error ()
150- return nil , err
178+ return codes . Unknown , err
151179 }
152180
153181 defer func () {
@@ -167,19 +195,19 @@ func (s *local) CreateVM(requestCtx context.Context, req *proto.CreateVMRequest)
167195 if err != nil {
168196 err = errors .Wrap (err , "failed to obtain shim socket address" )
169197 s .logger .WithError (err ).Error ()
170- return nil , err
198+ return codes . Unknown , err
171199 }
172200
173201 fcSocket , err := shim .NewSocket (fcSocketAddress )
174202 if err != nil {
175203 err = errors .Wrapf (err , "failed to open fccontrol socket at address %q" , fcSocketAddress )
176204 s .logger .WithError (err ).Error ()
177- return nil , err
205+ return codes . Unknown , err
178206 }
179207
180208 cmd , err := s .newShim (ns , id , s .containerdAddress , shimSocket , fcSocket )
181209 if err != nil {
182- return nil , err
210+ return codes . Unknown , err
183211 }
184212
185213 defer func () {
@@ -188,26 +216,12 @@ func (s *local) CreateVM(requestCtx context.Context, req *proto.CreateVMRequest)
188216 }
189217 }()
190218
191- client , err := s .shimFirecrackerClient (requestCtx , id )
192- if err != nil {
193- err = errors .Wrap (err , "failed to create firecracker shim client" )
194- s .logger .WithError (err ).Error ()
195- return nil , err
196- }
197-
198- defer client .Close ()
199-
200- resp , err := client .CreateVM (requestCtx , req )
201- if err != nil {
202- s .logger .WithError (err ).Error ("shim CreateVM returned error" )
203- return nil , err
204- }
205-
206219 s .addShim (shimSocketAddress , cmd )
207220
208- return resp , nil
221+ return codes . OK , nil
209222}
210223
224+
211225func (s * local ) addShim (address string , cmd * exec.Cmd ) {
212226 s .processesMu .Lock ()
213227 defer s .processesMu .Unlock ()
@@ -617,6 +631,14 @@ func (s *local) CreateSnapshot(ctx context.Context, req *proto.CreateSnapshotReq
617631
618632// LoadSnapshot Loads a snapshot of a VM
619633func (s * local ) LoadSnapshot (ctx context.Context , req * proto.LoadSnapshotRequest ) (* proto.LoadResponse , error ) {
634+ var err error
635+
636+ // Create shim if not exists yet
637+ code , err := s .CreateShim (ctx , req .GetVMID ())
638+ if err != nil && code != codes .AlreadyExists {
639+ return nil , err
640+ }
641+
620642 client , err := s .shimFirecrackerClient (ctx , req .VMID )
621643 if err != nil {
622644 return nil , err
@@ -651,4 +673,4 @@ func (s *local) Offload(ctx context.Context, req *proto.OffloadRequest) (*empty.
651673 }
652674
653675 return resp , nil
654- }
676+ }
0 commit comments