summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/templates/frr/bgpd.frr.j232
-rw-r--r--data/templates/load-balancing/haproxy.cfg.j213
-rw-r--r--interface-definitions/include/bgp/bmp-monitor-afi-policy.xml.i14
-rw-r--r--interface-definitions/include/bgp/protocol-common-config.xml.i86
-rw-r--r--interface-definitions/include/firewall/action.xml.i8
-rw-r--r--interface-definitions/include/firewall/ipv4-custom-name.xml.i1
-rw-r--r--interface-definitions/include/firewall/ipv6-custom-name.xml.i1
-rw-r--r--interface-definitions/include/pki/certificate-multi.xml.i15
-rw-r--r--interface-definitions/load-balancing-haproxy.xml.in2
-rw-r--r--python/vyos/ifconfig/interface.py2
-rw-r--r--python/vyos/system/grub.py2
-rwxr-xr-xsmoketest/scripts/cli/test_firewall.py36
-rwxr-xr-xsmoketest/scripts/cli/test_protocols_bgp.py56
-rwxr-xr-xsrc/conf_mode/load-balancing-haproxy.py20
-rwxr-xr-xsrc/conf_mode/protocols_bgp.py23
-rwxr-xr-xsrc/op_mode/image_installer.py30
16 files changed, 314 insertions, 27 deletions
diff --git a/data/templates/frr/bgpd.frr.j2 b/data/templates/frr/bgpd.frr.j2
index 641dac44a..679ba8b04 100644
--- a/data/templates/frr/bgpd.frr.j2
+++ b/data/templates/frr/bgpd.frr.j2
@@ -470,6 +470,38 @@ router bgp {{ system_as }} {{ 'vrf ' ~ vrf if vrf is vyos_defined }}
{% endfor %}
{% endif %}
!
+{% if bmp is vyos_defined %}
+{% if bmp.mirror_buffer_limit is vyos_defined %}
+ bmp mirror buffer-limit {{ bmp.mirror_buffer_limit }}
+ !
+{% endif %}
+{% if bmp.target is vyos_defined %}
+{% for bmp, bmp_config in bmp.target.items() %}
+ bmp targets {{ bmp }}
+{% if bmp_config.mirror is vyos_defined %}
+ bmp mirror
+{% endif %}
+{% if bmp_config.monitor is vyos_defined %}
+{% if bmp_config.monitor.ipv4_unicast.pre_policy is vyos_defined %}
+ bmp monitor ipv4 unicast pre-policy
+{% endif %}
+{% if bmp_config.monitor.ipv4_unicast.post_policy is vyos_defined %}
+ bmp monitor ipv4 unicast post-policy
+{% endif %}
+{% if bmp_config.monitor.ipv6_unicast.pre_policy is vyos_defined %}
+ bmp monitor ipv6 unicast pre-policy
+{% endif %}
+{% if bmp_config.monitor.ipv6_unicast.post_policy is vyos_defined %}
+ bmp monitor ipv6 unicast post-policy
+{% endif %}
+{% endif %}
+{% if bmp_config.address is vyos_defined %}
+ bmp connect {{ bmp_config.address }} port {{ bmp_config.port }} min-retry {{ bmp_config.min_retry }} max-retry {{ bmp_config.max_retry }}
+{% endif %}
+{% endfor %}
+ exit
+{% endif %}
+{% endif %}
{% if peer_group is vyos_defined %}
{% for peer, config in peer_group.items() %}
{{ bgp_neighbor(peer, config, true) }}
diff --git a/data/templates/load-balancing/haproxy.cfg.j2 b/data/templates/load-balancing/haproxy.cfg.j2
index a75ee9904..defb76fba 100644
--- a/data/templates/load-balancing/haproxy.cfg.j2
+++ b/data/templates/load-balancing/haproxy.cfg.j2
@@ -50,13 +50,19 @@ defaults
{% if service is vyos_defined %}
{% for front, front_config in service.items() %}
frontend {{ front }}
-{% set ssl_front = 'ssl crt /run/haproxy/' ~ front_config.ssl.certificate ~ '.pem' if front_config.ssl.certificate is vyos_defined else '' %}
+{% set ssl_front = [] %}
+{% if front_config.ssl.certificate is vyos_defined and front_config.ssl.certificate is iterable %}
+{% for cert in front_config.ssl.certificate %}
+{% set _ = ssl_front.append('crt /run/haproxy/' ~ cert ~ '.pem') %}
+{% endfor %}
+{% endif %}
+{% set ssl_directive = 'ssl' if ssl_front else '' %}
{% if front_config.listen_address is vyos_defined %}
{% for address in front_config.listen_address %}
- bind {{ address | bracketize_ipv6 }}:{{ front_config.port }} {{ ssl_front }}
+ bind {{ address | bracketize_ipv6 }}:{{ front_config.port }} {{ ssl_directive }} {{ ssl_front | join(' ') }}
{% endfor %}
{% else %}
- bind :::{{ front_config.port }} v4v6 {{ ssl_front }}
+ bind :::{{ front_config.port }} v4v6 {{ ssl_directive }} {{ ssl_front | join(' ') }}
{% endif %}
{% if front_config.redirect_http_to_https is vyos_defined %}
http-request redirect scheme https unless { ssl_fc }
@@ -161,4 +167,3 @@ backend {{ back }}
{% endfor %}
{% endif %}
-
diff --git a/interface-definitions/include/bgp/bmp-monitor-afi-policy.xml.i b/interface-definitions/include/bgp/bmp-monitor-afi-policy.xml.i
new file mode 100644
index 000000000..261d60232
--- /dev/null
+++ b/interface-definitions/include/bgp/bmp-monitor-afi-policy.xml.i
@@ -0,0 +1,14 @@
+<!-- include start from bgp/bmp-monitor-afi-policy.xml.i -->
+<leafNode name="pre-policy">
+ <properties>
+ <help>Send state before policy and filter processing</help>
+ <valueless/>
+ </properties>
+</leafNode>
+<leafNode name="post-policy">
+ <properties>
+ <help>Send state with policy and filters applied</help>
+ <valueless/>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/include/bgp/protocol-common-config.xml.i b/interface-definitions/include/bgp/protocol-common-config.xml.i
index c379ba95c..dce61ee77 100644
--- a/interface-definitions/include/bgp/protocol-common-config.xml.i
+++ b/interface-definitions/include/bgp/protocol-common-config.xml.i
@@ -909,6 +909,92 @@
</node>
</children>
</node>
+<node name="bmp">
+ <properties>
+ <help>BGP Monitoring Protocol (BMP)</help>
+ </properties>
+ <children>
+ <leafNode name="mirror-buffer-limit">
+ <properties>
+ <help>Maximum memory used for buffered mirroring messages (in bytes)</help>
+ <valueHelp>
+ <format>u32:0-4294967294</format>
+ <description>Limit in bytes</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-4294967294"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <tagNode name="target">
+ <properties>
+ <help>BMP target</help>
+ </properties>
+ <children>
+ #include <include/address-ipv4-ipv6-single.xml.i>
+ #include <include/port-number.xml.i>
+ <leafNode name="port">
+ <defaultValue>5000</defaultValue>
+ </leafNode>
+ <leafNode name="min-retry">
+ <properties>
+ <help>Minimum connection retry interval (in milliseconds)</help>
+ <valueHelp>
+ <format>u32:100-86400000</format>
+ <description>Minimum connection retry interval</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 100-86400000"/>
+ </constraint>
+ </properties>
+ <defaultValue>1000</defaultValue>
+ </leafNode>
+ <leafNode name="max-retry">
+ <properties>
+ <help>Maximum connection retry interval</help>
+ <valueHelp>
+ <format>u32:100-4294967295</format>
+ <description>Maximum connection retry interval</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 100-86400000"/>
+ </constraint>
+ </properties>
+ <defaultValue>2000</defaultValue>
+ </leafNode>
+ <leafNode name="mirror">
+ <properties>
+ <help>Send BMP route mirroring messages</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <node name="monitor">
+ <properties>
+ <help>Send BMP route monitoring messages</help>
+ </properties>
+ <children>
+ <node name="ipv4-unicast">
+ <properties>
+ <help>Address family IPv4 unicast</help>
+ </properties>
+ <children>
+ #include <include/bgp/bmp-monitor-afi-policy.xml.i>
+ </children>
+ </node>
+ <node name="ipv6-unicast">
+ <properties>
+ <help>Address family IPv6 unicast</help>
+ </properties>
+ <children>
+ #include <include/bgp/bmp-monitor-afi-policy.xml.i>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+ </tagNode>
+ </children>
+</node>
<tagNode name="interface">
<properties>
<help>Configure interface related parameters, e.g. MPLS</help>
diff --git a/interface-definitions/include/firewall/action.xml.i b/interface-definitions/include/firewall/action.xml.i
index 954e4f23e..e1f0c6cb6 100644
--- a/interface-definitions/include/firewall/action.xml.i
+++ b/interface-definitions/include/firewall/action.xml.i
@@ -3,7 +3,7 @@
<properties>
<help>Rule action</help>
<completionHelp>
- <list>accept continue jump reject return drop queue synproxy</list>
+ <list>accept continue jump reject return drop queue offload synproxy</list>
</completionHelp>
<valueHelp>
<format>accept</format>
@@ -34,11 +34,15 @@
<description>Enqueue packet to userspace</description>
</valueHelp>
<valueHelp>
+ <format>offload</format>
+ <description>Offload packet via flowtable</description>
+ </valueHelp>
+ <valueHelp>
<format>synproxy</format>
<description>Synproxy connections</description>
</valueHelp>
<constraint>
- <regex>(accept|continue|jump|reject|return|drop|queue|synproxy)</regex>
+ <regex>(accept|continue|jump|reject|return|drop|queue|offload|synproxy)</regex>
</constraint>
</properties>
</leafNode>
diff --git a/interface-definitions/include/firewall/ipv4-custom-name.xml.i b/interface-definitions/include/firewall/ipv4-custom-name.xml.i
index 9d6ecfaf2..c6420fe1f 100644
--- a/interface-definitions/include/firewall/ipv4-custom-name.xml.i
+++ b/interface-definitions/include/firewall/ipv4-custom-name.xml.i
@@ -33,6 +33,7 @@
<children>
#include <include/firewall/common-rule-ipv4.xml.i>
#include <include/firewall/inbound-interface.xml.i>
+ #include <include/firewall/offload-target.xml.i>
#include <include/firewall/outbound-interface.xml.i>
</children>
</tagNode>
diff --git a/interface-definitions/include/firewall/ipv6-custom-name.xml.i b/interface-definitions/include/firewall/ipv6-custom-name.xml.i
index 81610babf..2cc45a60c 100644
--- a/interface-definitions/include/firewall/ipv6-custom-name.xml.i
+++ b/interface-definitions/include/firewall/ipv6-custom-name.xml.i
@@ -33,6 +33,7 @@
<children>
#include <include/firewall/common-rule-ipv6.xml.i>
#include <include/firewall/inbound-interface.xml.i>
+ #include <include/firewall/offload-target.xml.i>
#include <include/firewall/outbound-interface.xml.i>
</children>
</tagNode>
diff --git a/interface-definitions/include/pki/certificate-multi.xml.i b/interface-definitions/include/pki/certificate-multi.xml.i
new file mode 100644
index 000000000..c49c5d9b2
--- /dev/null
+++ b/interface-definitions/include/pki/certificate-multi.xml.i
@@ -0,0 +1,15 @@
+<!-- include start from pki/certificate-multi.xml.i -->
+<leafNode name="certificate">
+ <properties>
+ <help>Certificate in PKI configuration</help>
+ <completionHelp>
+ <path>pki certificate</path>
+ </completionHelp>
+ <valueHelp>
+ <format>txt</format>
+ <description>Name of certificate in PKI configuration</description>
+ </valueHelp>
+ <multi/>
+ </properties>
+</leafNode>
+<!-- include end -->
diff --git a/interface-definitions/load-balancing-haproxy.xml.in b/interface-definitions/load-balancing-haproxy.xml.in
index 564c335ec..8f6bd3a99 100644
--- a/interface-definitions/load-balancing-haproxy.xml.in
+++ b/interface-definitions/load-balancing-haproxy.xml.in
@@ -49,7 +49,7 @@
<help>SSL Certificate, SSL Key and CA</help>
</properties>
<children>
- #include <include/pki/certificate.xml.i>
+ #include <include/pki/certificate-multi.xml.i>
</children>
</node>
</children>
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py
index 1586710db..56dcde214 100644
--- a/python/vyos/ifconfig/interface.py
+++ b/python/vyos/ifconfig/interface.py
@@ -115,7 +115,7 @@ class Interface(Control):
},
'vrf': {
'shellcmd': 'ip -json -detail link list dev {ifname}',
- 'format': lambda j: jmespath.search('[*].master | [0]', json.loads(j)),
+ 'format': lambda j: jmespath.search('[?linkinfo.info_slave_kind == `vrf`].master | [0]', json.loads(j)),
},
}
diff --git a/python/vyos/system/grub.py b/python/vyos/system/grub.py
index 0ac16af9a..2692aaea1 100644
--- a/python/vyos/system/grub.py
+++ b/python/vyos/system/grub.py
@@ -138,6 +138,8 @@ def version_list(root_dir: str = '') -> list[str]:
versions_list: list[str] = []
for file in versions_files:
versions_list.append(file.stem)
+ versions_list.sort(reverse=True)
+
return versions_list
diff --git a/smoketest/scripts/cli/test_firewall.py b/smoketest/scripts/cli/test_firewall.py
index 066ed707b..5cfddb269 100755
--- a/smoketest/scripts/cli/test_firewall.py
+++ b/smoketest/scripts/cli/test_firewall.py
@@ -753,5 +753,41 @@ class TestFirewall(VyOSUnitTestSHIM.TestCase):
self.verify_nftables_chain([['accept']], 'ip vyos_conntrack', 'FW_CONNTRACK')
self.verify_nftables_chain([['accept']], 'ip6 vyos_conntrack', 'FW_CONNTRACK')
+ def test_zone_flow_offload(self):
+ self.cli_set(['firewall', 'flowtable', 'smoketest', 'interface', 'eth0'])
+ self.cli_set(['firewall', 'flowtable', 'smoketest', 'offload', 'hardware'])
+
+ # QEMU virtual NIC does not support hw-tc-offload
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ self.cli_set(['firewall', 'flowtable', 'smoketest', 'offload', 'software'])
+
+ self.cli_set(['firewall', 'ipv4', 'name', 'smoketest', 'rule', '1', 'action', 'offload'])
+ self.cli_set(['firewall', 'ipv4', 'name', 'smoketest', 'rule', '1', 'offload-target', 'smoketest'])
+
+ self.cli_set(['firewall', 'ipv6', 'name', 'smoketest', 'rule', '1', 'action', 'offload'])
+ self.cli_set(['firewall', 'ipv6', 'name', 'smoketest', 'rule', '1', 'offload-target', 'smoketest'])
+
+ self.cli_commit()
+
+ nftables_search = [
+ ['chain NAME_smoketest'],
+ ['flow add @VYOS_FLOWTABLE_smoketest']
+ ]
+
+ self.verify_nftables(nftables_search, 'ip vyos_filter')
+
+ nftables_search = [
+ ['chain NAME6_smoketest'],
+ ['flow add @VYOS_FLOWTABLE_smoketest']
+ ]
+
+ self.verify_nftables(nftables_search, 'ip6 vyos_filter')
+
+ # Check conntrack
+ self.verify_nftables_chain([['accept']], 'ip vyos_conntrack', 'FW_CONNTRACK')
+ self.verify_nftables_chain([['accept']], 'ip6 vyos_conntrack', 'FW_CONNTRACK')
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/smoketest/scripts/cli/test_protocols_bgp.py b/smoketest/scripts/cli/test_protocols_bgp.py
index 97dab255e..8102a3153 100755
--- a/smoketest/scripts/cli/test_protocols_bgp.py
+++ b/smoketest/scripts/cli/test_protocols_bgp.py
@@ -15,6 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import unittest
+from subprocess import run
from base_vyostest_shim import VyOSUnitTestSHIM
@@ -1148,5 +1149,60 @@ class TestProtocolsBGP(VyOSUnitTestSHIM.TestCase):
self.assertIn(f' locator {locator_name}', frrconfig)
self.assertIn(f' sid vpn per-vrf export {sid}', frrconfig)
+ def test_bgp_25_bmp(self):
+ target_name = 'instance-bmp'
+ target_address = '127.0.0.1'
+ target_port = '5000'
+ min_retry = '1024'
+ max_retry = '2048'
+ monitor_ipv4 = 'pre-policy'
+ monitor_ipv6 = 'pre-policy'
+ mirror_buffer = '32000000'
+ bmp_path = base_path + ['bmp']
+ target_path = bmp_path + ['target', target_name]
+ bgpd_bmp_pid = process_named_running('bgpd', 'bmp')
+ command = ['/opt/vyatta/bin/vyatta-op-cmd-wrapper', 'restart', 'bgp']
+
+ self.cli_set(bmp_path)
+ # by default the 'bmp' module not loaded for the bgpd
+ # expect Error
+ if not bgpd_bmp_pid:
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ # add required 'bmp' module to bgpd and restart bgpd
+ self.cli_delete(bmp_path)
+ self.cli_set(['system', 'frr', 'bmp'])
+ self.cli_commit()
+ # restart bgpd to apply "-M bmp" and update PID
+ run(command, input='Y', text=True)
+ self.daemon_pid = process_named_running(PROCESS_NAME)
+
+ # set bmp config but not set address
+ self.cli_set(target_path + ['port', target_port])
+ # address is not set, expect Error
+ with self.assertRaises(ConfigSessionError):
+ self.cli_commit()
+
+ # config other bmp options
+ self.cli_set(target_path + ['address', target_address])
+ self.cli_set(bmp_path + ['mirror-buffer-limit', mirror_buffer])
+ self.cli_set(target_path + ['port', target_port])
+ self.cli_set(target_path + ['min-retry', min_retry])
+ self.cli_set(target_path + ['max-retry', max_retry])
+ self.cli_set(target_path + ['mirror'])
+ self.cli_set(target_path + ['monitor', 'ipv4-unicast', monitor_ipv4])
+ self.cli_set(target_path + ['monitor', 'ipv6-unicast', monitor_ipv6])
+ self.cli_commit()
+
+ # Verify bgpd bmp configuration
+ frrconfig = self.getFRRconfig(f'router bgp {ASN}')
+ self.assertIn(f'bmp mirror buffer-limit {mirror_buffer}', frrconfig)
+ self.assertIn(f'bmp targets {target_name}', frrconfig)
+ self.assertIn(f'bmp mirror', frrconfig)
+ self.assertIn(f'bmp monitor ipv4 unicast {monitor_ipv4}', frrconfig)
+ self.assertIn(f'bmp monitor ipv6 unicast {monitor_ipv6}', frrconfig)
+ self.assertIn(f'bmp connect {target_address} port {target_port} min-retry {min_retry} max-retry {max_retry}', frrconfig)
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/src/conf_mode/load-balancing-haproxy.py b/src/conf_mode/load-balancing-haproxy.py
index ec4311bb5..333ebc66c 100755
--- a/src/conf_mode/load-balancing-haproxy.py
+++ b/src/conf_mode/load-balancing-haproxy.py
@@ -108,17 +108,19 @@ def generate(lb):
if 'ssl' in front_config:
if 'certificate' in front_config['ssl']:
- cert_name = front_config['ssl']['certificate']
- pki_cert = lb['pki']['certificate'][cert_name]
- cert_file_path = os.path.join(load_balancing_dir, f'{cert_name}.pem')
- cert_key_path = os.path.join(load_balancing_dir, f'{cert_name}.pem.key')
+ cert_names = front_config['ssl']['certificate']
- with open(cert_file_path, 'w') as f:
- f.write(wrap_certificate(pki_cert['certificate']))
+ for cert_name in cert_names:
+ pki_cert = lb['pki']['certificate'][cert_name]
+ cert_file_path = os.path.join(load_balancing_dir, f'{cert_name}.pem')
+ cert_key_path = os.path.join(load_balancing_dir, f'{cert_name}.pem.key')
- if 'private' in pki_cert and 'key' in pki_cert['private']:
- with open(cert_key_path, 'w') as f:
- f.write(wrap_private_key(pki_cert['private']['key']))
+ with open(cert_file_path, 'w') as f:
+ f.write(wrap_certificate(pki_cert['certificate']))
+
+ if 'private' in pki_cert and 'key' in pki_cert['private']:
+ with open(cert_key_path, 'w') as f:
+ f.write(wrap_private_key(pki_cert['private']['key']))
if 'ca_certificate' in front_config['ssl']:
ca_name = front_config['ssl']['ca_certificate']
diff --git a/src/conf_mode/protocols_bgp.py b/src/conf_mode/protocols_bgp.py
index 557f0a9e9..bf807fa5f 100755
--- a/src/conf_mode/protocols_bgp.py
+++ b/src/conf_mode/protocols_bgp.py
@@ -30,6 +30,7 @@ from vyos.template import render_to_string
from vyos.utils.dict import dict_search
from vyos.utils.network import get_interface_vrf
from vyos.utils.network import is_addr_assigned
+from vyos.utils.process import process_named_running
from vyos import ConfigError
from vyos import frr
from vyos import airbag
@@ -49,8 +50,13 @@ def get_config(config=None):
# eqivalent of the C foo ? 'a' : 'b' statement
base = vrf and ['vrf', 'name', vrf, 'protocols', 'bgp'] or base_path
- bgp = conf.get_config_dict(base, key_mangling=('-', '_'),
- get_first_key=True, no_tag_node_value_mangle=True)
+ bgp = conf.get_config_dict(
+ base,
+ key_mangling=('-', '_'),
+ get_first_key=True,
+ no_tag_node_value_mangle=True,
+ with_recursive_defaults=True,
+ )
bgp['dependent_vrfs'] = conf.get_config_dict(['vrf', 'name'],
key_mangling=('-', '_'),
@@ -247,6 +253,19 @@ def verify(bgp):
if 'system_as' not in bgp:
raise ConfigError('BGP system-as number must be defined!')
+ # Verify BMP
+ if 'bmp' in bgp:
+ # check bmp flag "bgpd -d -F traditional --daemon -A 127.0.0.1 -M rpki -M bmp"
+ if not process_named_running('bgpd', 'bmp'):
+ raise ConfigError(
+ f'"bmp" flag is not found in bgpd. Configure "set system frr bmp" and restart bgp process'
+ )
+ # check bmp target
+ if 'target' in bgp['bmp']:
+ for target, target_config in bgp['bmp']['target'].items():
+ if 'address' not in target_config:
+ raise ConfigError(f'BMP target "{target}" address must be defined!')
+
# Verify vrf on interface and bgp section
if 'interface' in bgp:
for interface in bgp['interface']:
diff --git a/src/op_mode/image_installer.py b/src/op_mode/image_installer.py
index 09501ef46..6a8797aec 100755
--- a/src/op_mode/image_installer.py
+++ b/src/op_mode/image_installer.py
@@ -22,6 +22,7 @@ from pathlib import Path
from shutil import copy, chown, rmtree, copytree
from glob import glob
from sys import exit
+from os import environ
from time import sleep
from typing import Union
from urllib.parse import urlparse
@@ -463,16 +464,22 @@ def validate_signature(file_path: str, sign_type: str) -> None:
print('Signature is valid')
def download_file(local_file: str, remote_path: str, vrf: str,
+ username: str, password: str,
progressbar: bool = False, check_space: bool = False):
+ environ['REMOTE_USERNAME'] = username
+ environ['REMOTE_PASSWORD'] = password
if vrf is None:
download(local_file, remote_path, progressbar=progressbar,
check_space=check_space, raise_error=True)
else:
- vrf_cmd = f'ip vrf exec {vrf} {external_download_script} \
+ vrf_cmd = f'REMOTE_USERNAME={username} REMOTE_PASSWORD={password} \
+ ip vrf exec {vrf} {external_download_script} \
--local-file {local_file} --remote-path {remote_path}'
cmd(vrf_cmd)
-def image_fetch(image_path: str, vrf: str = None, no_prompt: bool = False) -> Path:
+def image_fetch(image_path: str, vrf: str = None,
+ username: str = '', password: str = '',
+ no_prompt: bool = False) -> Path:
"""Fetch an ISO image
Args:
@@ -486,6 +493,7 @@ def image_fetch(image_path: str, vrf: str = None, no_prompt: bool = False) -> Pa
if urlparse(image_path).scheme:
# download an image
download_file(ISO_DOWNLOAD_PATH, image_path, vrf,
+ username, password,
progressbar=True, check_space=True)
# download a signature
@@ -493,7 +501,8 @@ def image_fetch(image_path: str, vrf: str = None, no_prompt: bool = False) -> Pa
for sign_type in ['minisig', 'asc']:
try:
download_file(f'{ISO_DOWNLOAD_PATH}.{sign_type}',
- f'{image_path}.{sign_type}', vrf)
+ f'{image_path}.{sign_type}', vrf,
+ username, password)
sign_file = (True, sign_type)
break
except Exception:
@@ -744,7 +753,8 @@ def install_image() -> None:
@compat.grub_cfg_update
-def add_image(image_path: str, vrf: str = None, no_prompt: bool = False) -> None:
+def add_image(image_path: str, vrf: str = None, username: str = '',
+ password: str = '', no_prompt: bool = False) -> None:
"""Add a new image
Args:
@@ -754,7 +764,7 @@ def add_image(image_path: str, vrf: str = None, no_prompt: bool = False) -> None
exit(MSG_ERR_LIVE)
# fetch an image
- iso_path: Path = image_fetch(image_path, vrf, no_prompt)
+ iso_path: Path = image_fetch(image_path, vrf, username, password, no_prompt)
try:
# mount an ISO
Path(DIR_ISO_MOUNT).mkdir(mode=0o755, parents=True)
@@ -858,8 +868,11 @@ def parse_arguments() -> Namespace:
help='vrf name for image download')
parser.add_argument('--no-prompt', action='store_true',
help='perform action non-interactively')
- parser.add_argument(
- '--image-path',
+ parser.add_argument('--username', default='',
+ help='username for image download')
+ parser.add_argument('--password', default='',
+ help='password for image download')
+ parser.add_argument('--image-path',
help='a path (HTTP or local file) to an image that needs to be installed'
)
# parser.add_argument('--image_new_name', help='a new name for image')
@@ -877,7 +890,8 @@ if __name__ == '__main__':
if args.action == 'install':
install_image()
if args.action == 'add':
- add_image(args.image_path, args.vrf, args.no_prompt)
+ add_image(args.image_path, args.vrf,
+ args.username, args.password, args.no_prompt)
exit()