diff options
| author | Mark Asselstine <mark.asselstine@windriver.com> | 2017-01-09 10:04:10 -0500 |
|---|---|---|
| committer | Bruce Ashfield <bruce.ashfield@windriver.com> | 2017-01-09 12:23:58 -0500 |
| commit | 0d6067258d09fdd47c95828e5e0e9b0f9987a529 (patch) | |
| tree | dbce7395b11e577bbcd633fa0daeae24697df42e /meta-openstack/classes | |
| parent | 96dd0da3edc2f56de99d84ef96effdbf366a3041 (diff) | |
| download | meta-cloud-services-0d6067258d09fdd47c95828e5e0e9b0f9987a529.tar.gz | |
chef: remove the use of chef
The use of chef was never complete, had isses with updating binary
database files and had a cumbersome implementation. Since we are using
Ansible in meta-overc we are dropping the use of chef here and will
look to being at par with meta-overc by using Ansible if/when we get
time to look at runtime configuration in meta-cloud-services.
Signed-off-by: Mark Asselstine <mark.asselstine@windriver.com>
Signed-off-by: Bruce Ashfield <bruce.ashfield@windriver.com>
Diffstat (limited to 'meta-openstack/classes')
| -rw-r--r-- | meta-openstack/classes/openstack-base.bbclass | 2 | ||||
| -rw-r--r-- | meta-openstack/classes/openstackchef.bbclass | 115 | ||||
| -rw-r--r-- | meta-openstack/classes/openstackchef_inc.bbclass | 831 |
3 files changed, 1 insertions, 947 deletions
diff --git a/meta-openstack/classes/openstack-base.bbclass b/meta-openstack/classes/openstack-base.bbclass index 718aa1c..05dfdf1 100644 --- a/meta-openstack/classes/openstack-base.bbclass +++ b/meta-openstack/classes/openstack-base.bbclass | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | inherit hosts openstackchef | 1 | inherit hosts |
| 2 | 2 | ||
| 3 | ROOTFS_POSTPROCESS_COMMAND += "openstack_configure_hosts ; " | 3 | ROOTFS_POSTPROCESS_COMMAND += "openstack_configure_hosts ; " |
| 4 | 4 | ||
diff --git a/meta-openstack/classes/openstackchef.bbclass b/meta-openstack/classes/openstackchef.bbclass deleted file mode 100644 index c2e4a40..0000000 --- a/meta-openstack/classes/openstackchef.bbclass +++ /dev/null | |||
| @@ -1,115 +0,0 @@ | |||
| 1 | # openstackchef.bbclass | ||
| 2 | # Copyright (c) 2014 Wind River Systems, Inc. | ||
| 3 | # | ||
| 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 5 | # of this software and associated documentation files (the "Software"), to | ||
| 6 | # deal | ||
| 7 | # in the Software without restriction, including without limitation the rights | ||
| 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | # copies of the Software, and to permit persons to whom the Software is | ||
| 10 | # furnished to do so, subject to the following conditions: | ||
| 11 | # | ||
| 12 | # The above copyright notice and this permission notice shall be included in | ||
| 13 | # all copies or substantial portions of the Software. | ||
| 14 | # | ||
| 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| 20 | # FROM, | ||
| 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 22 | # THE SOFTWARE. | ||
| 23 | # | ||
| 24 | # | ||
| 25 | # This class provides a framework for openstack services like python-neutron | ||
| 26 | # or python-nova to register their configuration files so that they can be | ||
| 27 | # recreated at run-time by chef-solo. Inheriting | ||
| 28 | # this class involves exposing configuration files from which this class | ||
| 29 | # creates chef-solo templates. These template files are later used by chef-solo | ||
| 30 | # to recreate the configuration files. | ||
| 31 | # | ||
| 32 | # For the templates files to be created, the recipes are expected | ||
| 33 | # to define the following variables variables: | ||
| 34 | # | ||
| 35 | # SRCNAME: | ||
| 36 | # This is the name of the package, neutron for example for the package | ||
| 37 | # python-neutron. It's appended to the names of template files and also | ||
| 38 | # used in the creation of package based temporary files. A default value | ||
| 39 | # of ${BPN} is assigned to this variable when it's not defined by recipes | ||
| 40 | # inheriting class. | ||
| 41 | # | ||
| 42 | # CHEF_SERVICES_CONF_FILES | ||
| 43 | # | ||
| 44 | # This variable provides the list of configuration files | ||
| 45 | # exposed to this class by the recipes inheriting the class. | ||
| 46 | # These files are expected to be in the image( ${D}) directory, though ${D} | ||
| 47 | # directory is excluded from the file name. Definition of this variable | ||
| 48 | # by recipe files is optional. | ||
| 49 | # eg. | ||
| 50 | # CHEF_SERVICES_CONF_FILES="\ | ||
| 51 | # ${sysconfdir}/chef/neutron/plugins/linuxbridge/linuxbridge_conf.ini.rb \ | ||
| 52 | # ${sysconfdir}/chef/neutron/neutron.conf | ||
| 53 | # " | ||
| 54 | # | ||
| 55 | #INITSCRIPT_PACKAGES | ||
| 56 | #This variable provides a mechanism for recipes inheriting this class | ||
| 57 | #to provide a list of services to start/stop when their configuration files | ||
| 58 | #are recreated on disk. | ||
| 59 | #This variable is assumed to be provided by all recipes that register a set | ||
| 60 | #of configuration files with this class. Failing to do so will lead to | ||
| 61 | #service not reloading the newly created configuration file(s) at run-time. | ||
| 62 | # | ||
| 63 | # | ||
| 64 | #INITSCRIPT_NAME_x or INITSCRIPT_NAME | ||
| 65 | #This variable is also assumed to be set by recipes inheriting this class. | ||
| 66 | #It specifies the names of the services to start/stop as specified above. | ||
| 67 | #Like the variable immediately above, failure to provide this variable will | ||
| 68 | #lead to mis-configuration of the service at run-time. | ||
| 69 | # | ||
| 70 | # | ||
| 71 | #INITSCRIPT_PARAMS_x or INITSCRIPT_PARAMS | ||
| 72 | #Like the last two variable above, this variable is also assumed to be set | ||
| 73 | #by recipes inheriting this class. It is used to extract the run-level | ||
| 74 | #priority of the INITSCRIPT_NAME variable(s). Unlike, the previous two | ||
| 75 | #variables, a default run-level is assigned to the script when this variable | ||
| 76 | #defaults to the string 'default' | ||
| 77 | # | ||
| 78 | # | ||
| 79 | # CHEF_SERVICES_SPECIAL_FUNC | ||
| 80 | # This variable is optional, and is the name of a shell callback function. | ||
| 81 | # Unlike the placeholder/value substitution which this class does, | ||
| 82 | # there are times when recipes need to do more than a simple placeholder/ | ||
| 83 | # value substitution. This is made possible with the use of the callback | ||
| 84 | # function. | ||
| 85 | # The callback function should be defined by the recipe(s) inheriting | ||
| 86 | # this class. When this variable is defined, this class will call the | ||
| 87 | # callback function and pass it the name of the file to manipulate | ||
| 88 | # in the form of the variable CHEF_SERVICES_FILE_NAME. This variable | ||
| 89 | # is then accessed in the callback function in the recipe file as | ||
| 90 | # ${CHEF_SERVICES_FILE_NAME} | ||
| 91 | # | ||
| 92 | inherit hosts openstackchef_inc | ||
| 93 | |||
| 94 | #Call this function after the do_install function have executed in | ||
| 95 | #recipes inheriting this class, this ensures that we get configuration | ||
| 96 | #files that have been moved to the images directory | ||
| 97 | addtask deploychef_install before do_package after do_install | ||
| 98 | python do_deploychef_install() { | ||
| 99 | if deploychef_not_rootfs_class(d) and \ | ||
| 100 | deploychef_openstackchef_enabled(d): | ||
| 101 | #copy configuration files from packages inheriting class | ||
| 102 | template_files_tuple = deploychef_copy_conf_files(d) | ||
| 103 | #convert configuration files into templates for chefsolo | ||
| 104 | deploychef_make_templates( d, template_files_tuple) | ||
| 105 | #Generate a list of startup/shutdown services | ||
| 106 | deploychef_make_startup_shutdown_list(d) | ||
| 107 | } | ||
| 108 | |||
| 109 | #Use of ROOTFS_POSTPROCESS_COMMAND enables us to hook into the post | ||
| 110 | #rootfs creation process and influence the work of openstack_configure_hosts. | ||
| 111 | #However, to ensure that our function deploychef_rootfs_postprocess_commands | ||
| 112 | #is called after openstack_configure_hosts and not before it, | ||
| 113 | #we add it in front of our callback function here. | ||
| 114 | ROOTFS_POSTPROCESS_COMMAND += "openstack_configure_hosts ; deploychef_rootfs_postprocess_commands ; " | ||
| 115 | |||
diff --git a/meta-openstack/classes/openstackchef_inc.bbclass b/meta-openstack/classes/openstackchef_inc.bbclass deleted file mode 100644 index 91adb41..0000000 --- a/meta-openstack/classes/openstackchef_inc.bbclass +++ /dev/null | |||
| @@ -1,831 +0,0 @@ | |||
| 1 | # openstackchef_inc.bbclass | ||
| 2 | # Copyright (c) 2014 Wind River Systems, Inc. | ||
| 3 | # | ||
| 4 | # Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 5 | # of this software and associated documentation files (the "Software"), to | ||
| 6 | # deal | ||
| 7 | # in the Software without restriction, including without limitation the rights | ||
| 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | # copies of the Software, and to permit persons to whom the Software is | ||
| 10 | # furnished to do so, subject to the following conditions: | ||
| 11 | # | ||
| 12 | # The above copyright notice and this permission notice shall be included in | ||
| 13 | # all copies or substantial portions of the Software. | ||
| 14 | # | ||
| 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONE INFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| 20 | # FROM, | ||
| 21 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| 22 | # THE SOFTWARE. | ||
| 23 | # | ||
| 24 | # | ||
| 25 | #This class is a helper class for openstackchef.bbclass and should not be be | ||
| 26 | #inherited on it's own. It implements the functionalities used in | ||
| 27 | #openstackchef.bbclass | ||
| 28 | CHEFPN = "openstackchef" | ||
| 29 | #This variable is here to support legacy use of recipes that inherit this | ||
| 30 | #class. By default these recipes will be built without openstackchef support. | ||
| 31 | #Set this variable to 'yes' in your local.conf or similar to enable | ||
| 32 | #support for OPENSTACKCHEF. | ||
| 33 | OPENSTACKCHEF_ENABLED ?='' | ||
| 34 | #This variable is defined in most of the openstack services, however, | ||
| 35 | #it defaults to bare package name for packages that do not define it. | ||
| 36 | SRCNAME ?= "${BPN}" | ||
| 37 | #This is the base directory of where deploychef's templates files | ||
| 38 | #reside in the classes that inherit it. | ||
| 39 | CHEF_TEMPLATE_BASE="${D}${sysconfdir}/${CHEFPN}" | ||
| 40 | CHEF_PACKAGE_BASE="${WORKDIR}/package${sysconfdir}/${CHEFPN}" | ||
| 41 | CHEF_IMAGE_BASE="${D}${sysconfdir}" | ||
| 42 | CHEF_ROOTFS_BASE="${sysconfdir}/${CHEFPN}" | ||
| 43 | #These are the prefixs and suffixs to create chefsolo-like placeholders | ||
| 44 | ERB_PREFIX = "<%=node[:" | ||
| 45 | ERB_SUFFIX = "]%>" | ||
| 46 | #These prefix and suffix are used to create our default values | ||
| 47 | ERB_DEFAULT_PREFIX="default[" | ||
| 48 | ERB_DEFAULT_SUFFIX="]" | ||
| 49 | #Chefsolo template file extension | ||
| 50 | TEMPLATE_EXTENSION='.erb' | ||
| 51 | #Build deploychef package since this class has run-time and buil-time dependency | ||
| 52 | #on it | ||
| 53 | DEPENDS_${PN} += "${@bb.utils.contains('DISTRO_FEATURES', 'chef', 'deploychef', '', d)}" | ||
| 54 | RDEPENDS_${PN} += "${@bb.utils.contains('DISTRO_FEATURES', 'chef', 'deploychef', '', d)}" | ||
| 55 | CHEF_VERSION = '1' | ||
| 56 | #For classes that define a special substitution function, this variable is | ||
| 57 | #set by this class and specifies the file named passed back to these function | ||
| 58 | #for any special substitution. | ||
| 59 | CHEF_SERVICES_FILE_NAME ?='' | ||
| 60 | |||
| 61 | #These are hard coded in the recipes files where they are used. | ||
| 62 | ADMIN_TENANT_NAME ?= 'admin' | ||
| 63 | DEMO_USER ?= 'demo' | ||
| 64 | #This is dafault value used by update-rc.d script at runtime when | ||
| 65 | #build-time update-rd.d class specifies INITSCRIPT_PARAMS as 'defaults' | ||
| 66 | CHEF_INITSCRIPT_PARAMS='defaults 20 10' | ||
| 67 | |||
| 68 | def deploychef_services_default_sub_dict(d): | ||
| 69 | """Provides our placeholder/value substitution dictionary for global use | ||
| 70 | |||
| 71 | This function returns as dictionary containing the default substitution pattern | ||
| 72 | as follows: | ||
| 73 | :<key>: Name of placeholder variable | ||
| 74 | :<value>: A tuple consisting of the place holder variable followed | ||
| 75 | by its default value | ||
| 76 | """ | ||
| 77 | sub_dict={} | ||
| 78 | #neutron | ||
| 79 | sub_dict['SERVICE_TENANT_NAME'] = ('%SERVICE_TENANT_NAME%' , | ||
| 80 | '${SERVICE_TENANT_NAME}') | ||
| 81 | sub_dict['SERVICE_PASSWORD'] = ('%SERVICE_PASSWORD%' , '${SERVICE_PASSWORD}') | ||
| 82 | |||
| 83 | sub_dict['DB_USER'] = ('%DB_USER%', '${DB_USER}') | ||
| 84 | sub_dict['DB_PASSWORD'] = ('%DB_PASSWORD%' , '${DB_PASSWORD}') | ||
| 85 | sub_dict['CONTROLLER_IP'] = ('%CONTROLLER_IP%', '${CONTROLLER_IP}') | ||
| 86 | sub_dict['CONTROLLER_HOST'] = ('%CONTROLLER_HOST%', '${CONTROLLER_HOST}') | ||
| 87 | #nova | ||
| 88 | sub_dict['COMPUTE_IP'] = ('%COMPUTE_IP%', '${COMPUTE_IP}') | ||
| 89 | sub_dict['COMPUTE_HOST'] = ('%COMPUTE_HOST%', '${COMPUTE_HOST}') | ||
| 90 | sub_dict['LIBVIRT_IMAGES_TYPE'] = ('%LIBVIRT_IMAGES_TYPE%' , '${LIBVIRT_IMAGES_TYPE}') | ||
| 91 | sub_dict['OS_PASSWORD'] = ('%OS_PASSWORD%' , '${ADMIN_PASSWORD}') | ||
| 92 | sub_dict['SERVICE_TOKEN'] = ('%SERVICE_TOKEN%' , '${SERVICE_TOKEN}') | ||
| 93 | #swfit | ||
| 94 | sub_dict['ADMIN_TENANT_NAME'] = ('%ADMIN_TENANT_NAME%' , '${ADMIN_TENANT_NAME}') | ||
| 95 | sub_dict['ADMIN_USER'] = ('%ADMIN_USER%' , '${ADMIN_TENANT_NAME}') | ||
| 96 | sub_dict['ADMIN_PASSWORD'] = ('%ADMIN_PASSWORD%' , '${ADMIN_PASSWORD}') | ||
| 97 | sub_dict['DEMO_USER'] = ('%DEMO_USER%' , '${DEMO_USER}') | ||
| 98 | sub_dict['DEMO_PASSWORD'] = ('%DEMO_PASSWORD%' , '${ADMIN_PASSWORD}') | ||
| 99 | #ceilometer | ||
| 100 | sub_dict['CEILOMETER_SECRET'] = ('%CEILOMETER_SECRET%' , '${CEILOMETER_SECRET}') | ||
| 101 | |||
| 102 | #keystone | ||
| 103 | sub_dict['TOKEN_FORMAT'] = ('%TOKEN_FORMAT%' , '${TOKEN_FORMAT}') | ||
| 104 | sub_dict['METADATA_SHARED_SECRET'] = ('%METADATA_SHARED_SECRET%' , '${METADATA_SHARED_SECRET}') | ||
| 105 | #cinder | ||
| 106 | sub_dict['CINDER_BACKUP_BACKEND_DRIVER'] = ('%CINDER_BACKUP_BACKEND_DRIVER%' , '${CINDER_BACKUP_BACKEND_DRIVER}') | ||
| 107 | #cloud-init | ||
| 108 | sub_dict['MANAGE_HOSTS'] = ('%MANAGE_HOSTS%' , '${MANAGE_HOSTS}') | ||
| 109 | sub_dict['HOSTNAME'] = ('%HOSTNAME%' , '${MY_HOST}') | ||
| 110 | #postgresql | ||
| 111 | sub_dict['DB_DATADIR'] = ('%DB_DATADIR%' , '${DB_DATADIR}') | ||
| 112 | #glance | ||
| 113 | sub_dict['GLANCE_DEFAULT_STORE'] = ('%GLANCE_DEFAULT_STORE%' , '${GLANCE_DEFAULT_STORE}') | ||
| 114 | |||
| 115 | #barbican | ||
| 116 | sub_dict['BARBICAN_MAX_PACKET_SIZE'] = ('%BARBICAN_MAX_PACKET_SIZE%' , '${BARBICAN_MAX_PACKET_SIZE}') | ||
| 117 | #ceph | ||
| 118 | sub_dict['PUBLIC_IP'] = ('%PUBLIC_IP%' , '${CONTROLLER_IP}') | ||
| 119 | sub_dict['PRIVATE_IP'] = ('%PRIVATE_IP%' , '${MY_IP}') | ||
| 120 | sub_dict['PUBLIC_DOMAIN'] = ('%PUBLIC_DOMAIN%' , '${PUBLIC_DOMAIN}') | ||
| 121 | sub_dict['HOST_NAME'] = ('%HOST_NAME%' , '${MY_HOST}') | ||
| 122 | sub_dict['CEPH_BACKING_FILE_SIZE'] = ('%CEPH_BACKING_FILE_SIZE%' , '${CEPH_BACKING_FILE_SIZE}') | ||
| 123 | |||
| 124 | #Most of the services have SERVICE_USER define but the values are different | ||
| 125 | service_user = d.getVar('SRCNAME', True) | ||
| 126 | if service_user: | ||
| 127 | service_user = service_user.upper() + '_SERVICE_USER' | ||
| 128 | sub_dict[service_user] = ('%SERVICE_USER%' , '${SRCNAME}') | ||
| 129 | return sub_dict | ||
| 130 | |||
| 131 | #This variable is the default sets of substitutions common to most of the | ||
| 132 | #services in an openstack installation. It means this package is not completely | ||
| 133 | #agnostic but at the same time it gives us the added advantage of not repeating | ||
| 134 | #ourselves in the recipe/class files that inherits this class. | ||
| 135 | CHEF_SERVICES_DEFAULT_CONF_SUBS := "${@deploychef_services_default_sub_dict(d)}" | ||
| 136 | |||
| 137 | |||
| 138 | def deploychef_not_rootfs_class(d): | ||
| 139 | """Filter out rootfs related classes | ||
| 140 | |||
| 141 | This function is used to help us selectively executes the creation of template | ||
| 142 | files and daemon start/stop list. It allows us to executes certain functions | ||
| 143 | when the recipe inheriting this class is related to rootfs creation. | ||
| 144 | """ | ||
| 145 | pkg = d.getVar('PN', True) or d.getVar('BPN', True) | ||
| 146 | #Skip test if recipe/class calling this class is related to rootfs image | ||
| 147 | #creation. | ||
| 148 | if 'image-' in pkg: | ||
| 149 | return False | ||
| 150 | else: | ||
| 151 | return True | ||
| 152 | |||
| 153 | def deploychef_openstackchef_enabled(d): | ||
| 154 | """Find out if openstackchef class usage is enabled | ||
| 155 | |||
| 156 | The variable OPENSTACKCHEF_ENABLED is use to support legacy functionality | ||
| 157 | by recipes inheriting this class. Assinging it an empty string disables | ||
| 158 | the functionality of this class for that recipe file. | ||
| 159 | This function helps us detect when this variable is set to an empty string. | ||
| 160 | """ | ||
| 161 | chef = d.getVar('OPENSTACKCHEF_ENABLED', True) | ||
| 162 | #Skip test if recipe/class calling this class is related to rootfs image | ||
| 163 | #creation. | ||
| 164 | if chef != '' : | ||
| 165 | return True | ||
| 166 | else: | ||
| 167 | return False | ||
| 168 | |||
| 169 | def deploychef_make_startup_shutdown_list(d): | ||
| 170 | """Create list of services to start/stop and save them to file | ||
| 171 | |||
| 172 | This function uses the update-rc.d environment variables defined | ||
| 173 | in the recipes/classes inheriting this class to create the | ||
| 174 | startup and shutdown services list as defined in the file. | ||
| 175 | This is important because, when we are replacing the configuration | ||
| 176 | files for the services, the services needs to be shutdown and | ||
| 177 | restarted after their configuration files are edited. | ||
| 178 | Therefore, the following variables must be defined by classes inheriting | ||
| 179 | this class. | ||
| 180 | |||
| 181 | INITSCRIPT_PACKAGES: A list of init scripts | ||
| 182 | INITSCRIPT_PARAMS_x: The default start/stop priority for the above scripts | ||
| 183 | """ | ||
| 184 | |||
| 185 | import os | ||
| 186 | if d.getVar('INITSCRIPT_PACKAGES') or d.getVar('INITSCRIPT_NAME'): | ||
| 187 | #script_list = d.getVar('INITSCRIPT_PACKAGES', 1) | ||
| 188 | script_list = d.getVar('INITSCRIPT_PACKAGES', True) or \ | ||
| 189 | d.getVar('INITSCRIPT_NAME', True) #Some package do not define INITSCRIPT_PACKAGES | ||
| 190 | msg="list of start/stop services: %s" % str(script_list) | ||
| 191 | bb.debug(2, msg) | ||
| 192 | base_dir = d.getVar('CHEF_TEMPLATE_BASE', 1 ) | ||
| 193 | if not os.path.exists(base_dir): | ||
| 194 | os.mkdir(base_dir) | ||
| 195 | startup_file = os.path.join(base_dir, d.getVar('SRCNAME', True) +'-startup-list') | ||
| 196 | shutdown_file = os.path.join(base_dir, d.getVar('SRCNAME', True) +'-shutdown-list') | ||
| 197 | msg ="Startup and shutdown files %s %s saved to %s" % \ | ||
| 198 | ( startup_file, shutdown_file, base_dir) | ||
| 199 | bb.note(msg) | ||
| 200 | try: | ||
| 201 | hStartup = open(startup_file, 'w') | ||
| 202 | hShutdown = open(shutdown_file, 'w') | ||
| 203 | for script_name in script_list.split(): | ||
| 204 | #Retrieve the default params for update-rc.d for this script | ||
| 205 | #INITSCRIPT_PARAMS_nova-api="defaults 30 10" | ||
| 206 | init_script_name ="INITSCRIPT_NAME_%s" % script_name | ||
| 207 | init_script_name = d.getVar(init_script_name, True) or \ | ||
| 208 | d.getVar('INITSCRIPT_NAME', True) | ||
| 209 | |||
| 210 | script_params ="INITSCRIPT_PARAMS_%s" % script_name | ||
| 211 | script_params = d.getVar(script_params, True) or \ | ||
| 212 | d.getVar('INITSCRIPT_PARAMS', True) | ||
| 213 | #If only defaults is provided as parameter, then use our default priority | ||
| 214 | if not script_params or len(script_params.split()) < 3: | ||
| 215 | script_params = d.getVar('CHEF_INITSCRIPT_PARAMS', True) | ||
| 216 | if init_script_name: | ||
| 217 | #eg. start 20 5 3 2 . stop 80 0 1 6 . | ||
| 218 | startup_priority = shutdown_priority = '' | ||
| 219 | if script_params.find('stop') > 0: | ||
| 220 | start, stop = script_params.split('stop') | ||
| 221 | start = start.split() | ||
| 222 | stop = stop.split() | ||
| 223 | startup_priority = start[1] | ||
| 224 | shutdown_priority = stop[0] | ||
| 225 | elif script_params.find('stop') == 0: | ||
| 226 | start, stop = script_params.split('start') | ||
| 227 | start = start.split() | ||
| 228 | stop = stop.split() | ||
| 229 | startup_priority = start[0] | ||
| 230 | shutdown_priority = stop[1] | ||
| 231 | else: | ||
| 232 | #"defaults 20 10" | ||
| 233 | defaults = script_params.split() | ||
| 234 | startup_priority = defaults[1] | ||
| 235 | shutdown_priority = defaults[2] | ||
| 236 | #Arrange the script's startup/shutdown format as in rc.x | ||
| 237 | startup_string = "%s%s%s%s" % ('S', startup_priority, init_script_name, os.linesep) | ||
| 238 | shutdown_string = "%s%s%s%s" % ('K', shutdown_priority, init_script_name, os.linesep) | ||
| 239 | hStartup.write(startup_string) | ||
| 240 | hShutdown.write(shutdown_string) | ||
| 241 | msg = "%s %s registered for startup and shutdown in" % \ | ||
| 242 | (startup_string, shutdown_string) | ||
| 243 | bb.debug(2 , msg) | ||
| 244 | else: | ||
| 245 | msg = "The variables INITSCRIPT_PARAMS_%s or INITSCRIPT_PARAMS \ | ||
| 246 | are not set in %s, startup/shutdown list not created for %s: %s" \ | ||
| 247 | % (script_name, d.getVar('FILE', True), d.getVar('SRCNAME', True), script_params) | ||
| 248 | raise bb.build.FuncFailed(msg) | ||
| 249 | hStartup.close() | ||
| 250 | hShutdown.close() | ||
| 251 | except IOError as e: | ||
| 252 | bb.error("Error opening startup/shutdown files %s %s, %s %s" % \ | ||
| 253 | (startup_file, shutdown_file, d.getVar('FILE'), e)) | ||
| 254 | else: | ||
| 255 | msg = "The variable INITSCRIPT_PACKAGES is not set in %s, \ | ||
| 256 | startup/shutdown script will not be made for %s package" % \ | ||
| 257 | (d.getVar('FILE', True), d.getVar('SRCNAME', True)) | ||
| 258 | bb.build.FuncFailed(msg) | ||
| 259 | |||
| 260 | def deploychef_make_substitutions(d, sub_dict, attr_filename, sed_filename): | ||
| 261 | """Make placeholder/value substitution in a file | ||
| 262 | |||
| 263 | This function makes placeholder substitution into the file named | ||
| 264 | sed_filename and appends the default value for those substitution into | ||
| 265 | the file named attr_filename. | ||
| 266 | The substitution is based on sets of placeholder/value pair in the | ||
| 267 | dictionary called sub_dict. | ||
| 268 | :sub_dict: name, placeholder and value dictionary | ||
| 269 | :attr_filename: chef-solo attributes file name | ||
| 270 | :sed_filename: configuration or template file | ||
| 271 | """ | ||
| 272 | if attr_filename and sed_filename: | ||
| 273 | if type(sub_dict) is dict: | ||
| 274 | import os | ||
| 275 | import re | ||
| 276 | sHandle = open(sed_filename, 'r+') | ||
| 277 | lines_in_conf_file = sHandle.read() | ||
| 278 | #We only want to append to the list of defines needed by this class | ||
| 279 | hFile= open(attr_filename,'a+') | ||
| 280 | lines_in_file= hFile.read() | ||
| 281 | for key in sub_dict.keys(): | ||
| 282 | placeholder , replacement = sub_dict[key] | ||
| 283 | #Filter by placeholder so that our attribute file only include | ||
| 284 | #defines for class being built | ||
| 285 | if re.search(placeholder,lines_in_conf_file): | ||
| 286 | #Make the substitution to create a template file out of | ||
| 287 | #the configuration file or just replace placeholder in | ||
| 288 | #configuration file | ||
| 289 | if d.getVar('TEMPLATE_EXTENSION', True) in sed_filename: | ||
| 290 | #Format the default attributes as expected by chefsolo | ||
| 291 | #for template file. | ||
| 292 | attr_string = d.getVar('ERB_DEFAULT_PREFIX', True) | ||
| 293 | attr_string += r'"' + key | ||
| 294 | attr_string += r'"' + d.getVar('ERB_DEFAULT_SUFFIX', True) | ||
| 295 | attr_string +=' = ' + r'"' + replacement + r'"' | ||
| 296 | #Only write default values that do not yet exist in file | ||
| 297 | #if key not in lines_in_file: | ||
| 298 | if not re.search(key,lines_in_file): | ||
| 299 | hFile.write("%s%s" % (attr_string, os.linesep)) | ||
| 300 | #Replace the placeholders in the current file, with | ||
| 301 | #new_replacement | ||
| 302 | new_replacement = d.getVar('ERB_PREFIX') + key | ||
| 303 | new_replacement += d.getVar('ERB_SUFFIX') | ||
| 304 | lines_in_conf_file = re.sub(placeholder, new_replacement, lines_in_conf_file) | ||
| 305 | #Write template file to disk | ||
| 306 | sHandle.seek(0) | ||
| 307 | sHandle.truncate() | ||
| 308 | sHandle.write(lines_in_conf_file) | ||
| 309 | sHandle.close() | ||
| 310 | |||
| 311 | hFile.close() | ||
| 312 | if False: | ||
| 313 | msg = "Cannot read/write to attributes file %s as expected:%s"\ | ||
| 314 | % (attr_filename, d.getVar('FILE')) | ||
| 315 | bb.build.FuncFailed(msg) | ||
| 316 | else: | ||
| 317 | msg = "The substitution dictionary variable sub_dict is not set %s as expected "\ | ||
| 318 | % d.getVar('FILE') | ||
| 319 | bb.error(msg) | ||
| 320 | else: | ||
| 321 | msg = "Null file names passsed to function %s %s "\ | ||
| 322 | % (d.getVar('FUNC'), d.getVar('FILE')) | ||
| 323 | bb.error(msg) | ||
| 324 | |||
| 325 | |||
| 326 | |||
| 327 | def deploychef_make_templates( d, conf_tuple=tuple()): | ||
| 328 | """Create a template file out of a configuration file | ||
| 329 | |||
| 330 | Using substitution placeholders and values in the substitution | ||
| 331 | dictionary declared as CHEF_SERVICES_DEFAULT_CONF_SUBS, this function | ||
| 332 | makes the substitution for all placeholders. If the file is a ruby template file, | ||
| 333 | it replaces the placeholders with a chefsolo expression; | ||
| 334 | thereby creating a chefsolo template file. | ||
| 335 | |||
| 336 | :conf_tuple: List of configuration files | ||
| 337 | """ | ||
| 338 | |||
| 339 | if len(conf_tuple): | ||
| 340 | import os, ast | ||
| 341 | base_dir = d.getVar('CHEF_TEMPLATE_BASE', 1 ) | ||
| 342 | attr_file = os.path.join(base_dir, d.getVar('SRCNAME', True) + '-attributes.rb') | ||
| 343 | msg ="Default attributes saved to %s" % attr_file | ||
| 344 | if os.path.exists(attr_file): | ||
| 345 | os.remove(attr_file) | ||
| 346 | bb.note(msg) | ||
| 347 | try: | ||
| 348 | for file_name in conf_tuple: | ||
| 349 | #If a special substitution function is defined for class | ||
| 350 | #inheriting this class, set the file name expected by special | ||
| 351 | #function before calling the function | ||
| 352 | special_func_name = d.getVar('CHEF_SERVICES_SPECIAL_FUNC') | ||
| 353 | if special_func_name: | ||
| 354 | bb.data.setVar('CHEF_SERVICES_FILE_NAME', file_name,\ | ||
| 355 | d) | ||
| 356 | bb.build.exec_func(special_func_name, d) | ||
| 357 | |||
| 358 | #Make the necessary susbstitutions using the default | ||
| 359 | #substitutiin dictionary | ||
| 360 | sub_dict = d.getVar('CHEF_SERVICES_DEFAULT_CONF_SUBS', 1) | ||
| 361 | msg = "The variable %s is not set in %s as a dictionary as expected "\ | ||
| 362 | % ('CHEF_SERVICES_DEFAULT_CONF_SUBS', d.getVar('FILE')) | ||
| 363 | if sub_dict: | ||
| 364 | #Safely retrieve our python data structure | ||
| 365 | sub_dict = ast.literal_eval(sub_dict) | ||
| 366 | if type(sub_dict) is dict: | ||
| 367 | deploychef_make_substitutions(d, sub_dict, attr_file, file_name) | ||
| 368 | else: | ||
| 369 | raise bb.build.FuncFailed(msg) | ||
| 370 | else: | ||
| 371 | raise bb.build.FuncFailed(msg) | ||
| 372 | #Make the necessary susbstitutions using auxilliary dictionary | ||
| 373 | #if provided by inheriting class | ||
| 374 | sub_dict = d.getVar('CHEF_SERVICES_CONF_SUBS', 1) | ||
| 375 | if sub_dict: | ||
| 376 | sub_dict = ast.literal_eval(sub_dict) | ||
| 377 | msg = "The variable %s is not set in %s as a dictionary as expected "\ | ||
| 378 | % ('CHEF_SERVICES_CONF_SUB', d.getVar('FILE')) | ||
| 379 | if type(sub_dict) is dict: | ||
| 380 | pass | ||
| 381 | deploychef_make_substitutions(d, sub_dict, attr_file, file_name) | ||
| 382 | else: | ||
| 383 | bb.build.FuncFailed(msg) | ||
| 384 | except IOError as e: | ||
| 385 | bb.error("Could not write to attribute file %s: in %s, %s" % \ | ||
| 386 | (attr_file, d.getVar('FILE'), e)) | ||
| 387 | |||
| 388 | def deploychef_copy_single_conf_file(d, dst_base, conf_file): | ||
| 389 | """Create a chef-solo template from an openstack configuration file | ||
| 390 | |||
| 391 | This function copies a single configuration file (conf_file) | ||
| 392 | to destination directory (dst_dir) and return a tuple that contains | ||
| 393 | both the absolute path of the conf_file and the template files it was | ||
| 394 | copied as. | ||
| 395 | """ | ||
| 396 | if conf_file: | ||
| 397 | import shutil | ||
| 398 | import os | ||
| 399 | #Create the absolute path to configuration file since it's with relative | ||
| 400 | #to image directory | ||
| 401 | image_base = d.getVar('D', True) | ||
| 402 | if conf_file.startswith(os.sep): | ||
| 403 | conf_file=conf_file[1:] | ||
| 404 | abs_conf_path = os.path.join(image_base, conf_file) | ||
| 405 | |||
| 406 | if os.path.exists(abs_conf_path): | ||
| 407 | dst_base = os.path.join(dst_base, os.path.dirname(conf_file)) | ||
| 408 | #make room for the template file about to be created | ||
| 409 | if not os.path.exists(dst_base): | ||
| 410 | os.makedirs(dst_base) | ||
| 411 | |||
| 412 | abs_template_file = os.path.basename(conf_file) + \ | ||
| 413 | d.getVar('TEMPLATE_EXTENSION', True) + '.' + d.getVar('SRCNAME', True) | ||
| 414 | abs_template_file = os.path.join(dst_base, abs_template_file) | ||
| 415 | #Copy conf file as template file | ||
| 416 | shutil.copy(abs_conf_path, abs_template_file) | ||
| 417 | msg = "\nConf file: %s\n Copied to: %s \n"\ | ||
| 418 | % (abs_conf_path, abs_template_file) | ||
| 419 | bb.debug(2, msg) | ||
| 420 | return (abs_conf_path, abs_template_file) | ||
| 421 | else: | ||
| 422 | msg = "Configuration file: %s in %s does not \ | ||
| 423 | exist" % (abs_conf_path, d.getVar('FILE')) | ||
| 424 | raise bb.build.FuncFailed(msg) | ||
| 425 | else: | ||
| 426 | msg = "The specified configuration file destined for %s in %s is an empty string\n" \ | ||
| 427 | % (dst_base, d.getVar('FILE')) | ||
| 428 | raise bb.build.FuncFailed(msg) | ||
| 429 | |||
| 430 | |||
| 431 | |||
| 432 | def deploychef_copy_conf_files(d): | ||
| 433 | """Copy openstack services' configuration files to be used as chef-solo templates | ||
| 434 | |||
| 435 | Copy the configuration file(s) for the services under | ||
| 436 | ${D}${sysconfdir}/${CHEFPN}/<conf_file>. | ||
| 437 | The file(s) is/are assumed to be located in the images directory; ${D}<conf_file> | ||
| 438 | And evaluate all necessary substitution in the configuration file. | ||
| 439 | """ | ||
| 440 | abs_template_list = list() | ||
| 441 | abs_conf_list = list() | ||
| 442 | |||
| 443 | #Retrieve our string of configuration files | ||
| 444 | conf_files = d.getVar('CHEF_SERVICES_CONF_FILES', True ) | ||
| 445 | #The template files that will be made from the configuration files will be | ||
| 446 | #copied with reference to this base directory. | ||
| 447 | dst_base = d.getVar('CHEF_TEMPLATE_BASE', True ) | ||
| 448 | if conf_files and len(conf_files.strip()): | ||
| 449 | conf_files = conf_files.split() | ||
| 450 | if len(conf_files) != 1: | ||
| 451 | for conf_file in conf_files: | ||
| 452 | abs_conf_path, abs_template_path = deploychef_copy_single_conf_file(d, \ | ||
| 453 | dst_base, conf_file) | ||
| 454 | if abs_template_path: | ||
| 455 | #Save the absolute path to the template file | ||
| 456 | abs_template_list.append(abs_template_path) | ||
| 457 | if abs_conf_path: | ||
| 458 | #Save the absolute path to the configuration file | ||
| 459 | abs_conf_list.append(abs_conf_path) | ||
| 460 | else: | ||
| 461 | abs_conf_path, abs_template_path = deploychef_copy_single_conf_file(d,\ | ||
| 462 | dst_base, conf_files[0]) | ||
| 463 | if abs_template_path: | ||
| 464 | #Save the absolute path to the template file | ||
| 465 | abs_template_list.append(abs_template_path) | ||
| 466 | if abs_conf_path: | ||
| 467 | #Save the absolute path to the template file | ||
| 468 | abs_conf_list.append(abs_conf_path) | ||
| 469 | #Since the recipes no longer do the substitution in the | ||
| 470 | #configuration files, let us do it for the configuration files | ||
| 471 | deploychef_make_templates(d, tuple(abs_conf_list)) | ||
| 472 | else: | ||
| 473 | msg = "The variable CHEF_SERVICES_CONF_FILES is not set" | ||
| 474 | msg += " in %s as a list of files as expected" % d.getVar('FILE', True) | ||
| 475 | #raise bb.build.FuncFailed(msg) | ||
| 476 | #No longer a requirement that all recipes inheriting this | ||
| 477 | #class must have a set of configuration files. | ||
| 478 | bb.debug(2,msg) | ||
| 479 | return tuple(abs_template_list) | ||
| 480 | |||
| 481 | def deploychef_postinst_substitutions(d, sub_dict, postinst): | ||
| 482 | """Make value substitution in openstack services' postinstall scripts | ||
| 483 | |||
| 484 | This function makes all necessary substitution in the 'setup' related postinsts | ||
| 485 | functions pgk_postinst_${PN}-setup. The substitution is base on entries in a | ||
| 486 | dictionary sub_dict. In addition it also updates the list of defined constansts | ||
| 487 | based on the values specified in dictionary or as specified by the recipe's | ||
| 488 | callback function. | ||
| 489 | |||
| 490 | :sub_dict: name, placeholder and value substitution dictionary | ||
| 491 | :postinst: content of an openstack service's postinstall script | ||
| 492 | |||
| 493 | """ | ||
| 494 | if postinst: | ||
| 495 | if type(sub_dict) is dict: | ||
| 496 | import re | ||
| 497 | base_dir = d.getVar('CHEF_PACKAGE_BASE', True) | ||
| 498 | attr_filename = os.path.join(base_dir, d.getVar('SRCNAME', True) + '-attributes.rb') | ||
| 499 | if os.path.exists(attr_filename): | ||
| 500 | hFile= open(attr_filename,'a+') | ||
| 501 | lines_in_file= hFile.read() | ||
| 502 | for key in sub_dict.keys(): | ||
| 503 | placeholder , replacement = sub_dict[key] | ||
| 504 | if replacement and ( re.search(placeholder, postinst) or \ | ||
| 505 | re.search(replacement, postinst)): | ||
| 506 | #If there is any remaining placeholder in the current string | ||
| 507 | #replace it. | ||
| 508 | new_replacement = d.getVar('ERB_PREFIX') + key | ||
| 509 | new_replacement += d.getVar('ERB_SUFFIX') | ||
| 510 | |||
| 511 | updated_postinst = re.sub(placeholder, new_replacement, postinst) | ||
| 512 | #If the placeholder has been substituted, look for the | ||
| 513 | #substitution and replace it with our template value | ||
| 514 | updated_postinst = re.sub(replacement, new_replacement, updated_postinst) | ||
| 515 | #Update our attributes file with the updated replacement | ||
| 516 | #string | ||
| 517 | attr_string = d.getVar('ERB_DEFAULT_PREFIX', True) | ||
| 518 | attr_string += r'"' + key | ||
| 519 | attr_string += r'"' + d.getVar('ERB_DEFAULT_SUFFIX', True) | ||
| 520 | attr_string +=' = ' + r'"' + replacement + r'"' | ||
| 521 | #Only write default values that do not yet exist in file | ||
| 522 | #if key not in lines_in_file: | ||
| 523 | if not re.search(key,lines_in_file): | ||
| 524 | hFile.write("%s%s" % (attr_string, os.linesep)) | ||
| 525 | |||
| 526 | postinst_msg= "placeholder %s \n replacement %s \n updated_postinst :\n %s \n" % \ | ||
| 527 | (placeholder, replacement, updated_postinst) | ||
| 528 | bb.debug(2, postinst_msg) | ||
| 529 | postinst = updated_postinst | ||
| 530 | hFile.close() | ||
| 531 | else: | ||
| 532 | msg = "The substitution dictionary variable sub_dict is not set %s as expected "\ | ||
| 533 | % d.getVar('FILE') | ||
| 534 | bb.build.FuncFailed(msg) | ||
| 535 | else: | ||
| 536 | msg = "Null string passsed to function %s %s "\ | ||
| 537 | % (d.getVar('FUNC'), d.getVar('FILE')) | ||
| 538 | bb.build.FuncFailed(msg) | ||
| 539 | return postinst | ||
| 540 | |||
| 541 | def deploychef_update_package_postinsts(d): | ||
| 542 | """Make placeholder/value substitution in openstack postinstall scripts | ||
| 543 | |||
| 544 | This function searches all the 'setup' related post-install scripts for | ||
| 545 | references to placeholders of interest; such as %CONTROLLER_IP%. | ||
| 546 | It replaces any such reference when it does find one with a placeholder | ||
| 547 | (<%=node[:CONTROLLER_IP]%>); that essentially converts the post-install | ||
| 548 | script to a chefsolo template. | ||
| 549 | """ | ||
| 550 | def update_postinst_package(pkg): | ||
| 551 | bb.debug(1, 'Updating placeholders in postinst for pkg_postinst_%s scripts' % pkg) | ||
| 552 | |||
| 553 | ldata = bb.data.createCopy(d) | ||
| 554 | overrides = ldata.getVar("OVERRIDES", True) | ||
| 555 | |||
| 556 | msg = "%s The override variable is %s" % (pkg, overrides) | ||
| 557 | bb.note(msg) | ||
| 558 | ldata.setVar("OVERRIDES", "%s:%s" % (pkg, overrides)) | ||
| 559 | |||
| 560 | bb.data.update_data(ldata) | ||
| 561 | postinst = ldata.getVar('pkg_postinst', True) | ||
| 562 | if postinst: | ||
| 563 | #Make the necessary substitutions using the default | ||
| 564 | #substitution dictionary | ||
| 565 | overrides = d.getVar("OVERRIDES", True) | ||
| 566 | msg = "%s The override variable is %s :\n %s " % (pkg, overrides, postinst) | ||
| 567 | bb.note(msg) | ||
| 568 | sub_dict = d.getVar('CHEF_SERVICES_DEFAULT_CONF_SUBS', 1) | ||
| 569 | msg = "The variable %s is not set in %s as a dictionary as expected "\ | ||
| 570 | % ('CHEF_SERVICES_DEFAULT_CONF_SUBS', d.getVar('FILE')) | ||
| 571 | if sub_dict: | ||
| 572 | import ast | ||
| 573 | #Safely retrieve our python data structure | ||
| 574 | sub_dict = ast.literal_eval(sub_dict) | ||
| 575 | if type(sub_dict) is dict: | ||
| 576 | import re | ||
| 577 | updated_postinst = deploychef_postinst_substitutions(d, sub_dict, postinst) | ||
| 578 | #Replace the placeholders in postinst script if any | ||
| 579 | d.setVar('pkg_postinst_%s' % pkg, updated_postinst) | ||
| 580 | else: | ||
| 581 | raise bb.build.FuncFailed(msg) | ||
| 582 | else: | ||
| 583 | raise bb.build.FuncFailed(msg) | ||
| 584 | else: | ||
| 585 | msg= "pkg_postinst_%s does not exist for %s\n" % (pkg, str(ldata)) | ||
| 586 | bb.note(msg) | ||
| 587 | bb.build.FuncFailed(msg) | ||
| 588 | |||
| 589 | packages = (d.getVar('PACKAGES', True) or "").split() | ||
| 590 | if packages != []: | ||
| 591 | for pkg in packages: | ||
| 592 | if pkg.endswith('setup'): | ||
| 593 | update_postinst_package(pkg) | ||
| 594 | |||
| 595 | python populate_packages_append() { | ||
| 596 | |||
| 597 | deploychef_update_package_postinsts(d) | ||
| 598 | } | ||
| 599 | |||
| 600 | def deploychef_add_file_to_FILES_PN(d, conf_file=None): | ||
| 601 | """Add all directories under a file name to FILES_${PN} variable | ||
| 602 | |||
| 603 | This function appends the name of the template file to the FILES_${PN}/${BPN} | ||
| 604 | bitbake variable to avoid QA warning about files built but not | ||
| 605 | added to rootfs. $CHEF_TEMPLATE_BASE/conf_file. Note that conf_file | ||
| 606 | is relative to the root filesystem as in /etc/neutron/neutron.conf | ||
| 607 | The template file will be located in /etc/${CHEFPN}/etc/neutron/neutron.conf.rb | ||
| 608 | Thefore, we need to make sure that all directories above the | ||
| 609 | template file are added to FILES_${PN} variable. | ||
| 610 | |||
| 611 | :conf_file: a chef-solo template file | ||
| 612 | """ | ||
| 613 | import re | ||
| 614 | import os | ||
| 615 | #Perform an override so that we can update FILES_${PN} variables | ||
| 616 | ldata = bb.data.createCopy(d) | ||
| 617 | overrides = ldata.getVar("OVERRIDES", True) | ||
| 618 | pkg = d.getVar('PN', True) or d.getVar('BPN', True) | ||
| 619 | files = d.getVar('FILES_%s' % pkg, True) | ||
| 620 | pkg_files = "FILES_%s" % pkg | ||
| 621 | ldata.setVar("OVERRIDES", "%s:%s" % (pkg_files, overrides)) | ||
| 622 | bb.data.update_data(ldata) | ||
| 623 | |||
| 624 | dest_base = d.getVar('CHEF_TEMPLATE_BASE', True) | ||
| 625 | pkg_imagedir = d.getVar('CHEF_ROOTFS_BASE', True) | ||
| 626 | #Add the packages image base directory if it does not already exist | ||
| 627 | if re.search(pkg_imagedir, files) == None: | ||
| 628 | #All the directory and all files in it | ||
| 629 | files = "%s %s" % ( files, pkg_imagedir) | ||
| 630 | files = "%s %s%s*" % ( files, pkg_imagedir, os.sep ) | ||
| 631 | d.setVar('FILES_%s' % pkg, files) | ||
| 632 | msg= "Updated FILES_%s: %s for base images dir" % (pkg, d.getVar('FILES_%s' % pkg, files)) | ||
| 633 | bb.debug(2,msg) | ||
| 634 | #All the files and all sub directory leading up to the package image base directory | ||
| 635 | if conf_file: | ||
| 636 | rel_basedir = os.path.dirname(conf_file) | ||
| 637 | if rel_basedir.startswith(os.sep): | ||
| 638 | rel_basedir = rel_basedir[1:] | ||
| 639 | rel_basedir = os.path.join(pkg_imagedir, rel_basedir) | ||
| 640 | if re.search(rel_basedir, files) == None: | ||
| 641 | files = "%s %s" % ( files, rel_basedir) | ||
| 642 | files = "%s %s%s*" % ( files, rel_basedir, os.sep ) | ||
| 643 | while rel_basedir.count(os.sep) > 4: | ||
| 644 | #Must be above /etc/chef/etc/ | ||
| 645 | rel_basedir_list = rel_basedir.split(os.sep) | ||
| 646 | rel_basedir = os.sep.join(rel_basedir_list[:-1]) | ||
| 647 | if re.search(rel_basedir, files) == None: | ||
| 648 | #All the directory and files in it | ||
| 649 | files = "%s %s" % ( files, rel_basedir) | ||
| 650 | files = "%s %s%s*" % ( files, rel_basedir, os.sep ) | ||
| 651 | bb.note(files) | ||
| 652 | bb.debug(2, files) | ||
| 653 | d.setVar('FILES_%s' % pkg, files) | ||
| 654 | msg= "Updated FILES_%s: %s " % (pkg, d.getVar('FILES_%s' % pkg, files)) | ||
| 655 | bb.debug(2,msg) | ||
| 656 | |||
| 657 | def deploychef_update_FILES_PN_variable(d): | ||
| 658 | """Indicate that the created chef-solo templates should be packaged | ||
| 659 | |||
| 660 | This function ensures that all the templates files which are based off | ||
| 661 | of configuration files exposed to this class are packaged up when they | ||
| 662 | are copied from the images directory to the various packages folders | ||
| 663 | This avoids the QA warning such as: | ||
| 664 | WARNING: For recipe python-neutron, the following files/directories were installed | ||
| 665 | but not shipped in any package: | ||
| 666 | """ | ||
| 667 | conf_files = d.getVar('CHEF_SERVICES_CONF_FILES', True ) | ||
| 668 | if conf_files and len(conf_files.strip()): | ||
| 669 | import shutil | ||
| 670 | import os | ||
| 671 | for conf_file in conf_files.split(): | ||
| 672 | deploychef_add_file_to_FILES_PN(d, conf_file) | ||
| 673 | else: | ||
| 674 | #Add the directory containing the start/stop scripts | ||
| 675 | deploychef_add_file_to_FILES_PN(d) | ||
| 676 | |||
| 677 | |||
| 678 | python populate_packages_prepend() { | ||
| 679 | |||
| 680 | deploychef_update_FILES_PN_variable(d) | ||
| 681 | } | ||
| 682 | |||
| 683 | #The sets of functions below are for post rootfs processing. Preparing files | ||
| 684 | #for chefsolo is a two stage process. First we must create the required files | ||
| 685 | #in the package's image directory; and this is mostly done by the functions | ||
| 686 | #above. | ||
| 687 | #And then we aggregate the files from their respective package directories | ||
| 688 | #and put them together for the deploychef package in the expected | ||
| 689 | #location. | ||
| 690 | CHEF_ROOT_DIR="${IMAGE_ROOTFS}/${sysconfdir}/${CHEFPN}" | ||
| 691 | CHEF_CONF_DIR="${CHEF_ROOT_DIR}/${sysconfdir}" | ||
| 692 | INITD_DIR="${IMAGE_ROOTFS}/${sysconfdir}/init.d" | ||
| 693 | POSTINSTS_DIR="${IMAGE_ROOTFS}/${sysconfdir}/rpm-postinsts" | ||
| 694 | DEPLOYCHEF_DIR="${IMAGE_ROOTFS}/opt/deploychef" | ||
| 695 | DEPLOYCHEF_TEMPLATES_DIR="${DEPLOYCHEF_DIR}/cookbooks/openstack/templates/default" | ||
| 696 | ATTRIBUTES_DIR="${DEPLOYCHEF_DIR}/cookbooks/openstack/attributes" | ||
| 697 | ATTRIBUTES_FILE="${ATTRIBUTES_DIR}/default.rb" | ||
| 698 | |||
| 699 | deploychef_copy_host_files() { | ||
| 700 | #The /etc/hosts & /etc/hostname files are written during the rootfs | ||
| 701 | #post process, therefore the only way of making templates out of them | ||
| 702 | #is to hook into the rootfs post process command. | ||
| 703 | if [ -f "${IMAGE_ROOTFS}/${sysconfdir}/hosts" ]; then | ||
| 704 | #Convert etc/hosts to chefsolo template | ||
| 705 | cp ${IMAGE_ROOTFS}/${sysconfdir}/hosts ${IMAGE_ROOTFS}/${sysconfdir}/${CHEFPN}/${sysconfdir}/hosts.erb | ||
| 706 | sed -e "s,${CONTROLLER_IP},${ERB_PREFIX}CONTROLLER_IP${ERB_SUFFIX},g" -i \ | ||
| 707 | ${IMAGE_ROOTFS}/${sysconfdir}/${CHEFPN}/${sysconfdir}/hosts.erb | ||
| 708 | sed -e "s,${CONTROLLER_HOST},${ERB_PREFIX}CONTROLLER_HOST${ERB_SUFFIX},g" -i \ | ||
| 709 | ${IMAGE_ROOTFS}/${sysconfdir}/${CHEFPN}/${sysconfdir}/hosts.erb | ||
| 710 | |||
| 711 | sed -e "s,${COMPUTE_IP},${ERB_PREFIX}COMPUTE_IP${ERB_SUFFIX},g" -i \ | ||
| 712 | ${IMAGE_ROOTFS}/${sysconfdir}/${CHEFPN}/${sysconfdir}/hosts.erb | ||
| 713 | sed -e "s,${COMPUTE_HOST},${ERB_PREFIX}COMPUTE_HOST${ERB_SUFFIX},g" -i \ | ||
| 714 | ${IMAGE_ROOTFS}/${sysconfdir}/${CHEFPN}/${sysconfdir}/hosts.erb | ||
| 715 | #Create an attribute file for /etc/hosts | ||
| 716 | attr_string="${ERB_DEFAULT_PREFIX}\"COMPUTE_IP\"${ERB_DEFAULT_SUFFIX} = \"${COMPUTE_IP}\"" | ||
| 717 | echo "$attr_string" > ${IMAGE_ROOTFS}/${sysconfdir}/${CHEFPN}/hosts-attributes.rb | ||
| 718 | attr_string="${ERB_DEFAULT_PREFIX}\"COMPUTE_HOST\"${ERB_DEFAULT_SUFFIX} = \"${COMPUTE_HOST}\"" | ||
| 719 | echo "$attr_string" >> ${IMAGE_ROOTFS}/${sysconfdir}/${CHEFPN}/hosts-attributes.rb | ||
| 720 | attr_string="${ERB_DEFAULT_PREFIX}\"CONTROLLER_IP\"${ERB_DEFAULT_SUFFIX} = \"${CONTROLLER_IP}\"" | ||
| 721 | echo "$attr_string" >> ${IMAGE_ROOTFS}/${sysconfdir}/${CHEFPN}/hosts-attributes.rb | ||
| 722 | attr_string="${ERB_DEFAULT_PREFIX}\"CONTROLLER_HOST\"${ERB_DEFAULT_SUFFIX} = \"${CONTROLLER_HOST}\"" | ||
| 723 | echo "$attr_string" >> ${IMAGE_ROOTFS}/${sysconfdir}/${CHEFPN}/hosts-attributes.rb | ||
| 724 | fi | ||
| 725 | |||
| 726 | if [ -f "${IMAGE_ROOTFS}/${sysconfdir}/hostname" ]; then | ||
| 727 | #Convert etc/hostname to chefsolo template | ||
| 728 | cp ${IMAGE_ROOTFS}/${sysconfdir}/hostname ${IMAGE_ROOTFS}/${sysconfdir}/${CHEFPN}/${sysconfdir}/hostname.erb | ||
| 729 | sed -e "s,${MY_HOST},${ERB_PREFIX}HOSTNAME${ERB_SUFFIX},g" -i \ | ||
| 730 | ${IMAGE_ROOTFS}/${sysconfdir}/${CHEFPN}/${sysconfdir}/hostname.erb | ||
| 731 | #Create an attribute file for /etc/hostname | ||
| 732 | attr_string="${ERB_DEFAULT_PREFIX}\"HOSTNAME\"${ERB_DEFAULT_SUFFIX} = \"${MY_HOST}\"" | ||
| 733 | echo "$attr_string" > ${IMAGE_ROOTFS}/${sysconfdir}/${CHEFPN}/hostname-attributes.rb | ||
| 734 | fi | ||
| 735 | } | ||
| 736 | |||
| 737 | |||
| 738 | combine_services_daemons(){ | ||
| 739 | if [ -n $1 ]; then | ||
| 740 | file_suffix=$1 | ||
| 741 | rm -f ${DEPLOYCHEF_DIR}/$file_suffix | ||
| 742 | #combine the list of shutdown/startup scripts | ||
| 743 | find "${CHEF_ROOT_DIR}/" -name "*$file_suffix" 2> /dev/null | while read fname; do | ||
| 744 | service_cont=$(cat $fname) | ||
| 745 | for line in $service_cont; do | ||
| 746 | service=$(echo $line | awk -F"[SK][0-9]+" '{print $2}') | ||
| 747 | if [ -e ${INITD_DIR}/$service ]; then | ||
| 748 | echo $line >> ${DEPLOYCHEF_DIR}/$file_suffix | ||
| 749 | fi | ||
| 750 | done | ||
| 751 | done | ||
| 752 | fi | ||
| 753 | } | ||
| 754 | |||
| 755 | #This function combines the attributes of all the sevices into | ||
| 756 | #a default.rb attributes file. | ||
| 757 | combine_services_attributes(){ | ||
| 758 | file_suffix='attributes.rb' | ||
| 759 | mkdir -p ${ATTRIBUTES_DIR}; rm -f ${ATTRIBUTES_FILE} 2>/dev/null | ||
| 760 | #combine the list of shutdown/starup scripts | ||
| 761 | find "${CHEF_ROOT_DIR}/" -name "*$file_suffix" 2> /dev/null | \ | ||
| 762 | while read fname; do | ||
| 763 | cat $fname | while read line_in_file; do | ||
| 764 | index=$(echo $line_in_file | awk -F'"' '{print $2}') | ||
| 765 | #Only append attributes that are not in the default.rb attributes file | ||
| 766 | if [ ! `grep -l $index ${ATTRIBUTES_FILE}` ]; then | ||
| 767 | echo $line_in_file >> ${ATTRIBUTES_FILE} | ||
| 768 | fi | ||
| 769 | done | ||
| 770 | done | ||
| 771 | } | ||
| 772 | |||
| 773 | #This function copies the templates to deploychef directory from | ||
| 774 | #within the packages directories | ||
| 775 | copy_templates_in_place(){ | ||
| 776 | #copy rpm-postinsts and config templates into templates directory | ||
| 777 | mkdir -p ${DEPLOYCHEF_TEMPLATES_DIR} | ||
| 778 | #First copy all our configuration template files | ||
| 779 | if [ -d ${CHEF_CONF_DIR} ]; then | ||
| 780 | cp -rf ${CHEF_CONF_DIR} ${DEPLOYCHEF_TEMPLATES_DIR} | ||
| 781 | fi | ||
| 782 | #Now copy the rpm-postinsts files into cookbooks/templates/default/etc/ | ||
| 783 | if [ -d ${POSTINSTS_DIR} ]; then | ||
| 784 | cp -rf ${POSTINSTS_DIR} ${DEPLOYCHEF_TEMPLATES_DIR}/${sysconfdir} | ||
| 785 | #Move the files to base of the templates directory, where chef-solo | ||
| 786 | #expects them | ||
| 787 | cp -f ${POSTINSTS_DIR}/* ${DEPLOYCHEF_TEMPLATES_DIR}/. | ||
| 788 | fi | ||
| 789 | |||
| 790 | } | ||
| 791 | |||
| 792 | filter_node_dependent_templates(){ | ||
| 793 | if [ -d ${DEPLOYCHEF_TEMPLATES_DIR} ]; then | ||
| 794 | find "${DEPLOYCHEF_TEMPLATES_DIR}/" -name "*.erb*" 2> /dev/null | \ | ||
| 795 | while read fname; do | ||
| 796 | config_file=$(echo $fname | awk -F'/default' '{print $2}' | awk \ | ||
| 797 | -F'.erb' '{print $1}') | ||
| 798 | #If the base configuration file does not exist on this node | ||
| 799 | #remove it. | ||
| 800 | if [ ! -f ${IMAGE_ROOTFS}$config_file ]; then | ||
| 801 | rm -f "$fname" | ||
| 802 | else | ||
| 803 | #Move the file to the default template directory where | ||
| 804 | #chefsolo expect them | ||
| 805 | cp "$fname" "${DEPLOYCHEF_TEMPLATES_DIR}" | ||
| 806 | fi | ||
| 807 | done | ||
| 808 | fi | ||
| 809 | } | ||
| 810 | |||
| 811 | #This function is our post rootfs hook, it enables | ||
| 812 | #us to do what we wish to do during rootfs creation process. | ||
| 813 | deploychef_rootfs_postprocess_commands() { | ||
| 814 | |||
| 815 | if [ -n "${OPENSTACKCHEF_ENABLED}" ]; then | ||
| 816 | deploychef_copy_host_files | ||
| 817 | combine_services_daemons 'shutdown-list' | ||
| 818 | combine_services_daemons 'startup-list' | ||
| 819 | combine_services_attributes | ||
| 820 | copy_templates_in_place | ||
| 821 | filter_node_dependent_templates | ||
| 822 | else | ||
| 823 | #Let us delete the deploychef init script that runs | ||
| 824 | #chef-solo at boot-up from rootfs | ||
| 825 | rm -f ${INITD_DIR}/deploychef 2> /dev/null | ||
| 826 | fi | ||
| 827 | #We nolonger have need for /etc/${CHEFPN} directory on rootfs | ||
| 828 | #Not even at run-time | ||
| 829 | rm -rf "${CHEF_ROOT_DIR}" | ||
| 830 | } | ||
| 831 | |||
