diff options
| -rw-r--r-- | python/vyos/configverify.py | 27 | ||||
| -rwxr-xr-x | src/helpers/vyos_config_sync.py | 48 | ||||
| -rwxr-xr-x | src/services/vyos-http-api-server | 2 | 
3 files changed, 49 insertions, 28 deletions
| diff --git a/python/vyos/configverify.py b/python/vyos/configverify.py index 5d3723876..6508ccdd9 100644 --- a/python/vyos/configverify.py +++ b/python/vyos/configverify.py @@ -269,14 +269,33 @@ def verify_bridge_delete(config):          raise ConfigError(f'Interface "{interface}" cannot be deleted as it '                            f'is a member of bridge "{bridge_name}"!') -def verify_interface_exists(ifname): +def verify_interface_exists(ifname, warning_only=False):      """      Common helper function used by interface implementations to perform -    recurring validation if an interface actually exists. +    recurring validation if an interface actually exists. We first probe +    if the interface is defined on the CLI, if it's not found we try if +    it exists at the OS level.      """      import os -    if not os.path.exists(f'/sys/class/net/{ifname}'): -        raise ConfigError(f'Interface "{ifname}" does not exist!') +    from vyos.base import Warning +    from vyos.configquery import ConfigTreeQuery +    from vyos.utils.dict import dict_search_recursive + +    # Check if interface is present in CLI config +    config = ConfigTreeQuery() +    tmp = config.get_config_dict(['interfaces'], get_first_key=True) +    if bool(list(dict_search_recursive(tmp, ifname))): +        return True + +    # Interface not found on CLI, try Linux Kernel +    if os.path.exists(f'/sys/class/net/{ifname}'): +        return True + +    message = f'Interface "{ifname}" does not exist!' +    if warning_only: +        Warning(message) +        return False +    raise ConfigError(message)  def verify_source_interface(config):      """ diff --git a/src/helpers/vyos_config_sync.py b/src/helpers/vyos_config_sync.py index 572fea61f..77f7cd810 100755 --- a/src/helpers/vyos_config_sync.py +++ b/src/helpers/vyos_config_sync.py @@ -61,14 +61,16 @@ def post_request(url: str, -def retrieve_config(section: str = None) -> Optional[Dict[str, Any]]: +def retrieve_config(section: Optional[List[str]] = None) -> Optional[Dict[str, Any]]:      """Retrieves the configuration from the local server.      Args: -        section: str: The section of the configuration to retrieve. Default is None. +        section: List[str]: The section of the configuration to retrieve. +        Default is None.      Returns: -        Optional[Dict[str, Any]]: The retrieved configuration as a dictionary, or None if an error occurred. +        Optional[Dict[str, Any]]: The retrieved configuration as a +        dictionary, or None if an error occurred.      """      if section is None:          section = [] @@ -83,23 +85,21 @@ def retrieve_config(section: str = None) -> Optional[Dict[str, Any]]:  def set_remote_config(          address: str,          key: str, -        op: str, -        path: str = None, -        section: Optional[str] = None) -> Optional[Dict[str, Any]]: +        commands: List[Dict[str, Any]]) -> Optional[Dict[str, Any]]:      """Loads the VyOS configuration in JSON format to a remote host.      Args:          address (str): The address of the remote host.          key (str): The key to use for loading the configuration. -        path (Optional[str]): The path of the configuration. Default is None. -        section (Optional[str]): The section of the configuration to load. Default is None. +        commands (list): List of set/load commands for request, given as: +                         [{'op': str, 'path': list[str], 'section': dict}, +                         ...]      Returns: -        Optional[Dict[str, Any]]: The response from the remote host as a dictionary, or None if an error occurred. +        Optional[Dict[str, Any]]: The response from the remote host as a +        dictionary, or None if a RequestException occurred.      """ -    if path is None: -        path = []      headers = {'Content-Type': 'application/json'}      # Disable the InsecureRequestWarning @@ -107,9 +107,7 @@ def set_remote_config(      url = f'https://{address}/configure-section'      data = json.dumps({ -        'op': mode, -        'path': path, -        'section': section, +        'commands': commands,          'key': key      }) @@ -122,14 +120,14 @@ def set_remote_config(          return None -def is_section_revised(section: str) -> bool: +def is_section_revised(section: List[str]) -> bool:      from vyos.config_mgmt import is_node_revised      return is_node_revised(section)  def config_sync(secondary_address: str,                  secondary_key: str, -                sections: List[list], +                sections: List[list[str]],                  mode: str):      """Retrieve a config section from primary router in JSON format and send it to         secondary router @@ -142,21 +140,25 @@ def config_sync(secondary_address: str,      )      # Sync sections ("nat", "firewall", etc) +    commands = []      for section in sections:          config_json = retrieve_config(section=section)          # Check if config path deesn't exist, for example "set nat"          # we set empty value for config_json data          # As we cannot send to the remote host section "nat None" config          if not config_json: -            config_json = "" +            config_json = {}          logger.debug(              f"Retrieved config for section '{section}': {config_json}") -        set_config = set_remote_config(address=secondary_address, -                                       key=secondary_key, -                                       op=mode, -                                       path=section, -                                       section=config_json) -        logger.debug(f"Set config for section '{section}': {set_config}") + +        d = {'op': mode, 'path': section, 'section': config_json} +        commands.append(d) + +    set_config = set_remote_config(address=secondary_address, +                                   key=secondary_key, +                                   commands=commands) + +    logger.debug(f"Set config for sections '{sections}': {set_config}")  if __name__ == '__main__': diff --git a/src/services/vyos-http-api-server b/src/services/vyos-http-api-server index a7b14a1a3..77870a84c 100755 --- a/src/services/vyos-http-api-server +++ b/src/services/vyos-http-api-server @@ -463,7 +463,7 @@ def _configure_op(data: Union[ConfigureModel, ConfigureListModel,      endpoint = request.url.path      # Allow users to pass just one command -    if not isinstance(data, ConfigureListModel): +    if not isinstance(data, (ConfigureListModel, ConfigSectionListModel)):          data = [data]      else:          data = data.commands | 
