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