Browse code

Allow devstack plugins to specify prereq packages

We offer main devstack components the ability to install their own
system package preqreqs via files/{debs, rpms}/$service. This adds
similar functionality for plugins, who can now do the same in their
own tree at ./devstack/files/{debs, rpms}/$plugin.

Change-Id: I63af8dc54c75a6e80ca4b2a96c76233a0795aabb

Adam Gandelman authored on 2015/03/05 10:25:07
Showing 3 changed files
... ...
@@ -154,3 +154,24 @@ functions:
154 154
 -  ``start_nova_hypervisor`` - start any external services
155 155
 -  ``stop_nova_hypervisor`` - stop any external services
156 156
 -  ``cleanup_nova_hypervisor`` - remove transient data and cache
157
+
158
+System Packages
159
+===============
160
+
161
+Devstack provides a framework for getting packages installed at an early
162
+phase of its execution. This packages may be defined in a plugin as files
163
+that contain new-line separated lists of packages required by the plugin
164
+
165
+Supported packaging systems include apt and yum across multiple distributions.
166
+To enable a plugin to hook into this and install package dependencies, packages
167
+may be listed at the following locations in the top-level of the plugin
168
+repository:
169
+
170
+- ``./devstack/files/debs/$plugin_name`` - Packages to install when running
171
+  on Ubuntu, Debian or Linux Mint.
172
+
173
+- ``./devstack/files/rpms/$plugin_name`` - Packages to install when running
174
+  on Red Hat, Fedora, CentOS or XenServer.
175
+
176
+- ``./devstack/files/rpms-suse/$plugin_name`` - Packages to install when
177
+  running on SUSE Linux or openSUSE.
... ...
@@ -973,13 +973,18 @@ function get_or_create_endpoint {
973 973
 
974 974
 # _get_package_dir
975 975
 function _get_package_dir {
976
+    local base_dir=$1
976 977
     local pkg_dir
978
+
979
+    if [[ -z "$base_dir" ]]; then
980
+        base_dir=$FILES
981
+    fi
977 982
     if is_ubuntu; then
978
-        pkg_dir=$FILES/debs
983
+        pkg_dir=$base_dir/debs
979 984
     elif is_fedora; then
980
-        pkg_dir=$FILES/rpms
985
+        pkg_dir=$base_dir/rpms
981 986
     elif is_suse; then
982
-        pkg_dir=$FILES/rpms-suse
987
+        pkg_dir=$base_dir/rpms-suse
983 988
     else
984 989
         exit_distro_not_supported "list of packages"
985 990
     fi
... ...
@@ -1005,6 +1010,59 @@ function apt_get {
1005 1005
         apt-get --option "Dpkg::Options::=--force-confold" --assume-yes "$@"
1006 1006
 }
1007 1007
 
1008
+function _parse_package_files {
1009
+    local files_to_parse=$@
1010
+
1011
+    if [[ -z "$DISTRO" ]]; then
1012
+        GetDistro
1013
+    fi
1014
+
1015
+    for fname in ${files_to_parse}; do
1016
+        local OIFS line package distros distro
1017
+        [[ -e $fname ]] || continue
1018
+
1019
+        OIFS=$IFS
1020
+        IFS=$'\n'
1021
+        for line in $(<${fname}); do
1022
+            if [[ $line =~ "NOPRIME" ]]; then
1023
+                continue
1024
+            fi
1025
+
1026
+            # Assume we want this package
1027
+            package=${line%#*}
1028
+            inst_pkg=1
1029
+
1030
+            # Look for # dist:xxx in comment
1031
+            if [[ $line =~ (.*)#.*dist:([^ ]*) ]]; then
1032
+                # We are using BASH regexp matching feature.
1033
+                package=${BASH_REMATCH[1]}
1034
+                distros=${BASH_REMATCH[2]}
1035
+                # In bash ${VAR,,} will lowecase VAR
1036
+                # Look for a match in the distro list
1037
+                if [[ ! ${distros,,} =~ ${DISTRO,,} ]]; then
1038
+                    # If no match then skip this package
1039
+                    inst_pkg=0
1040
+                fi
1041
+            fi
1042
+
1043
+            # Look for # testonly in comment
1044
+            if [[ $line =~ (.*)#.*testonly.* ]]; then
1045
+                package=${BASH_REMATCH[1]}
1046
+                # Are we installing test packages? (test for the default value)
1047
+                if [[ $INSTALL_TESTONLY_PACKAGES = "False" ]]; then
1048
+                    # If not installing test packages the skip this package
1049
+                    inst_pkg=0
1050
+                fi
1051
+            fi
1052
+
1053
+            if [[ $inst_pkg = 1 ]]; then
1054
+                echo $package
1055
+            fi
1056
+        done
1057
+        IFS=$OIFS
1058
+    done
1059
+}
1060
+
1008 1061
 # get_packages() collects a list of package names of any type from the
1009 1062
 # prerequisite files in ``files/{debs|rpms}``.  The list is intended
1010 1063
 # to be passed to a package installer such as apt or yum.
... ...
@@ -1029,103 +1087,76 @@ function get_packages {
1029 1029
         echo "No package directory supplied"
1030 1030
         return 1
1031 1031
     fi
1032
-    if [[ -z "$DISTRO" ]]; then
1033
-        GetDistro
1034
-    fi
1035 1032
     for service in ${services//,/ }; do
1036 1033
         # Allow individual services to specify dependencies
1037 1034
         if [[ -e ${package_dir}/${service} ]]; then
1038
-            file_to_parse="${file_to_parse} $service"
1035
+            file_to_parse="${file_to_parse} ${package_dir}/${service}"
1039 1036
         fi
1040 1037
         # NOTE(sdague) n-api needs glance for now because that's where
1041 1038
         # glance client is
1042 1039
         if [[ $service == n-api ]]; then
1043 1040
             if [[ ! $file_to_parse =~ nova ]]; then
1044
-                file_to_parse="${file_to_parse} nova"
1041
+                file_to_parse="${file_to_parse} ${package_dir}/nova"
1045 1042
             fi
1046 1043
             if [[ ! $file_to_parse =~ glance ]]; then
1047
-                file_to_parse="${file_to_parse} glance"
1044
+                file_to_parse="${file_to_parse} ${package_dir}/glance"
1048 1045
             fi
1049 1046
         elif [[ $service == c-* ]]; then
1050 1047
             if [[ ! $file_to_parse =~ cinder ]]; then
1051
-                file_to_parse="${file_to_parse} cinder"
1048
+                file_to_parse="${file_to_parse} ${package_dir}/cinder"
1052 1049
             fi
1053 1050
         elif [[ $service == ceilometer-* ]]; then
1054 1051
             if [[ ! $file_to_parse =~ ceilometer ]]; then
1055
-                file_to_parse="${file_to_parse} ceilometer"
1052
+                file_to_parse="${file_to_parse} ${package_dir}/ceilometer"
1056 1053
             fi
1057 1054
         elif [[ $service == s-* ]]; then
1058 1055
             if [[ ! $file_to_parse =~ swift ]]; then
1059
-                file_to_parse="${file_to_parse} swift"
1056
+                file_to_parse="${file_to_parse} ${package_dir}/swift"
1060 1057
             fi
1061 1058
         elif [[ $service == n-* ]]; then
1062 1059
             if [[ ! $file_to_parse =~ nova ]]; then
1063
-                file_to_parse="${file_to_parse} nova"
1060
+                file_to_parse="${file_to_parse} ${package_dir}/nova"
1064 1061
             fi
1065 1062
         elif [[ $service == g-* ]]; then
1066 1063
             if [[ ! $file_to_parse =~ glance ]]; then
1067
-                file_to_parse="${file_to_parse} glance"
1064
+                file_to_parse="${file_to_parse} ${package_dir}/glance"
1068 1065
             fi
1069 1066
         elif [[ $service == key* ]]; then
1070 1067
             if [[ ! $file_to_parse =~ keystone ]]; then
1071
-                file_to_parse="${file_to_parse} keystone"
1068
+                file_to_parse="${file_to_parse} ${package_dir}/keystone"
1072 1069
             fi
1073 1070
         elif [[ $service == q-* ]]; then
1074 1071
             if [[ ! $file_to_parse =~ neutron ]]; then
1075
-                file_to_parse="${file_to_parse} neutron"
1072
+                file_to_parse="${file_to_parse} ${package_dir}/neutron"
1076 1073
             fi
1077 1074
         elif [[ $service == ir-* ]]; then
1078 1075
             if [[ ! $file_to_parse =~ ironic ]]; then
1079
-                file_to_parse="${file_to_parse} ironic"
1076
+                file_to_parse="${file_to_parse} ${package_dir}/ironic"
1080 1077
             fi
1081 1078
         fi
1082 1079
     done
1080
+    echo "$(_parse_package_files $file_to_parse)"
1081
+    $xtrace
1082
+}
1083 1083
 
1084
-    for file in ${file_to_parse}; do
1085
-        local fname=${package_dir}/${file}
1086
-        local OIFS line package distros distro
1087
-        [[ -e $fname ]] || continue
1088
-
1089
-        OIFS=$IFS
1090
-        IFS=$'\n'
1091
-        for line in $(<${fname}); do
1092
-            if [[ $line =~ "NOPRIME" ]]; then
1093
-                continue
1094
-            fi
1095
-
1096
-            # Assume we want this package
1097
-            package=${line%#*}
1098
-            inst_pkg=1
1099
-
1100
-            # Look for # dist:xxx in comment
1101
-            if [[ $line =~ (.*)#.*dist:([^ ]*) ]]; then
1102
-                # We are using BASH regexp matching feature.
1103
-                package=${BASH_REMATCH[1]}
1104
-                distros=${BASH_REMATCH[2]}
1105
-                # In bash ${VAR,,} will lowecase VAR
1106
-                # Look for a match in the distro list
1107
-                if [[ ! ${distros,,} =~ ${DISTRO,,} ]]; then
1108
-                    # If no match then skip this package
1109
-                    inst_pkg=0
1110
-                fi
1111
-            fi
1112
-
1113
-            # Look for # testonly in comment
1114
-            if [[ $line =~ (.*)#.*testonly.* ]]; then
1115
-                package=${BASH_REMATCH[1]}
1116
-                # Are we installing test packages? (test for the default value)
1117
-                if [[ $INSTALL_TESTONLY_PACKAGES = "False" ]]; then
1118
-                    # If not installing test packages the skip this package
1119
-                    inst_pkg=0
1120
-                fi
1121
-            fi
1122
-
1123
-            if [[ $inst_pkg = 1 ]]; then
1124
-                echo $package
1125
-            fi
1126
-        done
1127
-        IFS=$OIFS
1084
+# get_plugin_packages() collects a list of package names of any type from a
1085
+# plugin's prerequisite files in ``$PLUGIN/devstack/files/{debs|rpms}``.  The
1086
+# list is intended to be passed to a package installer such as apt or yum.
1087
+#
1088
+# Only packages required for enabled and collected plugins will included.
1089
+#
1090
+# The same metadata used in the main devstack prerequisite files may be used
1091
+# in these prerequisite files, see get_packages() for more info.
1092
+function get_plugin_packages {
1093
+    local xtrace=$(set +o | grep xtrace)
1094
+    set +o xtrace
1095
+    local files_to_parse=""
1096
+    local package_dir=""
1097
+    for plugin in ${DEVSTACK_PLUGINS//,/ }; do
1098
+        local package_dir="$(_get_package_dir ${GITDIR[$plugin]}/devstack/files)"
1099
+        files_to_parse+="$package_dir/$plugin"
1128 1100
     done
1101
+    echo "$(_parse_package_files $files_to_parse)"
1129 1102
     $xtrace
1130 1103
 }
1131 1104
 
... ...
@@ -62,6 +62,8 @@ export_proxy_variables
62 62
 
63 63
 # Install package requirements
64 64
 PACKAGES=$(get_packages general $ENABLED_SERVICES)
65
+PACKAGES="$PACKAGES $(get_plugin_packages)"
66
+
65 67
 if is_ubuntu && echo $PACKAGES | grep -q dkms ; then
66 68
     # ensure headers for the running kernel are installed for any DKMS builds
67 69
     PACKAGES="$PACKAGES linux-headers-$(uname -r)"