def set_config_section_key(self, section, key, value): """ Sets the value of key for a given logic (section) :param section: logic to set the key for :param key: key for which the value should be set :param value: value to set """ # load /etc/logic.yaml conf_filename = os.path.join(self._get_etc_dir(), 'logic') conf = shyaml.yaml_load_roundtrip(conf_filename) logger.info( "set_config_section_key: section={}, key={}, value={}".format( section, key, str(value))) if value == None: if conf[section].get(key, None) != None: del conf[section][key] else: conf[section][key] = value # save /etc/logic.yaml shyaml.yaml_save_roundtrip(conf_filename, conf, True) # activate visu_acl without reloading the logic if key == 'visu_acl': mylogic = self.return_logic(section) if mylogic is not None: logger.info(" - key={}, value={}".format(key, value)) # if value is None: # value = 'false' mylogic.visu_acl = str(value) return
def read_config_section(self, section): """ Read a section from /etc/logic.yaml This funtion returns the data from one section of the configuration file as a list of configuration entries. A configuration entry is a list with three items: - key configuration key - value configuration value (string or list) - comment comment for the value (string or list) :param section: Name of the logic (section) :type section: str :return: config_list: list of configuration entries. Each entry of this list is a list with three string entries: ['key', 'value', 'comment'] :rtype: list of lists """ if self.return_config_type() != YAML_FILE: logger.error("read_config_section: Editing of configuration only possible with new (yaml) config format") return False # load /etc/logic.yaml conf_filename = os.path.join(self._get_etc_dir(), 'logic') conf = shyaml.yaml_load_roundtrip(conf_filename) config_list = [] if conf is not None: section_dict = conf.get(section, {}) # logger.warning("read_config_section: read_config_section('{}') = {}".format(section, str(section_dict) )) for key in section_dict: if isinstance(section_dict[key], list): value = section_dict[key] comment = [] # 'Comment 6: ' + loaded['a']['c'].ca.items[0][0].value 'Comment 7: ' + loaded['a']['c'].ca.items[1][0].value for i in range(len(value)): if i in section_dict[key].ca.items: try: c = section_dict[key].ca.items[i][0].value except: logger.info("c: {}, Key: {}".format(c, key)) c = '' if len(c) > 0 and c[0] == '#': c = c[1:] else: c = '' comment.append(c.strip()) else: value = section_dict[key] c = '' if key in section_dict.ca.items: try: c = section_dict.ca.items[key][2].value # if not list: loaded['a'].ca.items['b'][2].value except: logger.info("c2: {}, Key: {}".format(c, key)) if len(c) > 0 and c[0] == '#': c = c[1:] comment = c.strip() # logger.warning("-> read_config_section: section_dict['{}'] = {}, comment = '{}'".format(key, str(section_dict[key]), comment )) config_list.append([key, value, comment]) return config_list
def add(self, id=None): self.logger.info("PluginController(): add('{}')".format(id)) params = self.get_body() if params is None: self.logger.warning("PluginController(): add(): section '{}': Bad, add request".format(id)) raise cherrypy.HTTPError(status=411) self.logger.info("PluginController(): add(): section '{}' = {}".format(id, params)) config_filename = self.get_config_filename() if self.test_for_old_config(config_filename): # make it 'readonly', if plugin.conf is used response = {'result': 'error', 'description': 'Updateing .CONF files is not supported'} else: response = {} plugin_conf = shyaml.yaml_load_roundtrip(config_filename) sect = plugin_conf.get(id) if sect is not None: response = {'result': 'error', 'description': "Configuration section '{}' already exists".format(id)} else: plugin_conf[id] = params.get('config', {}) shyaml.yaml_save_roundtrip(config_filename, plugin_conf, False) response = {'result': 'ok'} self.logger.info("PluginController(): add(): response = {}".format(response)) return json.dumps(response)
def read_config_section(self, section): """ Read a section from /etc/logic.yaml This funtion returns the data from one section of the configuration file as a list of configuration entries. A configuration entry is a list with three items: - key configuration key - value configuration value (string or list) - comment comment for the value (string or list) :param section: Name of the logic (section) :type section: str :return: config_list: list of configuration entries. Each entry of this list is a list with three string entries: ['key', 'value', 'comment'] :rtype: list of lists """ if self.return_config_type() != YAML_FILE: logger.error("read_config_section: Editing of configuration only possible with new (yaml) config format") return False # load /etc/logic.yaml conf_filename = os.path.join(self._get_etc_dir(), 'logic') conf = shyaml.yaml_load_roundtrip(conf_filename) config_list = [] if conf is not None: section_dict = conf.get(section, {}) # logger.warning("read_config_section: read_config_section('{}') = {}".format(section, str(section_dict) )) for key in section_dict: if isinstance(section_dict[key], list): value = section_dict[key] comment = [] # 'Comment 6: ' + loaded['a']['c'].ca.items[0][0].value 'Comment 7: ' + loaded['a']['c'].ca.items[1][0].value for i in range(len(value)): if i in section_dict[key].ca.items: try: c = section_dict[key].ca.items[i][0].value except: logger.info("c: {}, Key: {}".format(c, key)) c = '' if len(c) > 0 and c[0] == '#': c = c[1:] else: c = '' comment.append(c.strip()) else: value = section_dict[key] c = '' if key in section_dict.ca.items: try: c = section_dict.ca.items[key][2].value # if not list: loaded['a'].ca.items['b'][2].value except: logger.info("c2: {}, Key: {}".format(c, key)) if len(c) > 0 and c[0] == '#': c = c[1:] comment = c.strip() # logger.warning("-> read_config_section: section_dict['{}'] = {}, comment = '{}'".format(key, str(section_dict[key]), comment )) config_list.append([key, value, comment]) return config_list
def set_config_section_key(self, section, key, value): """ Sets the value of key for a given logic (section) :param section: logic to set the key for :param key: key for which the value should be set :param value: value to set """ # load /etc/logic.yaml conf_filename = os.path.join(self._get_etc_dir(), 'logic') conf = shyaml.yaml_load_roundtrip(conf_filename) logger.info("set_config_section_key: section={}, key={}, value={}".format(section, key, str(value))) if value == None: del conf[section][key] else: conf[section][key] = value # save /etc/logic.yaml shyaml.yaml_save_roundtrip(conf_filename, conf, True) # activate visu_acl without reloading the logic if key == 'visu_acl': mylogic = self.return_logic(section) if mylogic is not None: logger.info(" - key={}, value={}".format(key, value)) # if value is None: # value = 'false' mylogic.visu_acl = str(value) return
def update(self, id=None): """ Handle PUT requests """ self.logger.info("ConfigController() update: config {}".format(id)) if id in ['common', 'http', 'admin', 'mqtt', 'core']: # get http headers cl = cherrypy.request.headers.get('Content-Length', 0) if cl == 0: raise cherrypy.HTTPError(status=411) rawbody = cherrypy.request.body.read(int(cl)) data = json.loads(rawbody.decode('utf-8')) self.logger.info(" - update: data = {}".format(data)) # update holidays and remove keys from self.core_confdata self.update_holidays(data) # update etc/smarthome.yaml with data from admin frontend self.core_confdata = shyaml.yaml_load_roundtrip(os.path.join(self.etc_dir, 'smarthome.yaml')) self.update_configdict(self.core_confdata, data, 'common') shyaml.yaml_save_roundtrip(os.path.join(self.etc_dir, 'smarthome.yaml'), self.core_confdata, create_backup=True) # update etc/module.yaml with data from admin frontend self.module_confdata = shyaml.yaml_load_roundtrip(os.path.join(self.etc_dir, 'module.yaml')) self.update_configdict(self.module_confdata['http'], data, 'http') self.update_configdict(self.module_confdata['admin'], data, 'admin') if self.module_confdata.get('mqtt', None) is None: self.module_confdata['mqtt'] = {} self.module_confdata['mqtt']['module_name'] = 'mqtt' self.update_configdict(self.module_confdata['mqtt'], data, 'mqtt') self.logger.warning("Update: self.mqtt_conf = {}".format(self.mqtt_conf)) if self.module_confdata['mqtt'].get('enabled', None) is None: self.module_confdata['mqtt']['enabled'] = False if self.module_confdata['mqtt']['enabled']: self.module_confdata['mqtt'].pop('enabled', None) self.logger.warning("Update: ['mqtt'] = {}".format(self.module_confdata['mqtt'])) self.logger.warning("Update: enabled = {}".format(self.module_confdata['mqtt'].get('enabled', None))) shyaml.yaml_save_roundtrip(os.path.join(self.etc_dir, 'module.yaml'), self.module_confdata, create_backup=True) result = {"result": "ok"} return json.dumps(result) result = {"result": "error"} return json.dumps(result)
def delete_logic(self, name): """ Deletes a complete logic The python code and the section from the configuration file /etc/logic.yaml are removed. If it is a blockly logic, the blockly code is removed too. If a code file is references by more than the logic that is being deleted, the code file will not be deleted. It will only be deleted when the last logic referencing this code file is being deleted. :param name: name of the logic :type name: str :return: True, if deletion fas successful :rtype: bool """ logger.warning("delete_logic: This routineimplements the deletion of logic '{}' (still in testing)".format(name)) # Logik entladen if self.is_logic_loaded(name): logger.warning("delete_logic: Logic '{}' unloaded".format(name)) self.unload_logic( name) # load /etc/logic.yaml conf_filename = os.path.join(self._get_etc_dir(), 'logic') conf = shyaml.yaml_load_roundtrip(conf_filename) section = conf.get(name, None) if section is None: logger.warning("delete_logic: Section '{}' not found in logic configuration.".format(name)) return False filename = section.get('filename', None) if filename is None: logger.warning("delete_logic: Filename of logic is not defined in section '{}' of logic configuration.".format(name)) else: count = self._count_filename_uses(conf, filename) blocklyname = os.path.join(self.get_logics_dir(), os.path.splitext(os.path.basename(filename))[0]+'.blockly') filename = os.path.join(self._logic_dir, filename) if count < 2: # Deletion of the parts of the logic if os.path.isfile(blocklyname): os.remove(blocklyname) logger.warning("delete_logic: Blockly-Logic file '{}' deleted".format(blocklyname)) if os.path.isfile(filename): os.remove(filename) logger.warning("delete_logic: Logic file '{}' deleted".format(filename)) else: logger.warning("delete_logic: Skipped deletion of logic file '{}' because it is used by {} other logic(s)".format(filename, count-1)) del conf[name] logger.warning("delete_logic: Section '{}' from configuration deleted".format(name)) # save /etc/logic.yaml shyaml.yaml_save_roundtrip(conf_filename, conf, True) return True
def update_holidays(self, data): filename = os.path.join(self.etc_dir, 'holidays.yaml') self.holidays_confdata = shyaml.yaml_load_roundtrip(filename) self.logger.info( "update_holidays: self.holidays_confdata = '{}'".format( self.holidays_confdata)) self.logger.info( "update_holidays: data['common']['data'] = '{}'".format( data['common']['data'])) if self.holidays_confdata.get('location', None) is None: self.holidays_confdata['location'] = {} self.holidays_confdata['location']['country'] = data['common']['data'][ 'holidays_country'] self.holidays_confdata['location']['province'] = data['common'][ 'data']['holidays_province'] self.holidays_confdata['location']['state'] = data['common']['data'][ 'holidays_state'] del data['common']['data']['holidays_country'] del data['common']['data']['holidays_province'] del data['common']['data']['holidays_state'] if self.holidays_confdata.get('custom', None) is None: self.holidays_confdata['custom'] = [] try: if len(self.holidays_confdata['custom']) > 5: for i in range(1, 6): custom = data['common']['data']['holidays_custom' + str(i)] if custom is not None and custom != '': self.holidays_confdata['custom'][i - 1] = custom else: self.holidays_confdata['custom'] = [] for i in range(1, 6): custom = data['common']['data']['holidays_custom' + str(i)] if custom is not None and custom != '': self.holidays_confdata['custom'].append(custom) for i in range(1, 6): del data['common']['data']['holidays_custom' + str(i)] except Exception as e: self.logger.critical("update_holidays: Exception {}".format(e)) if self.holidays_confdata['custom'] == []: #self.holidays_confdata['custom'] = None del self.holidays_confdata['custom'] if self.holidays_confdata['location']['state'] is None: del self.holidays_confdata['location']['state'] self.logger.info( "update_holidays: self.holidays_confdata = '{}'".format( self.holidays_confdata)) shyaml.yaml_save_roundtrip(filename, self.holidays_confdata, create_backup=True) return
def delete_logic(self, name): """ Deletes a complete logic The python code and the section from the configuration file /etc/logic.yaml are removed. If it is a blockly logic, the blockly code is removed too. If a code file is references by more than the logic that is being deleted, the code file will not be deleted. It will only be deleted when the last logic referencing this code file is being deleted. :param name: name of the logic :type name: str :return: True, if deletion fas successful :rtype: bool """ logger.warning("delete_logic: This routineimplements the deletion of logic '{}' (still in testing)".format(name)) # Logik entladen if self.is_logic_loaded(name): logger.warning("delete_logic: Logic '{}' unloaded".format(name)) self.unload_logic( name) # load /etc/logic.yaml conf_filename = os.path.join(self._get_etc_dir(), 'logic') conf = shyaml.yaml_load_roundtrip(conf_filename) section = conf.get(name, None) if section is None: logger.warning("delete_logic: Section '{}' not found in logic configuration.".format(name)) return False filename = section.get('filename', None) if filename is None: logger.warning("delete_logic: Filename of logic is not defined in section '{}' of logic configuration.".format(name)) else: count = self._count_filename_uses(conf, filename) blocklyname = os.path.join(self.get_logics_dir(), os.path.splitext(os.path.basename(filename))[0]+'.blockly') filename = os.path.join(self._logic_dir, filename) if count < 2: # Deletion of the parts of the logic if os.path.isfile(blocklyname): os.remove(blocklyname) logger.warning("delete_logic: Blockly-Logic file '{}' deleted".format(blocklyname)) if os.path.isfile(filename): os.remove(filename) logger.warning("delete_logic: Logic file '{}' deleted".format(filename)) else: logger.warning("delete_logic: Skipped deletion of logic file '{}' because it is used by {} other logic(s)".format(filename, count-1)) del conf[name] logger.warning("delete_logic: Section '{}' from configuration deleted".format(name)) # save /etc/logic.yaml shyaml.yaml_save_roundtrip(conf_filename, conf, True) return True
def update(self, id=None): """ Handle PUT requests """ self.logger.info("ConfigController() update: config {}".format(id)) if id in ['common', 'http', 'admin', 'core']: # get http headers cl = cherrypy.request.headers.get('Content-Length', 0) if cl == 0: raise cherrypy.HTTPError(status=411) rawbody = cherrypy.request.body.read(int(cl)) data = json.loads(rawbody.decode('utf-8')) self.logger.info(" - update: data = {}".format(data)) # update etc/smarthome.yaml with data from admin frontend self.core_confdata = shyaml.yaml_load_roundtrip( os.path.join(self.etc_dir, 'smarthome.yaml')) self.update_configdict(self.core_confdata, data, 'common') shyaml.yaml_save_roundtrip(os.path.join(self.etc_dir, 'smarthome.yaml'), self.core_confdata, create_backup=True) # update etc/module.yaml with data from admin frontend self.module_confdata = shyaml.yaml_load_roundtrip( os.path.join(self.etc_dir, 'module.yaml')) self.update_configdict(self.module_confdata['http'], data, 'http') self.update_configdict(self.module_confdata['admin'], data, 'admin') shyaml.yaml_save_roundtrip(os.path.join(self.etc_dir, 'module.yaml'), self.module_confdata, create_backup=True) result = {"result": "ok"} return json.dumps(result) result = {"result": "error"} return json.dumps(result)
def return_logictype(self, name): """ Returns the type of a specified logic (Python, Blockly, None) :param name: Name of the logic (name of the configuration section) :type name: str :return: Logic type ('Python', 'Blockly' or None) :rtype: str or None """ logic_type = 'None' filename = '' if name in self._userlogics: try: filename = self._userlogics[name].get('filename', '') except: logger.warning( "return_logictype: self._userlogics[name] = '{}'".format( str(self._userlogics[name]))) logger.warning( "return_logictype: self._userlogics = '{}'".format( str(self._userlogics))) elif name in self._systemlogics: filename = self._systemlogics[name].get('filename', '') logic_type = 'Python' else: logger.info("return_logictype: name {} is not loaded".format(name)) # load /etc/logic.yaml if logic is not in the loaded logics conf_filename = os.path.join(self._get_etc_dir(), 'logic') config = shyaml.yaml_load_roundtrip(conf_filename) if config is not None: if name in config: filename = config[name].get('filename', '') if filename != '': blocklyname = os.path.splitext( os.path.basename(filename))[0] + '.blockly' if os.path.isfile(os.path.join(self.get_logics_dir(), filename)): logic_type = 'Python' if os.path.isfile( os.path.join(self.get_logics_dir(), blocklyname)): logic_type = 'Blockly' logger.debug( "return_logictype: name '{}', filename '{}', logic_type '{}'". format(name, filename, logic_type)) return logic_type
def load_logging_config_for_edit(self): """ Load config from logging.yaml to a dict If logging.yaml does not contain a 'shng_version' key, a backup is created """ conf_filename = os.path.join(self.etc_dir, 'logging') self.logging_config = shyaml.yaml_load_roundtrip(conf_filename) self.logger.warning("load_logging_config: shng_version={}".format( self.logging_config.get('shng_version', None))) if self.logging_config.get('shng_version', None) is None: self.create_backupfile(conf_filename) self.logging_config['shng_version'] = 'x' self.save_logging_config() return
def return_defined_logics(self, withtype=False): """ Returns the names of defined logics from file /etc/logic.yaml as a list If ``withtype`` is specified and set to True, the function returns a dict with names and logictypes ('Python', 'Blockly') :param withtype: If specified and set to True, the function will additionally return the logic types :type withtype: bool :return: list of defined logics or dict of defined logics with type :rtype: list or dict """ if withtype: logic_list = {} else: logic_list = [] # load /etc/logic.yaml conf_filename = os.path.join(self._get_etc_dir(), 'logic') config = shyaml.yaml_load_roundtrip(conf_filename) if config is not None: for section in config: logic_dict = {} filename = config[section]['filename'] blocklyname = os.path.splitext( os.path.basename(filename))[0] + '.xml' logic_type = 'None' if os.path.isfile(os.path.join(self.get_logics_dir(), filename)): logic_type = 'Python' if os.path.isfile( os.path.join(self.get_logics_dir(), blocklyname)): logic_type = 'Blockly' logger.debug( "return_defined_logics: section '{}', logic_type '{}'". format(section, logic_type)) if withtype: logic_list[section] = logic_type else: logic_list.append(section) return logic_list
def save_logic_parameters(self, logicname): params = self.get_body() self.logger.info( "LogicsController.save_logic_parameters: logic = {}, params = {}". format(logicname, params)) config_filename = os.path.join(self.etc_dir, 'logic') logic_conf = shyaml.yaml_load_roundtrip(config_filename) sect = logic_conf.get(logicname) if sect is None: response = { 'result': 'error', 'description': "Configuration section '{}' does not exist".format(logicname) } else: self.logger.info( "LogicsController.save_logic_parameters: logic = {}, alte params = {}" .format(logicname, dict(sect))) for param, value in params.items(): if value == None: sect.pop(param, None) else: self.logger.info( "- param = {}, value = {}, type(value) = {}".format( param, value, Utils.get_type(value))) if (Utils.get_type(value) == 'str') and (value == ''): sect.pop(param, None) elif (Utils.get_type(value) == 'list') and (value == []): sect.pop(param, None) elif (Utils.get_type(value) == 'dict') and (value == {}): sect.pop(param, None) else: sect[param] = value self.logger.info( "LogicsController.save_logic_parameters: logic = {}, neue params = {}" .format(logicname, dict(sect))) shyaml.yaml_save_roundtrip(config_filename, logic_conf, False) response = {'result': 'ok'} return json.dumps(response)
def delete(self, id=None): self.logger.info("PluginController(): delete('{}')".format(id)) config_filename = self.get_config_filename() if self.test_for_old_config(config_filename): # make it 'readonly', if plugin.conf is used response = {'result': 'error', 'description': 'Updateing .CONF files is not supported'} else: response = {} plugin_conf = shyaml.yaml_load_roundtrip(config_filename) sect = plugin_conf.pop(id, None) if sect is None: response = {'result': 'error', 'description': "Configuration section '{}' does not exist".format(id)} else: shyaml.yaml_save_roundtrip(config_filename, plugin_conf, False) response = {'result': 'ok'} self.logger.info("PluginController(): delete(): response = {}".format(response)) return json.dumps(response)
def return_defined_logics(self, withtype=False): """ Returns the names of defined logics from file /etc/logic.yaml as a list If ``withtype`` is specified and set to True, the function returns a dict with names and logictypes ('Python', 'Blockly') :param withtype: If specified and set to True, the function will additionally return the logic types :type withtype: bool :return: list of defined logics or dict of defined logics with type :rtype: list or dict """ if withtype: logic_list = {} else: logic_list = [] # load /etc/logic.yaml conf_filename = os.path.join(self._get_etc_dir(), 'logic') config = shyaml.yaml_load_roundtrip(conf_filename) if config is not None: for section in config: logic_dict = {} filename = config[section]['filename'] blocklyname = os.path.splitext(os.path.basename(filename))[0]+'.xml' logic_type = 'None' if os.path.isfile(os.path.join(self.get_logics_dir(), filename)): logic_type = 'Python' if os.path.isfile(os.path.join(self.get_logics_dir(), blocklyname)): logic_type = 'Blockly' logger.debug("return_defined_logics: section '{}', logic_type '{}'".format(section, logic_type)) if withtype: logic_list[section] = logic_type else: logic_list.append(section) return logic_list
def return_logictype(self, name): """ Returns the type of a specified logic (Python, Blockly, None) :param name: Name of the logic (name of the configuration section) :type name: str :return: Logic type ('Python', 'Blockly' or None) :rtype: str or None """ logic_type = 'None' filename = '' if name in self._userlogics: try: filename = self._userlogics[name].get('filename', '') except: logger.warning("return_logictype: self._userlogics[name] = '{}'".format(str(self._userlogics[name]))) logger.warning("return_logictype: self._userlogics = '{}'".format(str(self._userlogics))) elif name in self._systemlogics: filename = self._systemlogics[name].get('filename', '') logic_type = 'Python' else: logger.info("return_logictype: name {} is not loaded".format(name)) # load /etc/logic.yaml if logic is not in the loaded logics conf_filename = os.path.join(self._get_etc_dir(), 'logic') config = shyaml.yaml_load_roundtrip(conf_filename) if config is not None: if name in config: filename = config[name].get('filename', '') if filename != '': blocklyname = os.path.splitext(os.path.basename(filename))[0]+'.blockly' if os.path.isfile(os.path.join(self.get_logics_dir(), filename)): logic_type = 'Python' if os.path.isfile(os.path.join(self.get_logics_dir(), blocklyname)): logic_type = 'Blockly' logger.debug("return_logictype: name '{}', filename '{}', logic_type '{}'".format(name, filename, logic_type)) return logic_type
def update_config_section(self, param_dict): """ Update the config section of ../etc/plugin.yaml :param param_dict: dict with the pareters that should be updated :return: """ param_names = list(self.metadata.parameters.keys()) self.logger.debug("update_config_section: Beginning to update section '{}' of ../etc/plugin.yaml".format(self._configname)) self.logger.debug("update_config_section: valid parameter names to update = {}".format(param_names)) self.logger.info("update_config_section: Config file = '{}', update data = {}".format(self._configfilename, param_dict)) # read plugin.yaml plugin_conf = shyaml.yaml_load_roundtrip(self._configfilename) sect = plugin_conf.get(self._configname) if sect is None: self.logger.error("update_config_section: Config section '{}' not found in ../etc/plugin.yaml".format(self._configname)) return parameters_changed = False for param in param_dict: if param in param_names: self.logger.info("update_config_section: Changing Parameter '{}' -> type = '{}' from '{}' to '{}'".format(param, self.metadata.parameters[param]['type'], sect.get(param, None), param_dict[param])) if param_dict[param] == '' or param_dict[param] == {} or param_dict[param] == []: del sect[param] else: sect[param] = param_dict[param] parameters_changed = True else: self.logger.error("update_config_section: Invalid parameter '{}' specified for update".format(param, param_dict[param])) self.logger.debug("update_config_section: Config section content = '{}'".format(sect)) # write plugin.yaml if parameters_changed: shyaml.yaml_save_roundtrip(self._configfilename, plugin_conf, True) self.logger.debug("update_config_section: Finished updating section '{}' of ../etc/plugin.yaml".format(self._configname)) return
def update(self, id='', action=''): self.logger.info("PluginController.update(id='{}', action='{}')".format(id, action)) if action == '': # Update section for plugin in etc/plugin.yaml params = self.get_body() if params is None: self.logger.warning("PluginController.update(): section '{}': Bad, add request".format(id)) raise cherrypy.HTTPError(status=411) self.logger.info("PluginController.update(): section '{}' = {}".format(id, params)) config_filename = self.get_config_filename() if self.test_for_old_config(config_filename): # make it 'readonly', if plugin.conf is used response = {'result': 'error', 'description': 'Updateing .CONF files is not supported'} else: response = {} plugin_conf = shyaml.yaml_load_roundtrip(config_filename) sect = plugin_conf.get(id) if sect is None: response = {'result': 'error', 'description': "Configuration section '{}' does not exist".format(id)} else: self.logger.debug("update: params = {}".format(params)) if params.get('config', {}).get('plugin_enabled', None) == True: del params['config']['plugin_enabled'] plugin_conf[id] = params.get('config', {}) shyaml.yaml_save_roundtrip(config_filename, plugin_conf, False) response = {'result': 'ok'} elif action in ['start','stop']: response = self.handle_plugin_action(id, action) else: response = {'result': 'error', 'description': "Plugin '{}': unknown action '{}'".format(id, action)} self.logger.warning("PluginController.update(): " + response['description']) self.logger.info("PluginController.update(): response = {}".format(response)) return json.dumps(response)
def update_config_section(self, active, section, config_list): """ Update file /etc/logic.yaml This method creates/updates a section in /etc/logic.yaml. If the section exist, it is cleared before new configuration imformation is written to the section :param active: True: logic is/should be active, False: Triggers are not written to /etc/logic.yaml :param section: name of section to configure in logics configurationfile :param config_list: list of configuration entries. Each entry of this list is a list with three string entries: ['key', 'value', 'comment'] :type active: bool :type section: str :type config_list: list of lists """ if section == '': logger.error( "update_config_section: No section name specified. Not updatind logics configuration." ) return False if self.return_config_type() != YAML_FILE: logger.error( "update_config_section: Editing of configuration only possible with new (yaml) config format" ) return False # load /etc/logic.yaml conf_filename = os.path.join(self._get_etc_dir(), 'logic') conf = shyaml.yaml_load_roundtrip(conf_filename) if conf is None: conf = shyaml.get_emptynode() # empty section if conf.get(section, None) == None: conf[section] = shyaml.get_emptynode() if conf[section].get('filename', None) != None: del conf[section]['filename'] if conf[section].get('cycle', None) != None: del conf[section]['cycle'] if conf[section].get('crontab', None) != None: del conf[section]['crontab'] if conf[section].get('watch_item', None) != None: del conf[section]['watch_item'] # add entries to section logger.info("update_config_section: section {}".format(section)) for c in config_list: # process config entries key = c[0].strip() value = c[1] comment = c[2] logger.info(" - key={}, value={}, comment={}".format( key, str(value), str(comment))) if isinstance(value, str): value = value.strip() comment = comment.strip() if value != '' and value[0] == '[' and value[-1] == ']': # convert a list of triggers to list, if given as a string value = ast.literal_eval(value) if comment != '': comment = ast.literal_eval(comment) else: # process single trigger if active or (key == 'filename'): conf[section][key] = value if comment != '': conf[section].yaml_add_eol_comment(comment, key, column=50) elif isinstance(value, int) or isinstance( value, bool) or isinstance(value, float): comment = comment.strip() # process single trigger if active: conf[section][key] = value if comment != '': conf[section].yaml_add_eol_comment(comment, key, column=50) else: logger.warning( "update_config_section: unsupported datatype for key '{}'". format(key)) if active: if isinstance(value, list): # process a list of triggers conf[section][key] = shyaml.get_commentedseq(value) listvalue = True for i in range(len(value)): if comment != '': if comment[i] != '': conf[section][key].yaml_add_eol_comment( comment[i], i, column=50) if conf[section] == shyaml.get_emptynode(): conf[section] = None shyaml.yaml_save_roundtrip(conf_filename, conf, True)
def update_config_section(self, active, section, config_list): """ Update file /etc/logic.yaml This method creates/updates a section in /etc/logic.yaml. If the section exist, it is cleared before new configuration imformation is written to the section :param active: True: logic is/should be active, False: Triggers are not written to /etc/logic.yaml :param section: name of section to configure in logics configurationfile :param config_list: list of configuration entries. Each entry of this list is a list with three string entries: ['key', 'value', 'comment'] :type active: bool :type section: str :type config_list: list of lists """ if section == '': logger.error("update_config_section: No section name specified. Not updatind logics configuration.") return False if self.return_config_type() != YAML_FILE: logger.error("update_config_section: Editing of configuration only possible with new (yaml) config format") return False # load /etc/logic.yaml conf_filename = os.path.join(self._get_etc_dir(), 'logic') conf = shyaml.yaml_load_roundtrip(conf_filename) if conf is None: conf = shyaml.get_emptynode() # empty section if conf.get(section, None) == None: conf[section] = shyaml.get_emptynode() del conf[section]['filename'] del conf[section]['cycle'] del conf[section]['crontab'] del conf[section]['watch_item'] # add entries to section logger.info("update_config_section: section {}".format(section)) for c in config_list: # process config entries key = c[0].strip() value = c[1] comment = c[2] logger.info(" - key={}, value={}, comment={}".format(key, str(value), str(comment))) if isinstance(value, str): value = value.strip() comment = comment.strip() if value != '' and value[0] == '[' and value[-1] == ']': # convert a list of triggers to list, if given as a string value = ast.literal_eval(value) if comment != '': comment = ast.literal_eval(comment) else: # process single trigger if active or (key == 'filename'): conf[section][key] = value if comment != '': conf[section].yaml_add_eol_comment(comment, key, column=50) elif isinstance(value, int) or isinstance(value, bool) or isinstance(value, float): comment = comment.strip() # process single trigger if active: conf[section][key] = value if comment != '': conf[section].yaml_add_eol_comment(comment, key, column=50) else: logger.warning("update_config_section: unsupported datatype for key '{}'".format(key)) if active: if isinstance(value, list): # process a list of triggers conf[section][key] = shyaml.get_commentedseq(value) listvalue = True for i in range(len(value)): if comment != '': if comment[i] != '': conf[section][key].yaml_add_eol_comment(comment[i], i, column=50) if conf[section] == shyaml.get_emptynode(): conf[section] = None shyaml.yaml_save_roundtrip(conf_filename, conf, True)
def plugin_set_config_html(self, plugin_section='', config=''): """ Is called by items.html when an item value has been changed plugin_set_config.html?plugin_section=' + pluginsection + '&config=' + configstr; """ if config == '': self.logger.error("plugin_set_config_html: 'config' not specified") return 'false' if plugin_section == '': self.logger.error( "plugin_set_config_html: 'plugin_section' not specified") return 'false' self.logger.warning( "plugin_set_config_html: pluginconfig '{}' set to '{}'".format( plugin_section, config)) # to do: # - load etc/plugin.yaml for round-trip config_filename = self.plugins._get_plugin_conf_filename() self.logger.warning( 'Loading config_filename: {}'.format(config_filename)) plugin_yaml = shyaml.yaml_load_roundtrip(config_filename) self.logger.warning('plugin_yaml: {}'.format(plugin_yaml)) # - remove all entries of the section that don't start with plugin_ (all beside plugin_name) self.logger.warning('1: plugin_yaml[{}]: {}'.format( plugin_section, dict(plugin_yaml[plugin_section]))) key_list = list(plugin_yaml[plugin_section].keys()) for key in key_list: if key != 'plugin_name': del plugin_yaml[plugin_section][key] self.logger.warning('2: plugin_yaml[{}]: {}'.format( plugin_section, dict(plugin_yaml[plugin_section]))) # - add all entries to the section which just were received from the admin backend self.logger.warning('- {}:'.format(plugin_section)) config_dict = json.loads(config) # change class_path to plugin_name if 'class_path' in config_dict.keys(): if config_dict['class_path'].startswith('plugins.'): plugin_yaml[plugin_section]['plugin_name'] = config_dict[ 'class_path'][8:] del config_dict['class_path'] # handle plugin_enabled if 'plugin_enabled' in config_dict.keys(): if str(config_dict['plugin_enabled']).lower() == 'false': plugin_yaml[plugin_section]['plugin_enabled'] = False else: del config_dict['plugin_enabled'] # save the rest of the parameters to plugin.yaml for key in config_dict: self.logger.warning('- {}: {}'.format(key, config_dict[key])) plugin_yaml[plugin_section][key] = config_dict[key] self.logger.warning('3: plugin_yaml[{}]: {}'.format( plugin_section, dict(plugin_yaml[plugin_section]))) # - save etc/plugin.yaml self.logger.warning( 'Saving config_filename: {}'.format(config_filename)) shyaml.yaml_save_roundtrip(config_filename, plugin_yaml, create_backup=True) # self.logger.warning("Config-Information not saved to etc/plugin.yaml") # item_data = [] # item = self.items.return_item(item_path) # if 'num' in item.type(): # if "." in value or "," in value: # value = float(value) # else: # value = int(value) # item(value, caller='admin') return '{"result": "true"}'