blob: 3c81649f224380e41932afced2bc451e1b52bba6 [file] [log] [blame]
Thomas Vachuska7a8de842016-03-07 20:56:35 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Thomas Vachuska7a8de842016-03-07 20:56:35 -08003 *
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
17package org.onosproject.cluster.impl;
18
19import org.apache.felix.scr.Component;
20import org.apache.felix.scr.ScrService;
21import org.apache.felix.scr.annotations.Activate;
22import org.apache.felix.scr.annotations.Deactivate;
23import org.apache.felix.scr.annotations.Reference;
24import org.apache.felix.scr.annotations.ReferenceCardinality;
25import org.apache.karaf.features.Feature;
26import org.apache.karaf.features.FeaturesService;
27import org.onlab.util.SharedScheduledExecutors;
28import org.onosproject.cluster.ClusterAdminService;
29import org.osgi.framework.Bundle;
30import org.osgi.framework.BundleContext;
31import org.osgi.service.component.ComponentContext;
32import org.slf4j.Logger;
33import org.slf4j.LoggerFactory;
34
35import java.util.concurrent.ScheduledFuture;
36import java.util.concurrent.TimeUnit;
37
38/**
39 * Monitors the system to make sure that all bundles and their components
40 * are properly activated and keeps the cluster node service appropriately
41 * updated.
42 */
43@org.apache.felix.scr.annotations.Component(immediate = true)
44public class ComponentsMonitor {
45
46 private Logger log = LoggerFactory.getLogger(getClass());
47
48 private static final long PERIOD = 2500;
49
50 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
51 protected FeaturesService featuresService;
52
53 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
54 protected ScrService scrService;
55
56 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
57 protected ClusterAdminService clusterAdminService;
58
59 private BundleContext bundleContext;
60 private ScheduledFuture<?> poller;
61
62 @Activate
63 protected void activate(ComponentContext context) {
64 bundleContext = context.getBundleContext();
65 poller = SharedScheduledExecutors.getSingleThreadExecutor()
66 .scheduleAtFixedRate(this::checkStartedState, PERIOD,
67 PERIOD, TimeUnit.MILLISECONDS);
68 log.info("Started");
69 }
70
71 @Deactivate
72 protected void deactivate() {
73 poller.cancel(false);
74 log.info("Stopped");
75 }
76
77 private void checkStartedState() {
78 clusterAdminService.markFullyStarted(isFullyStarted());
79 }
80
81 /**
82 * Scans the system to make sure that all bundles and their components
83 * are fully started.
84 *
85 * @return true if all bundles and their components are active
86 */
87 private boolean isFullyStarted() {
88 for (Feature feature : featuresService.listInstalledFeatures()) {
89 if (!isFullyStarted(feature)) {
90 return false;
91 }
92 }
93 return true;
94 }
95
96 private boolean isFullyStarted(Feature feature) {
Ray Milkeyf13feb82016-08-30 10:38:59 -070097 try {
98 return feature.getBundles().stream()
99 .map(info -> bundleContext.getBundle(info.getLocation()))
100 .allMatch(this::isFullyStarted);
101 } catch (NullPointerException npe) {
102 // FIXME: Remove this catch block when Felix fixes the bug
103 // Due to a bug in the Felix implementation, this can throw an NPE.
104 // Catch the error and do something sensible with it.
105 return false;
106 }
Thomas Vachuska7a8de842016-03-07 20:56:35 -0800107 }
108
109 private boolean isFullyStarted(Bundle bundle) {
110 Component[] components = scrService.getComponents(bundle);
111 if (components != null) {
112 for (Component component : components) {
113 if (!isFullyStarted(component)) {
114 return false;
115 }
116 }
117 }
118 return true;
119 }
120
121 private boolean isFullyStarted(Component component) {
122 int state = component.getState();
123 return state == Component.STATE_ACTIVE || state == Component.STATE_DISABLED ||
124 (state == Component.STATE_REGISTERED && !component.isImmediate());
125 }
126
127}