blob: 7b14644f51fedcc1af3a24e54c0141752907ee90 [file] [log] [blame]
Jorge Hernandezae4a9352017-07-18 01:06:39 -05001#! /bin/bash
2
3###
4# ============LICENSE_START=======================================================
5# ONAP POLICY
6# ================================================================================
7# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
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# ============LICENSE_END=========================================================
21##
22
23# #############################################################
24# Features Directory Layout:
25#
26# POLICY_HOME/
27# └── features/
28# └── <feature-name>*/
29#     └── [config]/
30#     │   └── <config-file>*
31#     └── lib/
32#     │  └── [dependencies]/
33#     │  │ └── <dependent-jar>*
34#     │  └── feature/
35#     │  └── <feature-jar>
36#     └── [install]
37#      └── [enable]
38#      └── [disable]
39#      └── [other-future-operations]
40#      └── [other-files]
41#
42# <feature-name> directory should not have the "feature-" prefix.
43# <config-file> preferable with "feature-" prefix.
44#
45# Example:
46#
47# POLICY_HOME/
48# └── features/
49# ├── eelf/
50# │   ├── config/
51# │   │   ├── logback-eelf.xml
52# │   └── lib/
53# │   │ └── dependencies/
54# │   │ │ └── ECOMP-Logging-1.1.0-SNAPSHOT.jar
55# │   │ │ └── eelf-core-1.0.0.jar
56# │   │ └── feature/
57# │   │ └── feature-eelf-1.1.0-SNAPSHOT.jar
58# │   └── install/
59# │   └── enable
60# │   └── disable
61# └── healthcheck/
62# ├── config/
63# │   └── feature-healthcheck.properties
64# └── lib/
65# └── feature/
66# └── feature-healthcheck-1.1.0-SNAPSHOT.jar
67# #############################################################
68
69if [[ ${DEBUG} == y ]]; then
70 echo "-- MAIN --"
71 set -x
72fi
73
74# The directories at play
75
76LIB=${POLICY_HOME}/lib
77CONFIG=${POLICY_HOME}/config
78FEATURES=${POLICY_HOME}/features
79
80if [[ ! ( -d "${LIB}" && -x "${LIB}" ) ]]; then
81 echo "ERROR: no ${LIB} directory"
82 exit 1
83fi
84
85if [[ ! ( -d "${CONFIG}" && -x "${CONFIG}" ) ]]; then
86 echo "ERROR: no ${CONFIG} directory"
87 exit 2
88fi
89
90if [[ ! ( -d "${FEATURES}" && -x "${FEATURES}" ) ]]; then
91 echo "ERROR: no ${FEATURES} directory"
92 exit 3
93fi
94
95# relative per Feature Directory Paths
96
97FEATURE_DEPS="lib/dependencies"
98FEATURE_LIB="lib/feature"
99FEATURE_CONFIG="config"
100FEATURE_INSTALL="install"
101
102featureJars=$(find "${FEATURES}" -name "feature-*.jar" -type f -exec basename {} \; 2> /dev/null)
103if [[ -z ${featureJars} ]]; then
104 echo "no features"
105 usage
106 exit 0
107fi
108
109# default field lengths
110nameLength=20
111versionLength=15
112
113# update field lengths, if needed
114for jar in ${featureJars} ; do
115 # get file name without 'jar' suffix
116 tmp="${jar%\.jar}"
117
118 # remove feature prefix
119 tmp="${tmp#feature-}"
120
121 # get feature name by removing the version portion
122 name="${tmp%%-[0-9]*}"
123
124 # extract version portion of name
125 version="${tmp#${name}-}"
126
127 # grow the size of the name/version field, if needed
128 if (( "${#name}" > nameLength )) ; then
129 nameLength="${#name}"
130 fi
131 if (( "${#version}" > versionLength )) ; then
132 versionLength="${#version}"
133 fi
134done
135
136# ##########################################################
137# usage: usage information
138# ##########################################################
139function usage
140{
141 # print out usage information
142 cat >&2 <<-'EOF'
143 Usage: features status
144 Get enabled/disabled status on all features
145 features enable <feature> ...
146 Enable the specified feature
147 features disable <feature> ...
148 Disable the specified feature
149 EOF
150}
151
152# ##########################################################
153# status: dump out status information
154# ##########################################################
155function status
156{
157 if [[ ${DEBUG} == y ]]; then
158 echo "-- ${FUNCNAME[0]} $@ --"
159 set -x
160 fi
161
162 local tmp name version status
163 local format="%-${nameLength}s %-${versionLength}s %s\n"
164
165 printf "${format}" "name" "version" "status"
166 printf "${format}" "----" "-------" "------"
167
168 for jar in ${featureJars} ; do
169 # get file name without 'jar' suffix
170 tmp="${jar%\.jar}"
171
172 # remove feature prefix
173 tmp="${tmp#feature-}"
174
175 # get feature name by removing the version portion
176 name="${tmp%%-[0-9]*}"
177
178 # extract version portion of name
179 version="${tmp#${name}-}"
180
181 # determine status
182 status=disabled
183 if [[ -e "${LIB}/${jar}" ]] ; then
184 status=enabled
185 fi
186 printf "${format}" "${name}" "${version}" "${status}"
187 done
188}
189
190# ##########################################################
191# depEnableAnalysis(featureName):
192# reports on potential dependency conflicts
193# featureName: name of the feature
194# ##########################################################
195function depEnableAnalysis()
196{
197 if [[ ${DEBUG} == y ]]; then
198 echo "-- ${FUNCNAME[0]} $@ --"
199 set -x
200 fi
201
202 local featureName="$1"
203 local featureDepJars featureDepJarPath depJarName multiVersionJars
204
205 if [[ -z ${featureName} ]]; then
206 echo "WARN: no feature name"
207 return 1
208 fi
209
210 featureDepJars=$(ls "${FEATURES}"/"${featureName}"/"${FEATURE_DEPS}"/*.jar 2> /dev/null)
211 for featureDepJarPath in ${featureDepJars}; do
212 depJarName=$(basename "${featureDepJarPath}")
213
214 # it could be a base jar
215
216 if [[ -f "${LIB}"/"${depJarName}" ]]; then
217 echo "WARN: dependency ${depJarName} already in use"
218 continue
219 fi
220
221 # it could be a link from another feature
222
223 if [[ -L "${LIB}"/"${depJarName}" ]]; then
224 continue
225 fi
226
227 # unadvisable if multiple versions exist
228
229 multiVersionJars=$(ls "${LIB}"/"${depJarName%%-[0-9]*.jar}"-*.jar 2> /dev/null)
230 if [[ -n "${multiVersionJars}" ]]; then
231 echo "WARN: other version of library ${depJarName} present: ${multiVersionJars}"
232 return 2
233 fi
234 done
235}
236
237# ##########################################################
238# configEnableAnalysis(featureName):
239# reports on potential dependency conflicts
240# featureName: name of the feature
241# ##########################################################
242function configEnableAnalysis()
243{
244 if [[ ${DEBUG} == y ]]; then
245 echo "-- ${FUNCNAME[0]} $@ --"
246 set -x
247 fi
248
249 local featureName="$1"
250 local featureConfigs configPath configFileName
251
252 if [[ -z ${featureName} ]]; then
253 echo "WARN: no feature name"
254 return 1
255 fi
256
257 featureConfigs=$(ls "${FEATURES}"/"${featureName}"/"${FEATURE_CONFIG}"/ 2> /dev/null)
258 for configPath in ${featureConfigs}; do
259 configFileName=$(basename "${configPath}")
260 if [[ -e "${LIB}"/"${configFileName}" ]]; then
261 echo "ERROR: a config file of the same name is already in the base: ${configFileName}"
262 return 2
263 fi
264 done
265}
266
267# ##########################################################
268# enableFeatureDeps(featureName):
269# enables feature dependencies
270# featureName: name of the feature
271# ##########################################################
272function enableFeatureDeps()
273{
274 if [[ ${DEBUG} == y ]]; then
275 echo "-- ${FUNCNAME[0]} $@ --"
276 set -x
277 fi
278
279 local featureName="$1"
280 local featureDeps featureDepPath depJarName
281
282 if [[ -z ${featureName} ]]; then
283 echo "WARN: no feature name"
284 return 1
285 fi
286
287 featureDeps=$(ls "${FEATURES}"/"${featureName}"/"${FEATURE_DEPS}"/*.jar 2> /dev/null)
288 for featureDepPath in ${featureDeps}; do
289 depJarName=$(basename "${featureDepPath}")
290 if [[ ! -f "${LIB}"/"${depJarName}" ]]; then
291 ln -s -f "${featureDepPath}" "${LIB}/"
292 fi
293 done
294}
295
296# ##########################################################
297# enableFeatureConfig(featureName):
298# enables feature configuration
299# featureName: name of the feature
300# ##########################################################
301function enableFeatureConfig()
302{
303 if [[ ${DEBUG} == y ]]; then
304 echo "-- ${FUNCNAME[0]} $@ --"
305 set -x
306 fi
307
308 local featureName="$1"
309 local featureConfigs featureConfigPath
310
311 if [[ -z ${featureName} ]]; then
312 echo "WARN: no feature name"
313 return 1
314 fi
315
316 featureConfigs=$(find "${FEATURES}"/"${featureName}"/"${FEATURE_CONFIG}"/ -type f -maxdepth 1 2> /dev/null)
317 for featureConfigPath in ${featureConfigs}; do
318 ln -s -f "${featureConfigPath}" "${CONFIG}/"
319 done
320}
321
322# ##########################################################
323# enableFeatureOp(featureName): 'enable' feature operation
324# featureName: name of the feature
325# ##########################################################
326function enableFeatureOp()
327{
328 if [[ ${DEBUG} == y ]]; then
329 echo "-- ${FUNCNAME[0]} $@ --"
330 set -x
331 fi
332
333 local featureName="$1"
334
335 if [[ -z ${featureName} ]]; then
336 echo "WARN: no feature name"
337 return 1
338 fi
339
340 enableScript="${FEATURES}"/"${featureName}"/"${FEATURE_INSTALL}"/enable
341 if [[ -f ${enableScript} ]]; then
342 (
343 cd "${FEATURES}"/"${featureName}"/"${FEATURE_INSTALL}"
344 chmod u+x enable
345 ./enable
346 )
347 fi
348}
349
350# ##########################################################
351# enableFeature(featureName, featureJar): enables a feature
352# featureName: name of the feature
353# featureJar: path to feature jar implementation
354# ##########################################################
355function enableFeature()
356{
357 if [[ $DEBUG == y ]]; then
358 echo "-- ${FUNCNAME[0]} $@ --"
359 set -x
360 fi
361
362 local featureName="$1"
363 local featureJar="$2"
364
365 if [[ -z ${featureName} ]]; then
366 echo "WARN: no feature name"
367 return 1
368 fi
369
370 if [[ -z ${featureJar} ]]; then
371 echo "WARN: no feature jar"
372 return 2
373 fi
374
375 if ! depEnableAnalysis "${featureName}"; then
376 return 3
377 fi
378
379 if ! configEnableAnalysis "${featureName}"; then
380 return 4
381 fi
382
383 # enable feature itself
384
385 ln -s -f "${featureJar}" "${LIB}/"
386
387 # enable dependent libraries if any
388
389 enableFeatureDeps "${featureName}"
390
391 # enable configuration
392
393 enableFeatureConfig "${featureName}"
394
395 # TODO: run feature install DB scripts if any
396
397 # run custom enable if any
398
399 enableFeatureOp "${featureName}"
400}
401
402# ##########################################################
403# disableFeatureDeps(featureName):
404# disables feature dependencies
405# ##########################################################
406function disableFeatureDeps()
407{
408 if [[ ${DEBUG} == y ]]; then
409 echo "-- ${FUNCNAME[0]} $@ --"
410 set -x
411 fi
412
413 local featureName="$1"
414 local xDepsEnabledMap featureBaseDirs aFeatureDir aFeatureName
415 local featureDeps aFeatureDep
416 local depJarPath depJarName depJarRealPath
417
418 if [[ -z ${featureName} ]]; then
419 echo "WARN: no feature name"
420 return 1
421 fi
422
423 declare -A xDepsEnabledMap
424
425 featureBaseDirs=$(ls -d "${FEATURES}"/*/ 2> /dev/null)
426 for aFeatureDir in ${featureBaseDirs}; do
427 aFeatureName=$(basename "${aFeatureDir}")
428 if [[ "${aFeatureName}" == "${featureName}" ]]; then
429 continue
430 fi
431
432 depJarPaths=$(ls "${aFeatureDir}"/"${FEATURE_DEPS}"/*.jar 2> /dev/null)
433 for depJarPath in ${depJarPaths}; do
434 if [[ "$?" == 0 ]] ; then
435 depJarName=$(basename "${depJarPath}")
436 xDepsEnabledMap[${depJarName}]="${depJarPath}"
437 fi
438 done
439 done
440
441 if [[ ${DEBUG} == y ]]; then
442 echo "${!xDepsEnabledMap[@]}"
443 echo "${xDepsEnabledMap[@]}"
444 fi
445
446 featureDeps=$(ls "${FEATURES}"/"${featureName}"/"${FEATURE_DEPS}"/*.jar 2> /dev/null)
447 for aFeatureDep in ${featureDeps}; do
448 depJarName=$(basename "${aFeatureDep}")
449 if [[ -L "${LIB}"/"${depJarName}" ]]; then
450 depJarRealPath=$(readlink -f "${LIB}"/"${depJarName}")
451 if [[ "${depJarRealPath}" == "${aFeatureDep}" ]]; then
452 rm -f "${LIB}"/"${depJarName}"
453
454 # case there were multiple features using this library
455 # re-enable link fron an enabled feature
456
457 if [[ -n ${xDepsEnabledMap[${depJarName}]} ]]; then
458 ln -s -f "${xDepsEnabledMap[${depJarName}]}" "${LIB}/"
459 fi
460 fi
461 fi
462 done
463}
464
465# ##########################################################
466# disableFeatureConfig(featureName):
467# disables feature configuration
468# featureName: name of the feature
469# ##########################################################
470function disableFeatureConfig()
471{
472 if [[ ${DEBUG} == y ]]; then
473 echo "-- ${FUNCNAME[0]} $@ --"
474 set -x
475 fi
476
477 local featureName="$1"
478 local featureConfigs featureConfigPath
479
480 if [[ -z ${featureName} ]]; then
481 echo "WARN: no feature name"
482 return 1
483 fi
484
485 featureConfigs=$(find "${FEATURES}"/"${featureName}"/"${FEATURE_CONFIG}"/ -type f -maxdepth 1 2> /dev/null)
486 for featureConfigPath in ${featureConfigs}; do
487 configFileName=$(basename "${featureConfigPath}")
488 rm -f "${CONFIG}"/"${configFileName}" 2> /dev/null
489 done
490}
491
492# ##########################################################
493# disableFeatureOp(featureName): 'enable' feature operation
494# featureName: name of the feature
495# ##########################################################
496function disableFeatureOp()
497{
498 if [[ ${DEBUG} == y ]]; then
499 echo "-- ${FUNCNAME[0]} $@ --"
500 set -x
501 fi
502
503 local featureName="$1"
504
505 if [[ -z ${featureName} ]]; then
506 echo "WARN: no feature name"
507 return 1
508 fi
509
510 disableScript="${FEATURES}"/"${featureName}"/"${FEATURE_INSTALL}"/disable
511 if [[ -f ${disableScript} ]]; then
512 (
513 cd "${FEATURES}"/"${featureName}"/"${FEATURE_INSTALL}"
514 chmod u+x disable
515 ./disable
516 )
517 fi
518}
519
520# ##########################################################
521# disableFeature(featureName, featureJar): enables a feature
522# featureName: name of the feature
523# ##########################################################
524function disableFeature()
525{
526 if [[ ${DEBUG} == y ]]; then
527 echo "-- ${FUNCNAME[0]} $@ --"
528 set -x
529 fi
530
531 local featureName="$1"
532
533 if [[ -z ${featureName} ]]; then
534 echo "WARN: no feature name"
535 return
536 fi
537
538 # disable feature itself
539
540 (
541 cd "${LIB}"
542 rm -f feature-"${featureName}"-[0-9]*.jar 2> /dev/null
543 )
544
545 # disable dependencies if any
546
547 disableFeatureDeps "${featureName}"
548
549 # disable configuration if any
550
551 disableFeatureConfig "${featureName}"
552
553 # run feature uninstall DB scripts if any
554 # TODO: future
555
556 # run custom disable if any
557 disableFeatureOp "${featureName}"
558}
559
560case "$1" in
561 status)
562 {
563 # dump out status information
564 status
565 };;
566
567 enable)
568 {
569 if [[ -f "${POLICY_HOME}"/PID ]]; then
570 echo "ERROR: enable: not allowed when policy is running .."
571 echo
572 status
573 exit 10
574 fi
575
576 # enable the specified options
577 shift
578 match=
579 for name in "$@" ; do
580 # look for matches - 'file' has the full path name
581 file=$(ls "${FEATURES}"/"${name}"/"${FEATURE_LIB}"/feature-"${name}"-[0-9]*.jar 2> /dev/null)
582 if [[ "$?" != 0 ]] ; then
583 # no matching file
584 echo "${name}: no such option"
585 else
586 # make sure there is only one feature jar
587 countFeatureJars=$(echo "${file}" | wc -w)
588 if [[ ${countFeatureJars} != 1 ]]; then
589 echo "WARNING: skipping ${name}, ${countFeatureJars} feature libraries found"
590 continue
591 fi
592
593 # found a match (handle multiple matches, just in case)
594 match=true
595
596 enableFeature "${name}" "${file}"
597 fi
598 done
599 if [[ "${match}" ]] ; then
600 echo
601 status
602 fi
603 };;
604
605 disable)
606 {
607 if [[ -f "${POLICY_HOME}"/PID ]]; then
608 echo "ERROR: disable: not allowed when policy is running .."
609 echo
610 status
611 exit 11
612 fi
613
614 # disable the specified options
615 shift
616 match=
617 for name in "$@" ; do
618 # look for matches -- 'file' has the last segment of the path name
619 file=$(ls "${FEATURES}"/"${name}"/"${FEATURE_LIB}"/feature-"${name}"-[0-9]*.jar 2> /dev/null)
620 if [[ "$?" != 0 ]] ; then
621 echo "${name}: no such option"
622 else
623 # found a match (handle multiple matches, just in case)
624 match=true
625
626 disableFeature "${name}"
627 fi
628 done
629 if [[ "${match}" ]] ; then
630 echo
631 status
632 fi
633 };;
634
635 *)
636 {
637 usage
638 };;
639esac
640exit