def _configure_db_confs(self): dbtype = self.cfg.get("db", "type") #TODO: maybe this should be a subclass that handles these differences if self.distro == settings.RHEL6 and dbtype == MYSQL: LOG.info("Fixing up %s mysql configs." % (settings.RHEL6)) fc = sh.load_file('/etc/my.cnf') lines = fc.splitlines() new_lines = list() for line in lines: if line.startswith('skip-grant-tables'): line = '#' + line new_lines.append(line) fc = utils.joinlinesep(*new_lines) with sh.Rooted(True): sh.write_file('/etc/my.cnf', fc) elif self.distro == settings.UBUNTU11 and dbtype == MYSQL: LOG.info("Fixing up %s mysql configs." % (settings.UBUNTU11)) fc = sh.load_file('/etc/mysql/my.cnf') lines = fc.splitlines() new_lines = list() for line in lines: if line.startswith('bind-address'): line = 'bind-address = %s' % ('0.0.0.0') new_lines.append(line) fc = utils.joinlinesep(*new_lines) with sh.Rooted(True): sh.write_file('/etc/mysql/my.cnf', fc)
def _format_stderr_out(self, stderr, stdout): if stdout is None: stdout = '' if stderr is None: stderr = '' combined = ["===STDOUT===", str(stdout), "===STDERR===", str(stderr)] return utils.joinlinesep(*combined)
def update(self, fn): current_vars = RcReader().extract(fn) possible_vars = dict() possible_vars.update(self._get_general_envs()) possible_vars.update(self._get_ec2_envs()) possible_vars.update(self._get_password_envs()) possible_vars.update(self._get_os_envs()) possible_vars.update(self._get_euca_envs()) possible_vars.update(self._get_nova_envs()) new_vars = dict() updated_vars = dict() for (key, value) in possible_vars.items(): if value is not None: if key in current_vars and (current_vars.get(key) != value): updated_vars[key] = value elif key not in current_vars: new_vars[key] = value if new_vars or updated_vars: lines = list() lines.append("") lines.append('# Updated on %s' % (date.rcf8222date())) lines.append("") if new_vars: lines.append('# New stuff') lines.extend(self._make_dict_export(new_vars)) lines.append("") if updated_vars: lines.append('# Updated stuff') lines.extend(self._make_dict_export(updated_vars)) lines.append("") append_contents = utils.joinlinesep(*lines) sh.append_file(fn, append_contents) return len(new_vars) + len(updated_vars) else: return 0
def _config_fixups(self): #currently just handling rhel fixups #TODO: maybe this should be a subclass that handles these differences if not (self.distro in APACHE_FIXUPS_DISTROS): return #it seems like to get this to work #we need to do some conf.d/conf work which sort of sucks (user, group) = self._get_apache_user_group() socket_fn = APACHE_FIXUPS.get("SOCKET_CONF") self.tracewriter.file_touched(socket_fn) #not recorded since we aren't really creating this httpd_fn = APACHE_FIXUPS.get("HTTPD_CONF") with sh.Rooted(True): #fix the socket prefix to someplace we can use fc = "WSGISocketPrefix %s" % (sh.joinpths(self.log_dir, "wsgi-socket")) sh.write_file(socket_fn, fc) #now adjust the run user and group (of httpd.conf) new_lines = list() for line in sh.load_file(httpd_fn).splitlines(): if line.startswith("User "): line = "User %s" % (user) if line.startswith("Group "): line = "Group %s" % (group) new_lines.append(line) sh.write_file(httpd_fn, utils.joinlinesep(*new_lines))
def add_header(fn, contents): lines = list() lines.append('# Adjusted source file %s' % (fn.strip())) lines.append("# On %s" % (date.rcf8222date())) lines.append("# By user %s, group %s" % (sh.getuser(), sh.getgroupname())) lines.append("# Comments may have been removed (TODO: darn python config writer)") lines.append("") if contents: lines.append(contents) return utils.joinlinesep(*lines)
def _get_source_config(self, config_fn): if config_fn == API_CONF: (fn, top) = utils.load_template(self.component_name, API_CONF) (_, bottom) = self._get_source_config(API_PASTE_CONF) combined = [top, "### Joined here on %s with file %s" % (date.rcf8222date(), API_PASTE_CONF), bottom] return (fn, utils.joinlinesep(*combined)) elif config_fn == REG_CONF: (fn, top) = utils.load_template(self.component_name, REG_CONF) (_, bottom) = self._get_source_config(REG_PASTE_CONF) combined = [top, "### Joined here on %s with file %s" % (date.rcf8222date(), REG_PASTE_CONF), bottom] return (fn, utils.joinlinesep(*combined)) elif config_fn == POLICY_JSON: fn = sh.joinpths(self.cfgdir, POLICY_JSON) contents = sh.load_file(fn) return (fn, contents) elif config_fn == LOGGING_CONF: fn = sh.joinpths(self.cfgdir, LOGGING_SOURCE_FN) contents = sh.load_file(fn) return (fn, contents) return comp.PythonInstallComponent._get_source_config(self, config_fn)
def add_header(fn, contents): lines = list() lines.append('# Adjusted source file %s' % (fn.strip())) lines.append("# On %s" % (date.rcf8222date())) lines.append("# By user %s, group %s" % (sh.getuser(), sh.getgroupname())) lines.append("# Comments may have been removed (TODO: darn python config writer)") # TODO Maybe use https://code.google.com/p/iniparse/ which seems to preserve comments! lines.append("") if contents: lines.append(contents) return utils.joinlinesep(*lines)
def add_header(fn, contents): lines = list() if not fn: fn = "???" lines.append("# Adjusted source file %s" % (fn.strip())) lines.append("# On %s" % (date.rcf8222date())) lines.append("# By user %s, group %s" % (sh.getuser(), sh.getgroupname())) lines.append("") if contents: lines.append(contents) return utils.joinlinesep(*lines)
def add_header(fn, contents): lines = list() if not fn: fn = "???" lines.append('# Adjusted source file %s' % (fn.strip())) lines.append("# On %s" % (date.rcf8222date())) lines.append("# By user %s, group %s" % (sh.getuser(), sh.getgroupname())) lines.append("") if contents: lines.append(contents) return utils.joinlinesep(*lines)
def _configure_db_confs(self): LOG.info("Fixing up %r mysql configs.", self.distro.name) fc = sh.load_file('/etc/my.cnf') lines = fc.splitlines() new_lines = list() for line in lines: if line.startswith('skip-grant-tables'): line = '#' + line new_lines.append(line) fc = utils.joinlinesep(*new_lines) with sh.Rooted(True): sh.write_file('/etc/my.cnf', fc)
def _configure_db_confs(self): LOG.info("Fixing up %s mysql configs.", self.distro.name) fc = sh.load_file('/etc/mysql/my.cnf') lines = fc.splitlines() new_lines = list() for line in lines: if line.startswith('bind-address'): line = 'bind-address = %s' % ('0.0.0.0') new_lines.append(line) fc = utils.joinlinesep(*new_lines) with sh.Rooted(True): sh.write_file('/etc/mysql/my.cnf', fc)
def _configure_db_confs(self): LOG.info("Fixing up %r mysql configs.", self.distro.name) fc = sh.load_file('/etc/mysql/my.cnf') lines = fc.splitlines() new_lines = list() for line in lines: if line.startswith('bind-address'): line = 'bind-address = %s' % ('0.0.0.0') new_lines.append(line) fc = utils.joinlinesep(*new_lines) with sh.Rooted(True): sh.write_file('/etc/mysql/my.cnf', fc)
def _configure_db_confs(self): LOG.info("Fixing up %s mysql configs.", self.distro.name) fc = sh.load_file('/etc/my.cnf') lines = fc.splitlines() new_lines = list() for line in lines: if line.startswith('skip-grant-tables'): line = '#' + line new_lines.append(line) fc = utils.joinlinesep(*new_lines) with sh.Rooted(True): sh.write_file('/etc/my.cnf', fc)
def _config_fixups(self): (user, group) = self._get_apache_user_group() # This is recorded so it gets cleaned up during uninstall self.tracewriter.file_touched(SOCKET_CONF) LOG.info("Fixing up %r and %r files" % (SOCKET_CONF, HTTPD_CONF)) with sh.Rooted(True): # Fix the socket prefix to someplace we can use fc = "WSGISocketPrefix %s" % (sh.joinpths(self.log_dir, "wsgi-socket")) sh.write_file(SOCKET_CONF, fc) # Now adjust the run user and group (of httpd.conf) new_lines = list() for line in sh.load_file(HTTPD_CONF).splitlines(): if line.startswith("User "): line = "User %s" % (user) if line.startswith("Group "): line = "Group %s" % (group) new_lines.append(line) sh.write_file(HTTPD_CONF, utils.joinlinesep(*new_lines))
def _config_adjust_catalog(self, contents, fn): nlines = list() if 'swift' in self.options: mp = dict() mp['SERVICE_HOST'] = self.cfg.get('host', 'ip') nlines.append("# Swift additions") nlines.extend(utils.param_replace_list(SWIFT_TEMPL_ADDS, mp)) nlines.append("") if 'quantum' in self.options: mp = dict() mp['SERVICE_HOST'] = self.cfg.get('host', 'ip') nlines.append("# Quantum additions") nlines.extend(utils.param_replace_list(QUANTUM_TEMPL_ADDS, mp)) nlines.append("") if nlines: nlines.insert(0, contents) contents = cfg.add_header(fn, utils.joinlinesep(*nlines)) return contents
def _get_session(self): sessions = self._active_sessions() LOG.debug("Found sessions [%s]" % ", ".join(sessions)) if not sessions: return None if len(sessions) > 1: msg = [ "You are running multiple screen sessions [%s], please reduce the set to zero or one." % (", ".join(sessions)), ] for s in sorted(sessions): mp = {'SCREEN_ID': s} cmd_msg = self._gen_cmd(SCREEN_KILLER, mp) env = self._get_env() for (k, v) in env.items(): cmd_msg.insert(0, "%s=%s" % (k, v)) msg.append("Try running '%s' to quit that session." % (" ".join(cmd_msg))) raise excp.StartException(utils.joinlinesep(msg)) return sessions[0]
def _config_fixups(self): (user, group) = self._get_apache_user_group() # This is recorded so it gets cleaned up during uninstall self.tracewriter.file_touched(SOCKET_CONF) LOG.info("Fixing up %s and %s files" % (SOCKET_CONF, HTTPD_CONF)) with sh.Rooted(True): # Fix the socket prefix to someplace we can use fc = "WSGISocketPrefix %s" % (sh.joinpths(self.log_dir, "wsgi-socket")) sh.write_file(SOCKET_CONF, fc) # Now adjust the run user and group (of httpd.conf) new_lines = list() for line in sh.load_file(HTTPD_CONF).splitlines(): if line.startswith("User "): line = "User %s" % (user) if line.startswith("Group "): line = "Group %s" % (group) new_lines.append(line) sh.write_file(HTTPD_CONF, utils.joinlinesep(*new_lines))
def _get_content(self, nova_conf): generated_content = nova_conf.generate() extra_flags = self._get_extra('extra_flags') if extra_flags: LOG.warning("EXTRA_FLAGS is defined and may need to be converted to EXTRA_OPTS!") extra_flags = self._convert_extra_flags(extra_flags) extra_opts = self._get_extra('extra_opts') if extra_flags or extra_opts: new_contents = list() new_contents.append(generated_content) new_contents.append("") new_contents.append("# Extra flags") new_contents.append("") new_contents.extend(extra_flags) new_contents.append("") new_contents.append("# Extra options") new_contents.append("") new_contents.extend(extra_opts) new_contents.append("") generated_content = utils.joinlinesep(*new_contents) return generated_content
def _get_content(self, nova_conf): generated_content = nova_conf.generate() extra_flags = self._getstr('extra_flags') if extra_flags: new_contents = list() new_contents.append(generated_content) #Lines that start with a # are ignored as comments. #Leading whitespace is also ignored in flagfiles, as are blank lines. new_contents.append("") new_contents.append("# Extra FLAGS") new_contents.append("") cleaned_lines = list() extra_lines = extra_flags.splitlines() for line in extra_lines: cleaned_line = line.strip() if len(cleaned_line): cleaned_lines.append(cleaned_line) #anything actually found? if cleaned_lines: new_contents.extend(cleaned_lines) generated_content = utils.joinlinesep(*new_contents) return generated_content
def _config_adjust(self, contents, name): if name == ROOT_CONF: #use config parser and #then extract known configs that #will need locations/directories/files made (or touched)... with io.BytesIO(contents) as stream: config = cfg.IgnoreMissingConfigParser() config.readfp(stream) log_filename = config.get('default', 'log_file') if log_filename: LOG.info("Ensuring log file %s exists and is empty." % (log_filename)) log_dir = sh.dirname(log_filename) if log_dir: LOG.info("Ensuring log directory %s exists." % (log_dir)) self.tracewriter.make_dir(log_dir) #destroy then recreate it (the log file) sh.unlink(log_filename) sh.touch_file(log_filename) self.tracewriter.file_touched(log_filename) elif name == CATALOG_CONF: nlines = list() if utils.service_enabled(settings.SWIFT, self.instances): mp = dict() mp['SERVICE_HOST'] = self.cfg.get('host', 'ip') nlines.append("# Swift additions") nlines.extend(utils.param_replace_list(SWIFT_TEMPL_ADDS, mp)) nlines.append("") if utils.service_enabled(settings.QUANTUM, self.instances) or \ utils.service_enabled(settings.QUANTUM_CLIENT, self.instances): mp = dict() mp['SERVICE_HOST'] = self.cfg.get('host', 'ip') nlines.append("# Quantum additions") nlines.extend(utils.param_replace_list(QUANTUM_TEMPL_ADDS, mp)) nlines.append("") if nlines: nlines.insert(0, contents) contents = cfg.add_header(name, utils.joinlinesep(*nlines)) return contents
def _config_adjust(self, contents, name): if name == ROOT_CONF: # Use config parser and # then extract known configs that # ill need locations/directories/files made (or touched)... with io.BytesIO(contents) as stream: config = cfg.IgnoreMissingConfigParser() config.readfp(stream) log_filename = config.get('default', 'log_file') if log_filename: LOG.info("Ensuring log file %s exists and is empty." % (log_filename)) log_dir = sh.dirname(log_filename) if log_dir: LOG.info("Ensuring log directory %s exists." % (log_dir)) self.tracewriter.dirs_made(*sh.mkdirslist(log_dir)) # Destroy then recreate it (the log file) sh.unlink(log_filename) self.tracewriter.file_touched(sh.touch_file(log_filename)) elif name == CATALOG_CONF: nlines = list() if 'swift' in self.options: mp = dict() mp['SERVICE_HOST'] = self.cfg.get('host', 'ip') nlines.append("# Swift additions") nlines.extend(utils.param_replace_list(SWIFT_TEMPL_ADDS, mp)) nlines.append("") if 'quantum' in self.options: mp = dict() mp['SERVICE_HOST'] = self.cfg.get('host', 'ip') nlines.append("# Quantum additions") nlines.extend(utils.param_replace_list(QUANTUM_TEMPL_ADDS, mp)) nlines.append("") if nlines: nlines.insert(0, contents) contents = cfg.add_header(name, utils.joinlinesep(*nlines)) return contents
def _get_content(self, nova_conf): generated_content = nova_conf.generate() extra_flags = self._get_extra('extra_flags') if extra_flags: LOG.warning( "EXTRA_FLAGS is defined and may need to be converted to EXTRA_OPTS!" ) extra_flags = self._convert_extra_flags(extra_flags) extra_opts = self._get_extra('extra_opts') if extra_flags or extra_opts: new_contents = list() new_contents.append(generated_content) new_contents.append("") new_contents.append("# Extra flags") new_contents.append("") new_contents.extend(extra_flags) new_contents.append("") new_contents.append("# Extra options") new_contents.append("") new_contents.extend(extra_opts) new_contents.append("") generated_content = utils.joinlinesep(*new_contents) return generated_content
def _config_fixups(self): #currently just handling rhel fixups #TODO: maybe this should be a subclass that handles these differences if self.distro != settings.RHEL6: return #it seems like to get this to work #we need to do some conf.d/conf work which sort of sucks (user, group) = self._get_apache_user_group() with sh.Rooted(True): #fix the socket prefix to someplace we can use fc = "WSGISocketPrefix %s" % (sh.joinpths(self.log_dir, "wsgi-socket")) sh.write_file(RHEL_FIXUPS.get("SOCKET_CONF"), fc) #now adjust the run user and group fc = sh.load_file(RHEL_FIXUPS.get("HTTPD_CONF")) lines = fc.splitlines() new_lines = list() for line in lines: if line.startswith("User "): line = "User %s" % (user) if line.startswith("Group "): line = "Group %s" % (group) new_lines.append(line) fc = utils.joinlinesep(*new_lines) sh.write_file(RHEL_FIXUPS.get("HTTPD_CONF"), fc)
def generate(self, param_dict=None): conf_lines = sorted(self._generate_lines(param_dict)) full_lines = list() full_lines.append("# Generated on %s" % (date.rcf8222date())) full_lines.extend(conf_lines) return utils.joinlinesep(*full_lines)
def write(self, fn): contents = utils.joinlinesep(*self._generate_lines()) sh.write_file(fn, contents)
def generate(self): lines = self._generate_lines() return utils.joinlinesep(*lines)
def generate(self, param_dict=None): lines = list() lines.extend(self._generate_header()) lines.extend(sorted(self._generate_lines(param_dict))) lines.extend(self._generate_footer()) return utils.joinlinesep(*lines)
def create(self, session_name, env_exports): lines = self._generate_lines(session_name, env_exports) contents = utils.joinlinesep(*lines) return contents
def _format_stderr_out(self, stderr, stdout): combined = ["===STDOUT===", str(stdout), "===STDERR===", str(stderr)] return utils.joinlinesep(*combined)
def configure(self, component_dirs): nova_conf = NovaConf() #use more than once hostip = self.cfg.get('host', 'ip') #verbose on? if self._getbool('verbose'): nova_conf.add_simple('verbose') #allow the admin api? if self._getbool('allow_admin_api'): nova_conf.add_simple('allow_admin_api') #which scheduler do u want? scheduler = self._getstr('scheduler') if not scheduler: scheduler = DEF_SCHEDULER nova_conf.add('scheduler_driver', scheduler) #setup network settings self._configure_network_settings(nova_conf, component_dirs) #setup nova volume settings if self.volumes_enabled: self._configure_vols(nova_conf) #where we are running nova_conf.add('my_ip', hostip) #setup your sql connection nova_conf.add('sql_connection', self.cfg.get_dbdsn('nova')) #configure anything libvirt releated? virt_driver = self._getstr('virt_driver') if virt_driver == virsh.VIRT_TYPE: libvirt_type = virsh.default(self._getstr('libvirt_type')) self._configure_libvirt(libvirt_type, nova_conf) #how instances will be presented instance_template = self._getstr('instance_name_prefix') + self._getstr('instance_name_postfix') nova_conf.add('instance_name_template', instance_template) #??? nova_conf.add('osapi_compute_extension', 'nova.api.openstack.compute.contrib.standard_extensions') #vnc settings self._configure_vnc(nova_conf) #where our paste config is nova_conf.add('api_paste_config', self.paste_conf_fn) #what our imaging service will be self._configure_image_service(nova_conf) #ec2 / s3 stuff ec2_dmz_host = self._getstr('ec2_dmz_host') if not ec2_dmz_host: ec2_dmz_host = hostip nova_conf.add('ec2_dmz_host', ec2_dmz_host) nova_conf.add('s3_host', hostip) #how is your rabbit setup? nova_conf.add('rabbit_host', self.cfg.get('default', 'rabbit_host')) nova_conf.add('rabbit_password', self.cfg.get("passwords", "rabbit")) #where instances will be stored instances_path = self._getstr('instances_path') if not instances_path: instances_path = sh.joinpths(self.component_root, 'instances') self._configure_instances_path(instances_path, nova_conf) #is this a multihost setup? self._configure_multihost(nova_conf) #enable syslog?? self._configure_syslog(nova_conf) #handle any virt driver specifics self._configure_virt_driver(nova_conf) #now make it conf_lines = sorted(nova_conf.generate()) complete_file = utils.joinlinesep(*conf_lines) #add any extra flags in? extra_flags = self._getstr('extra_flags') if extra_flags: full_file = [complete_file, extra_flags] complete_file = utils.joinlinesep(*full_file) return complete_file
def configure(self, dirs): #TODO split up into sections?? nova_conf = NovaConf() hostip = self.cfg.get('host', 'ip') #verbose on? if self._getbool('verbose'): nova_conf.add_simple('verbose') #allow the admin api? if self._getbool('allow_admin_api'): nova_conf.add_simple('allow_admin_api') #which scheduler do u want? scheduler = self._getstr('scheduler') if not scheduler: scheduler = DEF_SCHEDULER nova_conf.add('scheduler_driver', scheduler) flag_conf_fn = sh.joinpths(dirs.get('bin'), API_CONF) nova_conf.add('dhcpbridge_flagfile', flag_conf_fn) #whats the network fixed range? nova_conf.add('fixed_range', self._getstr('fixed_range')) if settings.QUANTUM in self.instances: #setup quantum config nova_conf.add('network_manager', QUANTUM_MANAGER) nova_conf.add('quantum_connection_host', self.cfg.get('quantum', 'q_host')) nova_conf.add('quantum_connection_port', self.cfg.get('quantum', 'q_port')) # TODO add q-svc support #if 'q-svc' in self.othercomponents and # self.cfg.get('quantum', 'q_plugin') == 'openvswitch': # self.lines.extend(QUANTUM_OPENSWITCH_OPS) else: nova_conf.add('network_manager', NET_MANAGER_TEMPLATE % (self._getstr('network_manager'))) if self.nvol: nova_conf.add('volume_group', self._getstr('volume_group')) volume_name_template = self._getstr('volume_name_prefix') + self._getstr('volume_name_postfix') nova_conf.add('volume_name_template', volume_name_template) nova_conf.add('iscsi_help', 'tgtadm') nova_conf.add('my_ip', hostip) # The value for vlan_interface may default to the the current value # of public_interface. We'll grab the value and keep it handy. public_interface = self._getstr('public_interface') vlan_interface = self._getstr('vlan_interface') if not vlan_interface: vlan_interface = public_interface nova_conf.add('public_interface', public_interface) nova_conf.add('vlan_interface', vlan_interface) #setup your sql connection and what type of virt u will be doing nova_conf.add('sql_connection', self.cfg.get_dbdsn('nova')) #configure anything libvirt releated? self._configure_libvirt(self._getstr('libvirt_type'), nova_conf) #how instances will be presented instance_template = self._getstr('instance_name_prefix') + self._getstr('instance_name_postfix') nova_conf.add('instance_name_template', instance_template) if settings.OPENSTACK_X in self.instances: nova_conf.add('osapi_compute_extension', 'nova.api.openstack.compute.contrib.standard_extensions') nova_conf.add('osapi_compute_extension', 'extensions.admin.Admin') if settings.NOVNC in self.instances: vncproxy_url = self._getstr('vncproxy_url') if not vncproxy_url: vncproxy_url = 'http://' + hostip + ':6080/vnc_auto.html' nova_conf.add('vncproxy_url', vncproxy_url) nova_conf.add('api_paste_config', self.paste_conf_fn) img_service = self._getstr('img_service') if not img_service: img_service = DEF_IMAGE_SERVICE nova_conf.add('image_service', img_service) ec2_dmz_host = self._getstr('ec2_dmz_host') if not ec2_dmz_host: ec2_dmz_host = hostip nova_conf.add('ec2_dmz_host', ec2_dmz_host) #how is your rabbit setup? nova_conf.add('rabbit_host', self.cfg.get('default', 'rabbit_host')) nova_conf.add('rabbit_password', self.cfg.get("passwords", "rabbit")) #where is glance located? glance_api_server = self._getstr('glance_server') if not glance_api_server: glance_api_server = "%s:%d" % (hostip, DEF_GLANCE_PORT) nova_conf.add('glance_api_servers', glance_api_server) nova_conf.add_simple('force_dhcp_release') #where instances will be stored instances_path = self._getstr('instances_path') if not instances_path: # If there's no instances path, specify a default instances_path = sh.joinpths(self.appdir, '..', 'instances') nova_conf.add('instances_path', instances_path) LOG.debug("Attempting to create instance directory:%s" % (instances_path)) # Create the directory for instances self.tracewriter.make_dir(instances_path) #is this a multihost setup? if self._getbool('multi_host'): nova_conf.add_simple('multi_host') nova_conf.add_simple('send_arp_for_ha') #enable syslog?? if self.cfg.getboolean('default', 'syslog'): nova_conf.add_simple('use_syslog') #handle any virt driver specifics virt_driver = self._getstr('virt_driver') self._configure_virt_driver(virt_driver, nova_conf) #now make it conf_lines = sorted(nova_conf.generate()) complete_file = utils.joinlinesep(*conf_lines) #add any extra flags in? extra_flags = self._getstr('extra_flags') if extra_flags and len(extra_flags): full_file = [complete_file, extra_flags] complete_file = utils.joinlinesep(*full_file) return complete_file