Merge of new rebased code
[appc.git] / appc-adapters / appc-iaas-adapter / appc-iaas-adapter-bundle / src / main / java / org / openecomp / appc / adapter / iaas / provider / operation / impl / base / ProviderServerOperation.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * openECOMP : APP-C
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights
6  *                                              reserved.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  * 
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  * 
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.openecomp.appc.adapter.iaas.provider.operation.impl.base;
23
24 import org.openecomp.appc.Constants;
25 import org.openecomp.appc.adapter.iaas.impl.*;
26 import org.openecomp.appc.i18n.Msg;
27 import com.att.cdp.exceptions.ContextConnectionException;
28 import com.att.cdp.exceptions.NotLoggedInException;
29 import com.att.cdp.exceptions.TimeoutException;
30 import com.att.cdp.exceptions.ZoneException;
31 import com.att.cdp.pal.util.StringHelper;
32 import com.att.cdp.zones.ComputeService;
33 import com.att.cdp.zones.Context;
34 import com.att.cdp.zones.ImageService;
35 import com.att.cdp.zones.NetworkService;
36 import com.att.cdp.zones.Provider;
37 import com.att.cdp.zones.model.Hypervisor;
38 import com.att.cdp.zones.model.Image;
39 import com.att.cdp.zones.model.Network;
40 import com.att.cdp.zones.model.Port;
41 import com.att.cdp.zones.model.Server;
42 import com.att.eelf.configuration.EELFLogger;
43 import com.att.eelf.configuration.EELFManager;
44 import com.att.eelf.i18n.EELFResourceManager;
45 import org.glassfish.grizzly.http.util.HttpStatus;
46 import java.util.ArrayList;
47 import java.util.List;
48
49 /**
50  * @since September 29, 2016
51  */
52 public abstract class ProviderServerOperation extends ProviderOperation{
53
54     private static final EELFLogger logger = EELFManager.getInstance().getLogger(ProviderServerOperation.class);
55
56     /**
57      * Looks up the indicated server using the provided context and returns the server to the caller
58      *
59      * @param rc
60      *            The request context
61      * @param context
62      *            The provider context
63      * @param id
64      *            The id of the server
65      * @return The server, or null if there is a problem
66      * @throws ZoneException
67      *             If the server cannot be found
68      * @throws RequestFailedException
69      *             If the server cannot be found because we cant connect to the provider
70      */
71     @SuppressWarnings("nls")
72     protected Server lookupServer(RequestContext rc, Context context, String id)
73             throws ZoneException, RequestFailedException {
74         ComputeService service = context.getComputeService();
75         Server server = null;
76         String msg;
77         Provider provider = context.getProvider();
78
79         while (rc.attempt()) {
80             try {
81                 server = service.getServer(id);
82                 break;
83             } catch (ContextConnectionException e) {
84                 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
85                         context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
86                         Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
87                         Integer.toString(rc.getRetryLimit()));
88                 logger.error(msg, e);
89                 rc.delay();
90             }
91         }
92         if (rc.isFailed()) {
93             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
94             logger.error(msg);
95             doFailure(rc, HttpStatus.BAD_GATEWAY_502, msg);
96             throw new RequestFailedException("Lookup Server", msg, HttpStatus.BAD_GATEWAY_502, server);
97         }
98         return server;
99     }
100
101
102
103     /**
104      * Resume a suspended server and wait for it to enter a running state
105      *
106      * @param rc
107      *            The request context that manages the state and recovery of the request for the life of its processing.
108      * @param server
109      *            The server to be resumed
110      * @throws ZoneException
111      * @throws RequestFailedException
112      */
113     @SuppressWarnings("nls")
114     protected void resumeServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
115         logger.debug(Msg.RESUME_SERVER, server.getId());
116
117         Context context = server.getContext();
118         String msg;
119         Provider provider = context.getProvider();
120         ComputeService service = context.getComputeService();
121         while (rc.attempt()) {
122             try {
123                 server.resume();
124                 break;
125             } catch (ContextConnectionException e) {
126                 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
127                         context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
128                         Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
129                         Integer.toString(rc.getRetryLimit()));
130                 logger.error(msg, e);
131                 rc.delay();
132             }
133         }
134         if (rc.isFailed()) {
135             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
136             logger.error(msg);
137             throw new RequestFailedException("Resume Server", msg, HttpStatus.BAD_GATEWAY_502, server);
138         }
139         rc.reset();
140         waitForStateChange(rc, server, Server.Status.RUNNING);
141     }
142
143
144     protected boolean hasImageAccess(@SuppressWarnings("unused") RequestContext rc, Context context) {
145         logger.info("Checking permissions for image service.");
146         try {
147             ImageService service = context.getImageService();
148             service.getImageByName("CHECK_IMAGE_ACCESS");
149             logger.info("Image service is accessible.");
150             return true;
151         } catch (ZoneException e) {
152             logger.warn("Image service could not be accessed. Some operations may fail.", e);
153             return false;
154         }
155     }
156
157
158     /**
159      * Enter a pool-wait loop checking the server state to see if it has entered one of the desired states or not.
160      * <p>
161      * This method checks the state of the server periodically for one of the desired states. When the server enters one
162      * of the desired states, the method returns a successful indication (true). If the server never enters one of the
163      * desired states within the allocated timeout period, then the method returns a failed response (false). No
164      * exceptions are thrown from this method.
165      * </p>
166      *
167      * @param rc
168      *            The request context that manages the state and recovery of the request for the life of its processing.
169      * @param image
170      *            The server to wait on
171      * @param desiredStates
172      *            A variable list of desired states, any one of which is allowed.
173      * @throws RequestFailedException
174      *             If the request times out or fails for some reason
175      * @throws NotLoggedInException
176      */
177     @SuppressWarnings("nls")
178     protected void waitForStateChange(RequestContext rc, Image image, Image.Status... desiredStates)
179             throws RequestFailedException, NotLoggedInException {
180         int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL);
181         int timeout = configuration.getIntegerProperty(Constants.PROPERTY_SERVER_STATE_CHANGE_TIMEOUT);
182         Context context = image.getContext();
183         Provider provider = context.getProvider();
184         ImageService service = context.getImageService();
185         String msg;
186
187         long endTime = System.currentTimeMillis() + (timeout * 1000); //
188
189         while (rc.attempt()) {
190             try {
191                 try {
192                     image.waitForStateChange(pollInterval, timeout, desiredStates);
193                     break;
194                 } catch (TimeoutException e) {
195                     @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
196                     List<String> list = new ArrayList<>();
197                     for (Image.Status desiredState : desiredStates) {
198                         list.add(desiredState.name());
199                     }
200                     msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
201                             context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
202                             Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
203                             Integer.toString(rc.getRetryLimit()));
204                     logger.error(msg, e);
205                     rc.delay();
206                 }
207             } catch (ZoneException e) {
208                 List<String> list = new ArrayList<>();
209                 for (Image.Status desiredState : desiredStates) {
210                     list.add(desiredState.name());
211                 }
212                 String reason = EELFResourceManager.format(Msg.STATE_CHANGE_EXCEPTION, e.getClass().getSimpleName(),
213                         "server", image.getName(), image.getId(), StringHelper.asList(list), image.getStatus().name(),
214                         e.getMessage());
215                 logger.error(reason);
216                 logger.error(EELFResourceManager.format(e));
217
218                 // Instead of failing we are going to wait and try again.
219                 // Timeout is reduced by delay time
220                 logger.info(String.format("Retrying in %ds", rc.getRetryDelay()));
221                 rc.delay();
222                 timeout = (int) (endTime - System.currentTimeMillis()) / 1000;
223                 // throw new RequestFailedException(e, operation, reason,
224                 // HttpStatus.BAD_GATEWAY_502, server);
225             }
226         }
227
228         if (rc.isFailed()) {
229             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
230             logger.error(msg);
231             throw new RequestFailedException("Waiting for State Change", msg, HttpStatus.BAD_GATEWAY_502, new Server());
232         }
233         rc.reset();
234     }
235
236
237     /**
238      * Enter a pool-wait loop checking the server state to see if it has entered one of the desired states or not.
239      * <p>
240      * This method checks the state of the server periodically for one of the desired states. When the server enters one
241      * of the desired states, the method returns a successful indication (true). If the server never enters one of the
242      * desired states within the allocated timeout period, then the method returns a failed response (false). No
243      * exceptions are thrown from this method.
244      * </p>
245      *
246      * @param rc
247      *            The request context that manages the state and recovery of the request for the life of its processing.
248      * @param server
249      *            The server to wait on
250      * @param desiredStates
251      *            A variable list of desired states, any one of which is allowed.
252      * @throws RequestFailedException
253      *             If the request times out or fails for some reason
254      */
255     @SuppressWarnings("nls")
256     protected void waitForStateChange(RequestContext rc, Server server, Server.Status... desiredStates)
257             throws RequestFailedException {
258         int pollInterval = configuration.getIntegerProperty(Constants.PROPERTY_OPENSTACK_POLL_INTERVAL);
259         int timeout = configuration.getIntegerProperty(Constants.PROPERTY_SERVER_STATE_CHANGE_TIMEOUT);
260         Context context = server.getContext();
261         Provider provider = context.getProvider();
262         ComputeService service = context.getComputeService();
263         String msg;
264
265         long endTime = System.currentTimeMillis() + (timeout * 1000); //
266
267         while (rc.attempt()) {
268             try {
269                 try {
270                     server.waitForStateChange(pollInterval, timeout, desiredStates);
271                     break;
272                 } catch (TimeoutException e) {
273                     @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
274                     List<String> list = new ArrayList<>();
275                     for (Server.Status desiredState : desiredStates) {
276                         list.add(desiredState.name());
277                     }
278                     msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
279                             context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
280                             Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
281                             Integer.toString(rc.getRetryLimit()));
282                     logger.error(msg, e);
283                     rc.delay();
284                 }
285             } catch (ZoneException e) {
286                 List<String> list = new ArrayList<>();
287                 for (Server.Status desiredState : desiredStates) {
288                     list.add(desiredState.name());
289                 }
290                 String reason = EELFResourceManager.format(Msg.STATE_CHANGE_EXCEPTION, e.getClass().getSimpleName(),
291                         "server", server.getName(), server.getId(), StringHelper.asList(list), server.getStatus().name(),
292                         e.getMessage());
293                 logger.error(reason);
294                 logger.error(EELFResourceManager.format(e));
295
296                 // Instead of failing we are going to wait and try again.
297                 // Timeout is reduced by delay time
298                 logger.info(String.format("Retrying in %ds", rc.getRetryDelay()));
299                 rc.delay();
300                 timeout = (int) (endTime - System.currentTimeMillis()) / 1000;
301                 // throw new RequestFailedException(e, operation, reason,
302                 // HttpStatus.BAD_GATEWAY_502, server);
303             }
304         }
305
306         if (rc.isFailed()) {
307             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
308             logger.error(msg);
309             throw new RequestFailedException("Waiting for State Change", msg, HttpStatus.BAD_GATEWAY_502, server);
310         }
311         rc.reset();
312     }
313
314     /**
315      * Stop the specified server and wait for it to stop
316      *
317      * @param rc
318      *            The request context that manages the state and recovery of the request for the life of its processing.
319      * @param server
320      *            The server to be stopped
321      * @throws ZoneException
322      * @throws RequestFailedException
323      */
324     @SuppressWarnings("nls")
325     protected void stopServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
326         logger.debug(Msg.STOP_SERVER, server.getId());
327
328         String msg;
329         Context context = server.getContext();
330         Provider provider = context.getProvider();
331         ComputeService service = context.getComputeService();
332         while (rc.attempt()) {
333             try {
334                 server.stop();
335                 break;
336             } catch (ContextConnectionException e) {
337                 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
338                         context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
339                         Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
340                         Integer.toString(rc.getRetryLimit()));
341                 logger.error(msg, e);
342                 rc.delay();
343             }
344         }
345         if (rc.isFailed()) {
346             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
347             logger.error(msg);
348             throw new RequestFailedException("Stop Server", msg, HttpStatus.BAD_GATEWAY_502, server);
349         }
350         rc.reset();
351         waitForStateChange(rc, server, Server.Status.READY, Server.Status.ERROR);
352     }
353
354     /**
355      * Start the server and wait for it to enter a running state
356      *
357      * @param rc
358      *            The request context that manages the state and recovery of the request for the life of its processing.
359      * @param server
360      *            The server to be started
361      * @throws ZoneException
362      * @throws RequestFailedException
363      */
364     @SuppressWarnings("nls")
365     protected void startServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
366         logger.debug(Msg.START_SERVER, server.getId());
367         String msg;
368         Context context = server.getContext();
369         Provider provider = context.getProvider();
370         ComputeService service = context.getComputeService();
371         while (rc.attempt()) {
372             try {
373                 server.start();
374                 break;
375             } catch (ContextConnectionException e) {
376                 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
377                         context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
378                         Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
379                         Integer.toString(rc.getRetryLimit()));
380                 logger.error(msg, e);
381                 rc.delay();
382             }
383         }
384         if (rc.isFailed()) {
385             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
386             logger.error(msg);
387             throw new RequestFailedException("Start Server", msg, HttpStatus.BAD_GATEWAY_502, server);
388         }
389         rc.reset();
390         waitForStateChange(rc, server, Server.Status.RUNNING);
391     }
392
393
394     /**
395      * Un-Pause a paused server and wait for it to enter a running state
396      *
397      * @param rc
398      *            The request context that manages the state and recovery of the request for the life of its processing.
399      * @param server
400      *            The server to be un-paused
401      * @throws ZoneException
402      * @throws RequestFailedException
403      */
404     @SuppressWarnings("nls")
405     protected void unpauseServer(RequestContext rc, Server server) throws ZoneException, RequestFailedException {
406         logger.debug(Msg.UNPAUSE_SERVER, server.getId());
407
408         String msg;
409         Context context = server.getContext();
410         Provider provider = context.getProvider();
411         ComputeService service = context.getComputeService();
412         while (rc.attempt()) {
413             try {
414                 server.unpause();
415                 break;
416             } catch (ContextConnectionException e) {
417                 msg = EELFResourceManager.format(Msg.CONNECTION_FAILED_RETRY, provider.getName(), service.getURL(),
418                         context.getTenant().getName(), context.getTenant().getId(), e.getMessage(),
419                         Long.toString(rc.getRetryDelay()), Integer.toString(rc.getAttempts()),
420                         Integer.toString(rc.getRetryLimit()));
421                 logger.error(msg, e);
422                 rc.delay();
423             }
424         }
425         if (rc.isFailed()) {
426             msg = EELFResourceManager.format(Msg.CONNECTION_FAILED, provider.getName(), service.getURL());
427             logger.error(msg);
428             throw new RequestFailedException("Unpause Server", msg, HttpStatus.BAD_GATEWAY_502, server);
429         }
430         rc.reset();
431         waitForStateChange(rc, server, Server.Status.RUNNING, Server.Status.READY);
432     }
433
434
435     /**
436      * Generates the event indicating what happened
437      *
438      * @param rc
439      *            The request context that manages the state and recovery of the request for the life of its processing.
440      * @param success
441      *            True if the event represents a successful outcome
442      * @param msg
443      *            The detailed message
444      */
445     protected void generateEvent(@SuppressWarnings("unused") RequestContext rc, @SuppressWarnings("unused") boolean success, @SuppressWarnings("unused") String msg) {
446         // indication to the DG to generate the event?
447     }
448     
449     /**
450      * Checks if the VM is connected to the Virtual Network and reachable
451      *
452      * @param rc
453      *            The request context that manages the state and recovery of the request for the life of its processing.
454      * @param server
455      *             The server object representing the server we want to operate on
456      * @param context
457      *            The interface cloud service provider to access services or the object model, or both
458
459      */
460         protected void checkVirtualMachineNetworkStatus(RequestContext rc, Server server, Context context)
461                         throws ZoneException, RequestFailedException {
462
463                 logger.info("Performing the VM Server networking status checks...");
464                 List<Port> ports = server.getPorts();
465
466                 NetworkService netSvc = context.getNetworkService();
467
468                 String msg;
469                 for (Port port : ports) {
470
471                         switch (port.getPortState().toString().toUpperCase()) {
472                         /**
473                          * The port is connected, configured, and usable for communication
474                          */
475                         case "ONLINE":
476                                 Network network = netSvc.getNetworkById(port.getNetwork());
477                                 // Subnet subnet = netSvc.getSubnetById(port.getSubnetId());
478                                 if (!network.getStatus().equals(Network.Status.ACTIVE.toString())) {
479                                         msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
480                                         logger.error(msg);
481                                         doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
482                                         throw new RequestFailedException("VM Server Network is DOWN", msg.toString(), HttpStatus.PRECONDITION_FAILED_412,
483                                                         server);
484                                 }
485                                 break;
486
487                         /**
488                          * The port is disconnected or powered-off and cannot be used for
489                          * communication
490                          */
491                         case "OFFLINE":
492                                 msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
493                                 logger.error(msg);
494                                 doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
495                                 throw new RequestFailedException("VM Server Port status is OFFLINE", msg.toString(), HttpStatus.PRECONDITION_FAILED_412,
496                                                 server);
497
498                         /**
499                          * The port's status is changing because of some event or operation.
500                          * The final state is yet to be determined.
501                          */
502                         case "PENDING":
503                                 msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
504                                 logger.error(msg);
505                                 doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
506                                 throw new RequestFailedException("VM Server Port status is PENDING", msg.toString(), HttpStatus.PRECONDITION_FAILED_412,
507                                                 server);
508
509                         /**
510                          * The port is in an unknown state and cannot be used.
511                          */
512                         case "UNKNOWN":
513                                 msg = EELFResourceManager.format(Msg.SERVER_NETWORK_ERROR, server.getName(), port.getId());
514                                 logger.error(msg);
515                                 doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
516                                 throw new RequestFailedException("VM Server Port status is UNKNOWN", msg.toString(), HttpStatus.PRECONDITION_FAILED_412,
517                                                 server);
518                         }
519
520                 }
521                 logger.info("Passed the VM Server the Hypervisor status checks..");
522
523         }
524     
525         /**
526      * Checks if the VM is connected to the Virtual Network and reachable
527      *
528      * @param server
529      *             The server object representing the server we want to operate on
530      */
531         protected void checkHypervisor(Server server)
532                         throws ZoneException, RequestFailedException {
533
534                 logger.info("Performing the Hypervisor status checks..");
535                 String status = null, state = null, msg = null;
536
537                 status = server.getHypervisor().getStatus().toString();
538                 state = server.getHypervisor().getState().toString();
539                 
540                 if (!status.equals(Hypervisor.Status.ENABLED.toString()) || !state.equals(Hypervisor.State.UP.toString())) {
541                         msg = EELFResourceManager.format(Msg.HYPERVISOR_DOWN_ERROR, server.getHypervisor().getHostName(), server.getName());
542                         logger.error(msg.toString());
543                 
544                         //doFailure(rc, HttpStatus.PRECONDITION_FAILED_412, msg);
545                         throw new RequestFailedException("Hypervisor status DOWN or NOT ENABLED", msg.toString(), HttpStatus.PRECONDITION_FAILED_412,
546                                         server);
547
548                 }
549                 
550                 logger.info("Passed the Hypervisor status checks..");
551                 
552         }
553
554         /**
555      * Checks if a Host machine is reachable
556      *
557      * @param ipAddress
558      *            IP Address of the Host Machine.
559      * @param server
560      *             The server object representing the Virtual Machine server
561      * @return boolean
562      *            
563      */
564         /*private boolean isHostReachable(String ipAddress) throws IOException {
565                 
566                 InetAddress address = InetAddress.getByName(ipAddress);
567                 
568                 return address.isReachable(15000); 
569                 
570
571         }*/
572     
573 }