golden hour
/opt/saltstack/salt/lib/python3.10/site-packages/salt/modules
⬆️ Go Up
Upload
File/Folder
Size
Actions
__init__.py
35 B
Del
OK
__pycache__
-
Del
OK
acme.py
12.74 KB
Del
OK
aix_group.py
4.12 KB
Del
OK
aix_shadow.py
1.93 KB
Del
OK
aixpkg.py
24.15 KB
Del
OK
aliases.py
5.07 KB
Del
OK
alternatives.py
5.71 KB
Del
OK
ansiblegate.py
19.51 KB
Del
OK
apache.py
12.47 KB
Del
OK
apcups.py
2.15 KB
Del
OK
apf.py
3.09 KB
Del
OK
apkpkg.py
16 KB
Del
OK
aptly.py
15.28 KB
Del
OK
aptpkg.py
116.64 KB
Del
OK
archive.py
48.63 KB
Del
OK
arista_pyeapi.py
22.06 KB
Del
OK
artifactory.py
24.78 KB
Del
OK
at.py
10.72 KB
Del
OK
at_solaris.py
8.51 KB
Del
OK
augeas_cfg.py
13.93 KB
Del
OK
aws_sqs.py
6.55 KB
Del
OK
azurearm_compute.py
20.8 KB
Del
OK
azurearm_dns.py
15.8 KB
Del
OK
azurearm_network.py
82.99 KB
Del
OK
azurearm_resource.py
35.75 KB
Del
OK
bamboohr.py
7.36 KB
Del
OK
baredoc.py
11.13 KB
Del
OK
bcache.py
28.97 KB
Del
OK
beacons.py
27.82 KB
Del
OK
bigip.py
69.11 KB
Del
OK
bluez_bluetooth.py
6.76 KB
Del
OK
boto3_elasticache.py
37.34 KB
Del
OK
boto3_elasticsearch.py
53.17 KB
Del
OK
boto3_route53.py
39.82 KB
Del
OK
boto3_sns.py
12.93 KB
Del
OK
boto_apigateway.py
61.86 KB
Del
OK
boto_asg.py
35.69 KB
Del
OK
boto_cfn.py
7.95 KB
Del
OK
boto_cloudfront.py
12.75 KB
Del
OK
boto_cloudtrail.py
14.45 KB
Del
OK
boto_cloudwatch.py
10.99 KB
Del
OK
boto_cloudwatch_event.py
9.48 KB
Del
OK
boto_cognitoidentity.py
14.63 KB
Del
OK
boto_datapipeline.py
6.94 KB
Del
OK
boto_dynamodb.py
14.98 KB
Del
OK
boto_ec2.py
79.27 KB
Del
OK
boto_efs.py
14.05 KB
Del
OK
boto_elasticache.py
23.69 KB
Del
OK
boto_elasticsearch_domain.py
15.85 KB
Del
OK
boto_elb.py
35.53 KB
Del
OK
boto_elbv2.py
10.78 KB
Del
OK
boto_iam.py
75.62 KB
Del
OK
boto_iot.py
26.2 KB
Del
OK
boto_kinesis.py
19.62 KB
Del
OK
boto_kms.py
17.29 KB
Del
OK
boto_lambda.py
35.05 KB
Del
OK
boto_rds.py
34.92 KB
Del
OK
boto_route53.py
32.55 KB
Del
OK
boto_s3.py
4.24 KB
Del
OK
boto_s3_bucket.py
31.8 KB
Del
OK
boto_secgroup.py
25.22 KB
Del
OK
boto_sns.py
7.22 KB
Del
OK
boto_sqs.py
6.43 KB
Del
OK
boto_ssm.py
3.63 KB
Del
OK
boto_vpc.py
113.08 KB
Del
OK
bower.py
5.85 KB
Del
OK
bridge.py
10.81 KB
Del
OK
bsd_shadow.py
6.25 KB
Del
OK
btrfs.py
33.66 KB
Del
OK
cabal.py
3.79 KB
Del
OK
capirca_acl.py
40.04 KB
Del
OK
cassandra_cql.py
54.16 KB
Del
OK
cassandra_mod.py
4.3 KB
Del
OK
celery.py
3.33 KB
Del
OK
ceph.py
15.82 KB
Del
OK
chassis.py
1.52 KB
Del
OK
chef.py
4.66 KB
Del
OK
chocolatey.py
41.55 KB
Del
OK
chronos.py
2.89 KB
Del
OK
chroot.py
11.73 KB
Del
OK
cimc.py
23.02 KB
Del
OK
ciscoconfparse_mod.py
14.79 KB
Del
OK
cisconso.py
3.83 KB
Del
OK
cloud.py
9.39 KB
Del
OK
cmdmod.py
163.73 KB
Del
OK
composer.py
10.31 KB
Del
OK
config.py
16.98 KB
Del
OK
consul.py
69.3 KB
Del
OK
container_resource.py
12.94 KB
Del
OK
cp.py
31.98 KB
Del
OK
cpan.py
5.54 KB
Del
OK
cron.py
28.09 KB
Del
OK
cryptdev.py
10.08 KB
Del
OK
csf.py
16.04 KB
Del
OK
cyg.py
8.32 KB
Del
OK
daemontools.py
5.41 KB
Del
OK
data.py
3.85 KB
Del
OK
datadog_api.py
7.76 KB
Del
OK
ddns.py
7.12 KB
Del
OK
deb_apache.py
7.41 KB
Del
OK
deb_postgres.py
4.18 KB
Del
OK
debconfmod.py
4.06 KB
Del
OK
debian_ip.py
64.91 KB
Del
OK
debian_service.py
6.55 KB
Del
OK
debuild_pkgbuild.py
34.68 KB
Del
OK
defaults.py
6.55 KB
Del
OK
devinfo.py
9.07 KB
Del
OK
devmap.py
627 B
Del
OK
dig.py
8.75 KB
Del
OK
disk.py
30.82 KB
Del
OK
djangomod.py
7.53 KB
Del
OK
dnsmasq.py
5.71 KB
Del
OK
dnsutil.py
11.51 KB
Del
OK
dockercompose.py
32.62 KB
Del
OK
dockermod.py
224.85 KB
Del
OK
dpkg_lowpkg.py
12.94 KB
Del
OK
drac.py
10.97 KB
Del
OK
dracr.py
38.53 KB
Del
OK
drbd.py
7.19 KB
Del
OK
dummyproxy_pkg.py
2.46 KB
Del
OK
dummyproxy_service.py
2.91 KB
Del
OK
ebuildpkg.py
38.74 KB
Del
OK
eix.py
1.58 KB
Del
OK
elasticsearch.py
51.44 KB
Del
OK
environ.py
8.96 KB
Del
OK
eselect.py
4.99 KB
Del
OK
esxcluster.py
1.66 KB
Del
OK
esxdatacenter.py
1.68 KB
Del
OK
esxi.py
2.79 KB
Del
OK
esxvm.py
1.63 KB
Del
OK
etcd_mod.py
8.56 KB
Del
OK
ethtool.py
11.12 KB
Del
OK
event.py
7.67 KB
Del
OK
extfs.py
8.78 KB
Del
OK
file.py
232.18 KB
Del
OK
firewalld.py
20.51 KB
Del
OK
freebsd_sysctl.py
4.99 KB
Del
OK
freebsd_update.py
6.19 KB
Del
OK
freebsdjail.py
7.16 KB
Del
OK
freebsdkmod.py
6.17 KB
Del
OK
freebsdpkg.py
17.04 KB
Del
OK
freebsdports.py
13.13 KB
Del
OK
freebsdservice.py
12.53 KB
Del
OK
freezer.py
10.2 KB
Del
OK
gcp_addon.py
4.07 KB
Del
OK
gem.py
10.6 KB
Del
OK
genesis.py
21.75 KB
Del
OK
gentoo_service.py
9.18 KB
Del
OK
gentoolkitmod.py
8.39 KB
Del
OK
git.py
172.01 KB
Del
OK
github.py
53.19 KB
Del
OK
glanceng.py
4.69 KB
Del
OK
glassfish.py
19.49 KB
Del
OK
glusterfs.py
19.55 KB
Del
OK
gnomedesktop.py
6.85 KB
Del
OK
google_chat.py
1.52 KB
Del
OK
gpg.py
39.09 KB
Del
OK
grafana4.py
30.27 KB
Del
OK
grains.py
21.81 KB
Del
OK
groupadd.py
11.87 KB
Del
OK
grub_legacy.py
3.08 KB
Del
OK
guestfs.py
2.37 KB
Del
OK
hadoop.py
3.76 KB
Del
OK
haproxyconn.py
10.17 KB
Del
OK
hashutil.py
6.77 KB
Del
OK
heat.py
25.25 KB
Del
OK
helm.py
39.27 KB
Del
OK
hg.py
7.16 KB
Del
OK
highstate_doc.py
22.76 KB
Del
OK
hosts.py
10.47 KB
Del
OK
http.py
3.76 KB
Del
OK
icinga2.py
4.46 KB
Del
OK
idem.py
1.75 KB
Del
OK
ifttt.py
2.28 KB
Del
OK
ilo.py
15.98 KB
Del
OK
incron.py
7.68 KB
Del
OK
influxdb08mod.py
15.07 KB
Del
OK
influxdbmod.py
16.13 KB
Del
OK
infoblox.py
17.53 KB
Del
OK
ini_manage.py
14.63 KB
Del
OK
inspectlib
-
Del
OK
inspector.py
8.19 KB
Del
OK
introspect.py
4.02 KB
Del
OK
iosconfig.py
14.78 KB
Del
OK
ipmi.py
25.47 KB
Del
OK
ipset.py
17.97 KB
Del
OK
iptables.py
57.44 KB
Del
OK
iwtools.py
3.99 KB
Del
OK
jboss7.py
20.51 KB
Del
OK
jboss7_cli.py
15.23 KB
Del
OK
jenkinsmod.py
11.9 KB
Del
OK
jinja.py
2.66 KB
Del
OK
jira_mod.py
7.07 KB
Del
OK
junos.py
73.96 KB
Del
OK
k8s.py
24.87 KB
Del
OK
kapacitor.py
5.37 KB
Del
OK
kerberos.py
5.42 KB
Del
OK
kernelpkg_linux_apt.py
6.71 KB
Del
OK
kernelpkg_linux_yum.py
7.26 KB
Del
OK
key.py
1007 B
Del
OK
keyboard.py
2.64 KB
Del
OK
keystone.py
43.14 KB
Del
OK
keystoneng.py
21.82 KB
Del
OK
keystore.py
7.18 KB
Del
OK
kmod.py
7.65 KB
Del
OK
kubeadm.py
34.64 KB
Del
OK
kubernetesmod.py
46.77 KB
Del
OK
launchctl_service.py
9.69 KB
Del
OK
layman.py
4.22 KB
Del
OK
ldap3.py
18.81 KB
Del
OK
ldapmod.py
5.9 KB
Del
OK
libcloud_compute.py
23.48 KB
Del
OK
libcloud_dns.py
9.73 KB
Del
OK
libcloud_loadbalancer.py
13.14 KB
Del
OK
libcloud_storage.py
12.16 KB
Del
OK
linux_acl.py
7.7 KB
Del
OK
linux_ip.py
5.55 KB
Del
OK
linux_lvm.py
17.86 KB
Del
OK
linux_service.py
4.64 KB
Del
OK
linux_shadow.py
12.96 KB
Del
OK
linux_sysctl.py
7.5 KB
Del
OK
localemod.py
11.84 KB
Del
OK
locate.py
2.58 KB
Del
OK
logadm.py
9.44 KB
Del
OK
logmod.py
1.25 KB
Del
OK
logrotate.py
7.72 KB
Del
OK
lvs.py
11.54 KB
Del
OK
lxc.py
147.27 KB
Del
OK
lxd.py
90.07 KB
Del
OK
mac_assistive.py
11.37 KB
Del
OK
mac_brew_pkg.py
19.91 KB
Del
OK
mac_desktop.py
2.77 KB
Del
OK
mac_group.py
6.62 KB
Del
OK
mac_keychain.py
6.39 KB
Del
OK
mac_pkgutil.py
2.84 KB
Del
OK
mac_portspkg.py
11.36 KB
Del
OK
mac_power.py
13.29 KB
Del
OK
mac_service.py
19.64 KB
Del
OK
mac_shadow.py
14.23 KB
Del
OK
mac_softwareupdate.py
14.52 KB
Del
OK
mac_sysctl.py
5.13 KB
Del
OK
mac_system.py
15.07 KB
Del
OK
mac_timezone.py
8.34 KB
Del
OK
mac_user.py
16.41 KB
Del
OK
mac_xattr.py
6.27 KB
Del
OK
macdefaults.py
2.33 KB
Del
OK
macpackage.py
6.66 KB
Del
OK
makeconf.py
17.31 KB
Del
OK
mandrill.py
6.31 KB
Del
OK
marathon.py
5.36 KB
Del
OK
match.py
13 KB
Del
OK
mattermost.py
3.4 KB
Del
OK
mdadm_raid.py
9.86 KB
Del
OK
mdata.py
3.38 KB
Del
OK
memcached.py
6.13 KB
Del
OK
mine.py
18.84 KB
Del
OK
minion.py
7.68 KB
Del
OK
mod_random.py
7.18 KB
Del
OK
modjk.py
12.48 KB
Del
OK
mongodb.py
29.75 KB
Del
OK
monit.py
5.51 KB
Del
OK
moosefs.py
3.87 KB
Del
OK
mount.py
58.44 KB
Del
OK
mssql.py
14.64 KB
Del
OK
msteams.py
2.11 KB
Del
OK
munin.py
2.4 KB
Del
OK
mysql.py
90.66 KB
Del
OK
nacl.py
9.72 KB
Del
OK
nagios.py
6.53 KB
Del
OK
nagios_rpc.py
5.09 KB
Del
OK
namecheap_domains.py
12.84 KB
Del
OK
namecheap_domains_dns.py
5.93 KB
Del
OK
namecheap_domains_ns.py
4.51 KB
Del
OK
namecheap_ssl.py
25.69 KB
Del
OK
namecheap_users.py
2.4 KB
Del
OK
napalm_bgp.py
9.72 KB
Del
OK
napalm_formula.py
11.33 KB
Del
OK
napalm_mod.py
61.37 KB
Del
OK
napalm_netacl.py
28.59 KB
Del
OK
napalm_network.py
93.22 KB
Del
OK
napalm_ntp.py
10.22 KB
Del
OK
napalm_probes.py
13.25 KB
Del
OK
napalm_route.py
5.09 KB
Del
OK
napalm_snmp.py
7.05 KB
Del
OK
napalm_users.py
6.49 KB
Del
OK
napalm_yang_mod.py
20.28 KB
Del
OK
netaddress.py
1.6 KB
Del
OK
netbox.py
32.22 KB
Del
OK
netbsd_sysctl.py
3.92 KB
Del
OK
netbsdservice.py
6.43 KB
Del
OK
netmiko_mod.py
19.61 KB
Del
OK
netscaler.py
27.02 KB
Del
OK
network.py
63.42 KB
Del
OK
neutron.py
44.92 KB
Del
OK
neutronng.py
15.02 KB
Del
OK
nexus.py
22.95 KB
Del
OK
nfs3.py
3.9 KB
Del
OK
nftables.py
33.58 KB
Del
OK
nginx.py
3.83 KB
Del
OK
nilrt_ip.py
36.18 KB
Del
OK
nix.py
8.03 KB
Del
OK
nova.py
19.6 KB
Del
OK
npm.py
10.4 KB
Del
OK
nspawn.py
41.35 KB
Del
OK
nxos.py
24.65 KB
Del
OK
nxos_api.py
14.72 KB
Del
OK
nxos_upgrade.py
14.74 KB
Del
OK
omapi.py
3.6 KB
Del
OK
openbsd_sysctl.py
3.74 KB
Del
OK
openbsdpkg.py
10.97 KB
Del
OK
openbsdrcctl_service.py
6.33 KB
Del
OK
openbsdservice.py
8.31 KB
Del
OK
openscap.py
2.81 KB
Del
OK
openstack_config.py
3.21 KB
Del
OK
openstack_mng.py
2.71 KB
Del
OK
openvswitch.py
17.19 KB
Del
OK
opkg.py
49.67 KB
Del
OK
opsgenie.py
3.29 KB
Del
OK
oracle.py
5.82 KB
Del
OK
osquery.py
24.93 KB
Del
OK
out.py
2.53 KB
Del
OK
pacmanpkg.py
31.92 KB
Del
OK
pagerduty.py
4.7 KB
Del
OK
pagerduty_util.py
13.48 KB
Del
OK
pam.py
2.01 KB
Del
OK
panos.py
61.05 KB
Del
OK
parallels.py
19.85 KB
Del
OK
parted_partition.py
21.53 KB
Del
OK
pcs.py
14.11 KB
Del
OK
pdbedit.py
10.79 KB
Del
OK
pecl.py
3.79 KB
Del
OK
peeringdb.py
8.39 KB
Del
OK
pf.py
9.51 KB
Del
OK
philips_hue.py
1.55 KB
Del
OK
pillar.py
21.37 KB
Del
OK
pip.py
53.42 KB
Del
OK
pkg_resource.py
12.3 KB
Del
OK
pkgin.py
17.29 KB
Del
OK
pkgng.py
61.07 KB
Del
OK
pkgutil.py
9.85 KB
Del
OK
portage_config.py
22.73 KB
Del
OK
postfix.py
16.24 KB
Del
OK
postgres.py
88.24 KB
Del
OK
poudriere.py
7.85 KB
Del
OK
powerpath.py
2.57 KB
Del
OK
proxy.py
11.49 KB
Del
OK
ps.py
20.89 KB
Del
OK
publish.py
10.25 KB
Del
OK
puppet.py
10.9 KB
Del
OK
purefa.py
33.59 KB
Del
OK
purefb.py
13.69 KB
Del
OK
pushbullet.py
1.88 KB
Del
OK
pushover_notify.py
3.48 KB
Del
OK
pw_group.py
4.62 KB
Del
OK
pw_user.py
12.47 KB
Del
OK
pyenv.py
6.93 KB
Del
OK
qemu_img.py
1.53 KB
Del
OK
qemu_nbd.py
3.28 KB
Del
OK
quota.py
6.43 KB
Del
OK
rabbitmq.py
38.4 KB
Del
OK
rallydev.py
6.09 KB
Del
OK
random_org.py
23.76 KB
Del
OK
rbac_solaris.py
16.05 KB
Del
OK
rbenv.py
10.75 KB
Del
OK
rdp.py
6.08 KB
Del
OK
rebootmgr.py
7.68 KB
Del
OK
redismod.py
16.36 KB
Del
OK
reg.py
16.36 KB
Del
OK
rest_pkg.py
2.26 KB
Del
OK
rest_sample_utils.py
558 B
Del
OK
rest_service.py
3.63 KB
Del
OK
restartcheck.py
24.1 KB
Del
OK
restconf.py
3.15 KB
Del
OK
ret.py
1.27 KB
Del
OK
rh_ip.py
38.55 KB
Del
OK
rh_service.py
16.61 KB
Del
OK
riak.py
5.19 KB
Del
OK
rpm_lowpkg.py
27.67 KB
Del
OK
rpmbuild_pkgbuild.py
24.53 KB
Del
OK
rsync.py
8.04 KB
Del
OK
runit.py
17.17 KB
Del
OK
rvm.py
11.1 KB
Del
OK
s3.py
9.93 KB
Del
OK
s6.py
3.62 KB
Del
OK
salt_proxy.py
4.48 KB
Del
OK
salt_version.py
4.58 KB
Del
OK
saltcheck.py
46.66 KB
Del
OK
saltcloudmod.py
954 B
Del
OK
saltutil.py
57.49 KB
Del
OK
schedule.py
50.81 KB
Del
OK
scp_mod.py
6.22 KB
Del
OK
scsi.py
2.66 KB
Del
OK
sdb.py
2.48 KB
Del
OK
seed.py
8.87 KB
Del
OK
selinux.py
24.2 KB
Del
OK
sensehat.py
7.79 KB
Del
OK
sensors.py
1.3 KB
Del
OK
serverdensity_device.py
8.1 KB
Del
OK
servicenow.py
4.36 KB
Del
OK
slack_notify.py
7.83 KB
Del
OK
slackware_service.py
6.84 KB
Del
OK
slsutil.py
19.04 KB
Del
OK
smartos_imgadm.py
12.04 KB
Del
OK
smartos_nictagadm.py
6.46 KB
Del
OK
smartos_virt.py
5.21 KB
Del
OK
smartos_vmadm.py
26.2 KB
Del
OK
smbios.py
10.05 KB
Del
OK
smf_service.py
8.52 KB
Del
OK
smtp.py
5.41 KB
Del
OK
snapper.py
27.14 KB
Del
OK
solaris_fmadm.py
11.2 KB
Del
OK
solaris_group.py
2.8 KB
Del
OK
solaris_shadow.py
7.98 KB
Del
OK
solaris_system.py
3.72 KB
Del
OK
solaris_user.py
11.06 KB
Del
OK
solarisipspkg.py
18.68 KB
Del
OK
solarispkg.py
15.4 KB
Del
OK
solr.py
45.54 KB
Del
OK
solrcloud.py
14.63 KB
Del
OK
splunk.py
8.14 KB
Del
OK
splunk_search.py
8.76 KB
Del
OK
sqlite3.py
2.54 KB
Del
OK
ssh.py
43.89 KB
Del
OK
ssh_pkg.py
1.08 KB
Del
OK
ssh_service.py
3.39 KB
Del
OK
state.py
82.34 KB
Del
OK
status.py
57.79 KB
Del
OK
statuspage.py
14.67 KB
Del
OK
supervisord.py
11.15 KB
Del
OK
suse_apache.py
2.45 KB
Del
OK
suse_ip.py
35.72 KB
Del
OK
svn.py
10.75 KB
Del
OK
swarm.py
13.5 KB
Del
OK
swift.py
5.53 KB
Del
OK
sysbench.py
6.62 KB
Del
OK
sysfs.py
6.61 KB
Del
OK
syslog_ng.py
31.52 KB
Del
OK
sysmod.py
22.59 KB
Del
OK
sysrc.py
3.38 KB
Del
OK
system.py
19.28 KB
Del
OK
system_profiler.py
3.54 KB
Del
OK
systemd_service.py
46.29 KB
Del
OK
telegram.py
3.28 KB
Del
OK
telemetry.py
12.87 KB
Del
OK
temp.py
831 B
Del
OK
test.py
15.4 KB
Del
OK
test_virtual.py
237 B
Del
OK
testinframod.py
9.92 KB
Del
OK
textfsm_mod.py
16.22 KB
Del
OK
timezone.py
19.98 KB
Del
OK
tls.py
58.63 KB
Del
OK
tomcat.py
18.59 KB
Del
OK
trafficserver.py
10.44 KB
Del
OK
transactional_update.py
35.83 KB
Del
OK
travisci.py
2.05 KB
Del
OK
tuned.py
2.34 KB
Del
OK
twilio_notify.py
2.95 KB
Del
OK
udev.py
3.72 KB
Del
OK
upstart_service.py
16.92 KB
Del
OK
uptime.py
3.23 KB
Del
OK
useradd.py
22.63 KB
Del
OK
uwsgi.py
996 B
Del
OK
vagrant.py
20.4 KB
Del
OK
varnish.py
3.08 KB
Del
OK
vault.py
15.61 KB
Del
OK
vbox_guest.py
10.55 KB
Del
OK
vboxmanage.py
14.71 KB
Del
OK
vcenter.py
1.61 KB
Del
OK
victorops.py
6.54 KB
Del
OK
virt.py
287.71 KB
Del
OK
virtualenv_mod.py
15.09 KB
Del
OK
vmctl.py
9.56 KB
Del
OK
vsphere.py
380.41 KB
Del
OK
webutil.py
3.66 KB
Del
OK
win_auditpol.py
4.74 KB
Del
OK
win_autoruns.py
2.29 KB
Del
OK
win_certutil.py
4.55 KB
Del
OK
win_dacl.py
32.27 KB
Del
OK
win_disk.py
1.8 KB
Del
OK
win_dism.py
20.7 KB
Del
OK
win_dns_client.py
4.19 KB
Del
OK
win_dsc.py
27.54 KB
Del
OK
win_event.py
22.32 KB
Del
OK
win_file.py
64.39 KB
Del
OK
win_firewall.py
20.15 KB
Del
OK
win_groupadd.py
11.27 KB
Del
OK
win_iis.py
68.78 KB
Del
OK
win_ip.py
11.43 KB
Del
OK
win_lgpo.py
491.76 KB
Del
OK
win_lgpo_reg.py
17.9 KB
Del
OK
win_license.py
2.72 KB
Del
OK
win_network.py
13.9 KB
Del
OK
win_ntp.py
1.8 KB
Del
OK
win_path.py
11.12 KB
Del
OK
win_pkg.py
86.43 KB
Del
OK
win_pki.py
15.8 KB
Del
OK
win_powercfg.py
9.85 KB
Del
OK
win_psget.py
8.97 KB
Del
OK
win_servermanager.py
14.21 KB
Del
OK
win_service.py
32.96 KB
Del
OK
win_shadow.py
3.03 KB
Del
OK
win_shortcut.py
16.49 KB
Del
OK
win_smtp_server.py
17.67 KB
Del
OK
win_snmp.py
13.38 KB
Del
OK
win_status.py
16.94 KB
Del
OK
win_system.py
40.61 KB
Del
OK
win_task.py
79.17 KB
Del
OK
win_timezone.py
13.3 KB
Del
OK
win_useradd.py
27.39 KB
Del
OK
win_wua.py
38.29 KB
Del
OK
win_wusa.py
5.88 KB
Del
OK
winrepo.py
6.09 KB
Del
OK
wordpress.py
4.71 KB
Del
OK
x509.py
63.1 KB
Del
OK
x509_v2.py
74.15 KB
Del
OK
xapi_virt.py
24.07 KB
Del
OK
xbpspkg.py
15.84 KB
Del
OK
xfs.py
15.35 KB
Del
OK
xml.py
2.14 KB
Del
OK
xmpp.py
5.28 KB
Del
OK
yaml.py
1.94 KB
Del
OK
yumpkg.py
116.5 KB
Del
OK
zabbix.py
97.55 KB
Del
OK
zcbuildout.py
28.16 KB
Del
OK
zenoss.py
5.64 KB
Del
OK
zfs.py
34.44 KB
Del
OK
zk_concurrency.py
11.16 KB
Del
OK
znc.py
2.26 KB
Del
OK
zoneadm.py
15.05 KB
Del
OK
zonecfg.py
21.85 KB
Del
OK
zookeeper.py
14.72 KB
Del
OK
zpool.py
44.02 KB
Del
OK
zypperpkg.py
94.87 KB
Del
OK
Edit: napalm_network.py
""" NAPALM Network ============== Basic methods for interaction with the network device through the virtual proxy 'napalm'. :codeauthor: Mircea Ulinic <ping@mirceaulinic.net> & Jerome Fleury <jf@cloudflare.com> :maturity: new :depends: napalm :platform: unix Dependencies ------------ - :mod:`napalm proxy minion <salt.proxy.napalm>` .. versionadded:: 2016.11.0 .. versionchanged:: 2017.7.0 """ import datetime import logging import time import salt.utils.files import salt.utils.napalm import salt.utils.templates import salt.utils.versions log = logging.getLogger(__name__) try: import jxmlease # pylint: disable=unused-import HAS_JXMLEASE = True except ImportError: HAS_JXMLEASE = False # ---------------------------------------------------------------------------------------------------------------------- # module properties # ---------------------------------------------------------------------------------------------------------------------- __virtualname__ = "net" __proxyenabled__ = ["*"] __virtual_aliases__ = ("napalm_net",) # uses NAPALM-based proxy to interact with network devices # ---------------------------------------------------------------------------------------------------------------------- # property functions # ---------------------------------------------------------------------------------------------------------------------- def __virtual__(): """ NAPALM library must be installed for this module to work and run in a (proxy) minion. """ return salt.utils.napalm.virtual(__opts__, __virtualname__, __file__) # ---------------------------------------------------------------------------------------------------------------------- # helper functions -- will not be exported # ---------------------------------------------------------------------------------------------------------------------- def _filter_list(input_list, search_key, search_value): """ Filters a list of dictionary by a set of key-value pair. :param input_list: is a list of dictionaries :param search_key: is the key we are looking for :param search_value: is the value we are looking for the key specified in search_key :return: filered list of dictionaries """ output_list = list() for dictionary in input_list: if dictionary.get(search_key) == search_value: output_list.append(dictionary) return output_list def _filter_dict(input_dict, search_key, search_value): """ Filters a dictionary of dictionaries by a key-value pair. :param input_dict: is a dictionary whose values are lists of dictionaries :param search_key: is the key in the leaf dictionaries :param search_values: is the value in the leaf dictionaries :return: filtered dictionary """ output_dict = dict() for key, key_list in input_dict.items(): key_list_filtered = _filter_list(key_list, search_key, search_value) if key_list_filtered: output_dict[key] = key_list_filtered return output_dict def _safe_commit_config(loaded_result, napalm_device): _commit = commit( inherit_napalm_device=napalm_device ) # calls the function commit, defined below if not _commit.get("result", False): # if unable to commit loaded_result["comment"] += ( _commit["comment"] if _commit.get("comment") else "Unable to commit." ) loaded_result["result"] = False # unable to commit, something went wrong discarded = _safe_dicard_config(loaded_result, napalm_device) if not discarded["result"]: return loaded_result return _commit def _safe_dicard_config(loaded_result, napalm_device): log.debug("Discarding the config") log.debug(loaded_result) _discarded = discard_config(inherit_napalm_device=napalm_device) if not _discarded.get("result", False): loaded_result["comment"] += ( _discarded["comment"] if _discarded.get("comment") else "Unable to discard config." ) loaded_result["result"] = False # make sure it notifies # that something went wrong _explicit_close(napalm_device) __context__["retcode"] = 1 return loaded_result return _discarded def _explicit_close(napalm_device): """ Will explicily close the config session with the network device, when running in a now-always-alive proxy minion or regular minion. This helper must be used in configuration-related functions, as the session is preserved and not closed before making any changes. """ if salt.utils.napalm.not_always_alive(__opts__): # force closing the configuration session # when running in a non-always-alive proxy # or regular minion try: napalm_device["DRIVER"].close() except Exception as err: # pylint: disable=broad-except log.error("Unable to close the temp connection with the device:") log.error(err) log.error("Please report.") def _config_logic( napalm_device, loaded_result, test=False, debug=False, replace=False, commit_config=True, loaded_config=None, commit_in=None, commit_at=None, revert_in=None, revert_at=None, commit_jid=None, **kwargs ): """ Builds the config logic for `load_config` and `load_template` functions. """ # As the Salt logic is built around independent events # when it comes to configuration changes in the # candidate DB on the network devices, we need to # make sure we're using the same session. # Hence, we need to pass the same object around. # the napalm_device object is inherited from # the load_config or load_template functions # and forwarded to compare, discard, commit etc. # then the decorator will make sure that # if not proxy (when the connection is always alive) # and the `inherit_napalm_device` is set, # `napalm_device` will be overridden. # See `salt.utils.napalm.proxy_napalm_wrap` decorator. current_jid = kwargs.get("__pub_jid") if not current_jid: current_jid = "{:%Y%m%d%H%M%S%f}".format(datetime.datetime.now()) loaded_result["already_configured"] = False loaded_result["loaded_config"] = "" if debug: loaded_result["loaded_config"] = loaded_config _compare = compare_config(inherit_napalm_device=napalm_device) if _compare.get("result", False): loaded_result["diff"] = _compare.get("out") loaded_result.pop("out", "") # not needed else: loaded_result["diff"] = None loaded_result["result"] = False loaded_result["comment"] = _compare.get("comment") __context__["retcode"] = 1 return loaded_result _loaded_res = loaded_result.get("result", False) if not _loaded_res or test: # if unable to load the config (errors / warnings) # or in testing mode, # will discard the config if loaded_result["comment"]: loaded_result["comment"] += "\n" if not loaded_result.get("diff", ""): loaded_result["already_configured"] = True discarded = _safe_dicard_config(loaded_result, napalm_device) if not discarded["result"]: return loaded_result loaded_result["comment"] += "Configuration discarded." # loaded_result['result'] = False not necessary # as the result can be true when test=True _explicit_close(napalm_device) if not loaded_result["result"]: __context__["retcode"] = 1 return loaded_result if not test and commit_config: # if not in testing mode and trying to commit if commit_jid: log.info("Committing the JID: %s", str(commit_jid)) removed = cancel_commit(commit_jid) log.debug("Cleaned up the commit from the schedule") log.debug(removed["comment"]) if loaded_result.get("diff", ""): # if not testing mode # and also the user wants to commit (default) # and there are changes to commit if commit_in or commit_at: commit_time = __utils__["timeutil.get_time_at"]( time_in=commit_in, time_at=commit_in ) # schedule job scheduled_job_name = "__napalm_commit_{}".format(current_jid) temp_file = salt.utils.files.mkstemp() with salt.utils.files.fopen(temp_file, "w") as fp_: fp_.write(loaded_config) scheduled = __salt__["schedule.add"]( scheduled_job_name, function="net.load_config", job_kwargs={ "filename": temp_file, "commit_jid": current_jid, "replace": replace, }, once=commit_time, ) log.debug("Scheduling job") log.debug(scheduled) saved = __salt__["schedule.save"]() # ensure the schedule is # persistent cross Minion restart discarded = _safe_dicard_config(loaded_result, napalm_device) # discard the changes if not discarded["result"]: discarded["comment"] += ( "Scheduled the job to be executed at {schedule_ts}, " "but was unable to discard the config: \n".format( schedule_ts=commit_time ) ) return discarded loaded_result["comment"] = ( "Changes discarded for now, and scheduled commit at:" " {schedule_ts}.\nThe commit ID is: {current_jid}.\nTo discard this" " commit, you can execute: \n\nsalt {min_id} net.cancel_commit" " {current_jid}".format( schedule_ts=commit_time, min_id=__opts__["id"], current_jid=current_jid, ) ) loaded_result["commit_id"] = current_jid return loaded_result log.debug("About to commit:") log.debug(loaded_result["diff"]) if revert_in or revert_at: revert_time = __utils__["timeutil.get_time_at"]( time_in=revert_in, time_at=revert_at ) if __grains__["os"] == "junos": if not HAS_JXMLEASE: loaded_result["comment"] = ( "This feature requires the library jxmlease to be" " installed.\nTo install, please execute: ``pip install" " jxmlease``." ) loaded_result["result"] = False return loaded_result timestamp_at = __utils__["timeutil.get_timestamp_at"]( time_in=revert_in, time_at=revert_at ) minutes = int((timestamp_at - time.time()) / 60) _comm = __salt__["napalm.junos_commit"](confirm=minutes) if not _comm["out"]: # If unable to commit confirm, should try to bail out loaded_result[ "comment" ] = "Unable to commit confirm: {}".format(_comm["message"]) loaded_result["result"] = False # But before exiting, we must gracefully discard the config discarded = _safe_dicard_config(loaded_result, napalm_device) if not discarded["result"]: return loaded_result else: temp_file = salt.utils.files.mkstemp() running_config = __salt__["net.config"](source="running")["out"][ "running" ] with salt.utils.files.fopen(temp_file, "w") as fp_: fp_.write(running_config) committed = _safe_commit_config(loaded_result, napalm_device) if not committed["result"]: # If unable to commit, dicard the config (which is # already done by the _safe_commit_config function), and # return with the command and other details. return loaded_result scheduled_job_name = "__napalm_commit_{}".format(current_jid) scheduled = __salt__["schedule.add"]( scheduled_job_name, function="net.load_config", job_kwargs={ "filename": temp_file, "commit_jid": current_jid, "replace": True, }, once=revert_time, ) log.debug("Scheduling commit confirmed") log.debug(scheduled) saved = __salt__["schedule.save"]() loaded_result["comment"] = ( "The commit ID is: {current_jid}.\nThis commit will be reverted at:" " {schedule_ts}, unless confirmed.\nTo confirm the commit and avoid" " reverting, you can execute:\n\nsalt {min_id} net.confirm_commit" " {current_jid}".format( schedule_ts=revert_time, min_id=__opts__["id"], current_jid=current_jid, ) ) loaded_result["commit_id"] = current_jid return loaded_result committed = _safe_commit_config(loaded_result, napalm_device) if not committed["result"]: return loaded_result else: # would like to commit, but there's no change # need to call discard_config() to release the config DB discarded = _safe_dicard_config(loaded_result, napalm_device) if not discarded["result"]: return loaded_result loaded_result["already_configured"] = True loaded_result["comment"] = "Already configured." _explicit_close(napalm_device) if not loaded_result["result"]: __context__["retcode"] = 1 return loaded_result # ---------------------------------------------------------------------------------------------------------------------- # callable functions # ---------------------------------------------------------------------------------------------------------------------- @salt.utils.napalm.proxy_napalm_wrap def connected(**kwargs): # pylint: disable=unused-argument """ Specifies if the connection to the device succeeded. CLI Example: .. code-block:: bash salt '*' net.connected """ return {"out": napalm_device.get("UP", False)} # pylint: disable=undefined-variable @salt.utils.napalm.proxy_napalm_wrap def facts(**kwargs): # pylint: disable=unused-argument """ Returns characteristics of the network device. :return: a dictionary with the following keys: * uptime - Uptime of the device in seconds. * vendor - Manufacturer of the device. * model - Device model. * hostname - Hostname of the device * fqdn - Fqdn of the device * os_version - String with the OS version running on the device. * serial_number - Serial number of the device * interface_list - List of the interfaces of the device CLI Example: .. code-block:: bash salt '*' net.facts Example output: .. code-block:: python { 'os_version': '13.3R6.5', 'uptime': 10117140, 'interface_list': [ 'lc-0/0/0', 'pfe-0/0/0', 'pfh-0/0/0', 'xe-0/0/0', 'xe-0/0/1', 'xe-0/0/2', 'xe-0/0/3', 'gr-0/0/10', 'ip-0/0/10' ], 'vendor': 'Juniper', 'serial_number': 'JN131356FBFA', 'model': 'MX480', 'hostname': 're0.edge05.syd01', 'fqdn': 're0.edge05.syd01' } """ return salt.utils.napalm.call( napalm_device, "get_facts", **{} # pylint: disable=undefined-variable ) @salt.utils.napalm.proxy_napalm_wrap def environment(**kwargs): # pylint: disable=unused-argument """ Returns the environment of the device. CLI Example: .. code-block:: bash salt '*' net.environment Example output: .. code-block:: python { 'fans': { 'Bottom Rear Fan': { 'status': True }, 'Bottom Middle Fan': { 'status': True }, 'Top Middle Fan': { 'status': True }, 'Bottom Front Fan': { 'status': True }, 'Top Front Fan': { 'status': True }, 'Top Rear Fan': { 'status': True } }, 'memory': { 'available_ram': 16349, 'used_ram': 4934 }, 'temperature': { 'FPC 0 Exhaust A': { 'is_alert': False, 'temperature': 35.0, 'is_critical': False } }, 'cpu': { '1': { '%usage': 19.0 }, '0': { '%usage': 35.0 } } } """ return salt.utils.napalm.call( napalm_device, "get_environment", **{} # pylint: disable=undefined-variable ) @salt.utils.napalm.proxy_napalm_wrap def cli(*commands, **kwargs): # pylint: disable=unused-argument """ Returns a dictionary with the raw output of all commands passed as arguments. commands List of commands to be executed on the device. textfsm_parse: ``False`` Try parsing the outputs using the TextFSM templates. .. versionadded:: 2018.3.0 .. note:: This option can be also specified in the minion configuration file or pillar as ``napalm_cli_textfsm_parse``. textfsm_path The path where the TextFSM templates can be found. This option implies the usage of the TextFSM index file. ``textfsm_path`` can be either absolute path on the server, either specified using the following URL mschemes: ``file://``, ``salt://``, ``http://``, ``https://``, ``ftp://``, ``s3://``, ``swift://``. .. versionadded:: 2018.3.0 .. note:: This needs to be a directory with a flat structure, having an index file (whose name can be specified using the ``index_file`` option) and a number of TextFSM templates. .. note:: This option can be also specified in the minion configuration file or pillar as ``textfsm_path``. textfsm_template The path to a certain the TextFSM template. This can be specified using the absolute path to the file, or using one of the following URL schemes: - ``salt://``, to fetch the template from the Salt fileserver. - ``http://`` or ``https://`` - ``ftp://`` - ``s3://`` - ``swift://`` .. versionadded:: 2018.3.0 textfsm_template_dict A dictionary with the mapping between a command and the corresponding TextFSM path to use to extract the data. The TextFSM paths can be specified as in ``textfsm_template``. .. versionadded:: 2018.3.0 .. note:: This option can be also specified in the minion configuration file or pillar as ``napalm_cli_textfsm_template_dict``. platform_grain_name: ``os`` The name of the grain used to identify the platform name in the TextFSM index file. Default: ``os``. .. versionadded:: 2018.3.0 .. note:: This option can be also specified in the minion configuration file or pillar as ``textfsm_platform_grain``. platform_column_name: ``Platform`` The column name used to identify the platform, exactly as specified in the TextFSM index file. Default: ``Platform``. .. versionadded:: 2018.3.0 .. note:: This is field is case sensitive, make sure to assign the correct value to this option, exactly as defined in the index file. .. note:: This option can be also specified in the minion configuration file or pillar as ``textfsm_platform_column_name``. index_file: ``index`` The name of the TextFSM index file, under the ``textfsm_path``. Default: ``index``. .. versionadded:: 2018.3.0 .. note:: This option can be also specified in the minion configuration file or pillar as ``textfsm_index_file``. saltenv: ``base`` Salt fileserver environment from which to retrieve the file. Ignored if ``textfsm_path`` is not a ``salt://`` URL. .. versionadded:: 2018.3.0 include_empty: ``False`` Include empty files under the ``textfsm_path``. .. versionadded:: 2018.3.0 include_pat Glob or regex to narrow down the files cached from the given path. If matching with a regex, the regex must be prefixed with ``E@``, otherwise the expression will be interpreted as a glob. .. versionadded:: 2018.3.0 exclude_pat Glob or regex to exclude certain files from being cached from the given path. If matching with a regex, the regex must be prefixed with ``E@``, otherwise the expression will be interpreted as a glob. .. versionadded:: 2018.3.0 .. note:: If used with ``include_pat``, files matching this pattern will be excluded from the subset of files defined by ``include_pat``. CLI Example: .. code-block:: bash salt '*' net.cli "show version" "show chassis fan" CLI Example with TextFSM template: .. code-block:: bash salt '*' net.cli textfsm_parse=True textfsm_path=salt://textfsm/ Example output: .. code-block:: python { 'show version and haiku': 'Hostname: re0.edge01.arn01 Model: mx480 Junos: 13.3R6.5 Help me, Obi-Wan I just saw Episode Two You're my only hope ', 'show chassis fan' : 'Item Status RPM Measurement Top Rear Fan OK 3840 Spinning at intermediate-speed Bottom Rear Fan OK 3840 Spinning at intermediate-speed Top Middle Fan OK 3900 Spinning at intermediate-speed Bottom Middle Fan OK 3840 Spinning at intermediate-speed Top Front Fan OK 3810 Spinning at intermediate-speed Bottom Front Fan OK 3840 Spinning at intermediate-speed ' } Example output with TextFSM parsing: .. code-block:: json { "comment": "", "result": true, "out": { "sh ver": [ { "kernel": "9.1S3.5", "documentation": "9.1S3.5", "boot": "9.1S3.5", "crypto": "9.1S3.5", "chassis": "", "routing": "9.1S3.5", "base": "9.1S3.5", "model": "mx960" } ] } } """ raw_cli_outputs = salt.utils.napalm.call( napalm_device, # pylint: disable=undefined-variable "cli", **{"commands": list(commands)} ) # thus we can display the output as is # in case of errors, they'll be caught in the proxy if not raw_cli_outputs["result"]: # Error -> dispaly the output as-is. return raw_cli_outputs textfsm_parse = ( kwargs.get("textfsm_parse") or __opts__.get("napalm_cli_textfsm_parse") or __pillar__.get("napalm_cli_textfsm_parse", False) ) if not textfsm_parse: # No TextFSM parsing required, return raw commands. log.debug("No TextFSM parsing requested.") return raw_cli_outputs if "textfsm.extract" not in __salt__ or "textfsm.index" not in __salt__: raw_cli_outputs["comment"] += "Unable to process: is TextFSM installed?" log.error(raw_cli_outputs["comment"]) return raw_cli_outputs textfsm_template = kwargs.get("textfsm_template") log.debug("textfsm_template: %s", textfsm_template) textfsm_path = ( kwargs.get("textfsm_path") or __opts__.get("textfsm_path") or __pillar__.get("textfsm_path") ) log.debug("textfsm_path: %s", textfsm_path) textfsm_template_dict = ( kwargs.get("textfsm_template_dict") or __opts__.get("napalm_cli_textfsm_template_dict") or __pillar__.get("napalm_cli_textfsm_template_dict", {}) ) log.debug("TextFSM command-template mapping: %s", textfsm_template_dict) index_file = ( kwargs.get("index_file") or __opts__.get("textfsm_index_file") or __pillar__.get("textfsm_index_file") ) log.debug("index_file: %s", index_file) platform_grain_name = ( kwargs.get("platform_grain_name") or __opts__.get("textfsm_platform_grain") or __pillar__.get("textfsm_platform_grain", "os") ) log.debug("platform_grain_name: %s", platform_grain_name) platform_column_name = ( kwargs.get("platform_column_name") or __opts__.get("textfsm_platform_column_name") or __pillar__.get("textfsm_platform_column_name", "Platform") ) log.debug("platform_column_name: %s", platform_column_name) saltenv = kwargs.get("saltenv", "base") include_empty = kwargs.get("include_empty", False) include_pat = kwargs.get("include_pat") exclude_pat = kwargs.get("exclude_pat") processed_cli_outputs = { "comment": raw_cli_outputs.get("comment", ""), "result": raw_cli_outputs["result"], "out": {}, } log.debug("Starting to analyse the raw outputs") for command in list(commands): command_output = raw_cli_outputs["out"][command] log.debug("Output from command: %s", command) log.debug(command_output) processed_command_output = None if textfsm_path: log.debug("Using the templates under %s", textfsm_path) processed_cli_output = __salt__["textfsm.index"]( command, platform_grain_name=platform_grain_name, platform_column_name=platform_column_name, output=command_output.strip(), textfsm_path=textfsm_path, saltenv=saltenv, include_empty=include_empty, include_pat=include_pat, exclude_pat=exclude_pat, ) log.debug("Processed CLI output:") log.debug(processed_cli_output) if not processed_cli_output["result"]: log.debug("Apparently this did not work, returning the raw output") processed_command_output = command_output processed_cli_outputs[ "comment" ] += "\nUnable to process the output from {}: {}.".format( command, processed_cli_output["comment"] ) log.error(processed_cli_outputs["comment"]) elif processed_cli_output["out"]: log.debug("All good, %s has a nice output!", command) processed_command_output = processed_cli_output["out"] else: comment = """\nProcessing "{}" didn't fail, but didn't return anything either. Dumping raw.""".format( command ) processed_cli_outputs["comment"] += comment log.error(comment) processed_command_output = command_output elif textfsm_template or command in textfsm_template_dict: if command in textfsm_template_dict: textfsm_template = textfsm_template_dict[command] log.debug("Using %s to process the command: %s", textfsm_template, command) processed_cli_output = __salt__["textfsm.extract"]( textfsm_template, raw_text=command_output, saltenv=saltenv ) log.debug("Processed CLI output:") log.debug(processed_cli_output) if not processed_cli_output["result"]: log.debug("Apparently this did not work, returning the raw output") processed_command_output = command_output processed_cli_outputs[ "comment" ] += "\nUnable to process the output from {}: {}".format( command, processed_cli_output["comment"] ) log.error(processed_cli_outputs["comment"]) elif processed_cli_output["out"]: log.debug("All good, %s has a nice output!", command) processed_command_output = processed_cli_output["out"] else: log.debug( "Processing %s did not fail, but did not return" " anything either. Dumping raw.", command, ) processed_command_output = command_output else: log.error("No TextFSM template specified, or no TextFSM path defined") processed_command_output = command_output processed_cli_outputs[ "comment" ] += "\nUnable to process the output from {}.".format(command) processed_cli_outputs["out"][command] = processed_command_output processed_cli_outputs["comment"] = processed_cli_outputs["comment"].strip() return processed_cli_outputs @salt.utils.napalm.proxy_napalm_wrap def traceroute( destination, source=None, ttl=None, timeout=None, vrf=None, **kwargs ): # pylint: disable=unused-argument """ Calls the method traceroute from the NAPALM driver object and returns a dictionary with the result of the traceroute command executed on the device. destination Hostname or address of remote host source Source address to use in outgoing traceroute packets ttl IP maximum time-to-live value (or IPv6 maximum hop-limit value) timeout Number of seconds to wait for response (seconds) vrf VRF (routing instance) for traceroute attempt .. versionadded:: 2016.11.4 CLI Example: .. code-block:: bash salt '*' net.traceroute 8.8.8.8 salt '*' net.traceroute 8.8.8.8 source=127.0.0.1 ttl=5 timeout=1 """ return salt.utils.napalm.call( napalm_device, # pylint: disable=undefined-variable "traceroute", **{ "destination": destination, "source": source, "ttl": ttl, "timeout": timeout, "vrf": vrf, } ) @salt.utils.napalm.proxy_napalm_wrap def ping( destination, source=None, ttl=None, timeout=None, size=None, count=None, vrf=None, **kwargs ): # pylint: disable=unused-argument """ Executes a ping on the network device and returns a dictionary as a result. destination Hostname or IP address of remote host source Source address of echo request ttl IP time-to-live value (IPv6 hop-limit value) (1..255 hops) timeout Maximum wait time after sending final packet (seconds) size Size of request packets (0..65468 bytes) count Number of ping requests to send (1..2000000000 packets) vrf VRF (routing instance) for ping attempt .. versionadded:: 2016.11.4 CLI Example: .. code-block:: bash salt '*' net.ping 8.8.8.8 salt '*' net.ping 8.8.8.8 ttl=3 size=65468 salt '*' net.ping 8.8.8.8 source=127.0.0.1 timeout=1 count=100 """ return salt.utils.napalm.call( napalm_device, # pylint: disable=undefined-variable "ping", **{ "destination": destination, "source": source, "ttl": ttl, "timeout": timeout, "size": size, "count": count, "vrf": vrf, } ) @salt.utils.napalm.proxy_napalm_wrap def arp( interface="", ipaddr="", macaddr="", **kwargs ): # pylint: disable=unused-argument """ NAPALM returns a list of dictionaries with details of the ARP entries. :param interface: interface name to filter on :param ipaddr: IP address to filter on :param macaddr: MAC address to filter on :return: List of the entries in the ARP table CLI Example: .. code-block:: bash salt '*' net.arp salt '*' net.arp macaddr='5c:5e:ab:da:3c:f0' Example output: .. code-block:: python [ { 'interface' : 'MgmtEth0/RSP0/CPU0/0', 'mac' : '5c:5e:ab:da:3c:f0', 'ip' : '172.17.17.1', 'age' : 1454496274.84 }, { 'interface': 'MgmtEth0/RSP0/CPU0/0', 'mac' : '66:0e:94:96:e0:ff', 'ip' : '172.17.17.2', 'age' : 1435641582.49 } ] """ proxy_output = salt.utils.napalm.call( napalm_device, "get_arp_table", **{} # pylint: disable=undefined-variable ) if not proxy_output.get("result"): return proxy_output arp_table = proxy_output.get("out") if interface: arp_table = _filter_list(arp_table, "interface", interface) if ipaddr: arp_table = _filter_list(arp_table, "ip", ipaddr) if macaddr: arp_table = _filter_list(arp_table, "mac", macaddr) proxy_output.update({"out": arp_table}) return proxy_output @salt.utils.napalm.proxy_napalm_wrap def ipaddrs(**kwargs): # pylint: disable=unused-argument """ Returns IP addresses configured on the device. :return: A dictionary with the IPv4 and IPv6 addresses of the interfaces. Returns all configured IP addresses on all interfaces as a dictionary of dictionaries. Keys of the main dictionary represent the name of the interface. Values of the main dictionary represent are dictionaries that may consist of two keys 'ipv4' and 'ipv6' (one, both or none) which are themselvs dictionaries with the IP addresses as keys. CLI Example: .. code-block:: bash salt '*' net.ipaddrs Example output: .. code-block:: python { 'FastEthernet8': { 'ipv4': { '10.66.43.169': { 'prefix_length': 22 } } }, 'Loopback555': { 'ipv4': { '192.168.1.1': { 'prefix_length': 24 } }, 'ipv6': { '1::1': { 'prefix_length': 64 }, '2001:DB8:1::1': { 'prefix_length': 64 }, 'FE80::3': { 'prefix_length': 'N/A' } } } } """ return salt.utils.napalm.call( napalm_device, "get_interfaces_ip", **{} # pylint: disable=undefined-variable ) @salt.utils.napalm.proxy_napalm_wrap def interfaces(**kwargs): # pylint: disable=unused-argument """ Returns details of the interfaces on the device. :return: Returns a dictionary of dictionaries. The keys for the first dictionary will be the interfaces in the devices. CLI Example: .. code-block:: bash salt '*' net.interfaces Example output: .. code-block:: python { 'Management1': { 'is_up': False, 'is_enabled': False, 'description': '', 'last_flapped': -1, 'speed': 1000, 'mac_address': 'dead:beef:dead', }, 'Ethernet1':{ 'is_up': True, 'is_enabled': True, 'description': 'foo', 'last_flapped': 1429978575.1554043, 'speed': 1000, 'mac_address': 'beef:dead:beef', } } """ return salt.utils.napalm.call( napalm_device, "get_interfaces", **{} # pylint: disable=undefined-variable ) @salt.utils.napalm.proxy_napalm_wrap def lldp(interface="", **kwargs): # pylint: disable=unused-argument """ Returns a detailed view of the LLDP neighbors. :param interface: interface name to filter on :return: A dictionary with the LLDL neighbors. The keys are the interfaces with LLDP activated on. CLI Example: .. code-block:: bash salt '*' net.lldp salt '*' net.lldp interface='TenGigE0/0/0/8' Example output: .. code-block:: python { 'TenGigE0/0/0/8': [ { 'parent_interface': 'Bundle-Ether8', 'interface_description': 'TenGigE0/0/0/8', 'remote_chassis_id': '8c60.4f69.e96c', 'remote_system_name': 'switch', 'remote_port': 'Eth2/2/1', 'remote_port_description': 'Ethernet2/2/1', 'remote_system_description': 'Cisco Nexus Operating System (NX-OS) Software 7.1(0)N1(1a) TAC support: http://www.cisco.com/tac Copyright (c) 2002-2015, Cisco Systems, Inc. All rights reserved.', 'remote_system_capab': 'B, R', 'remote_system_enable_capab': 'B' } ] } """ proxy_output = salt.utils.napalm.call( napalm_device, # pylint: disable=undefined-variable "get_lldp_neighbors_detail", **{} ) if not proxy_output.get("result"): return proxy_output lldp_neighbors = proxy_output.get("out") if interface: lldp_neighbors = {interface: lldp_neighbors.get(interface)} proxy_output.update({"out": lldp_neighbors}) return proxy_output @salt.utils.napalm.proxy_napalm_wrap def mac(address="", interface="", vlan=0, **kwargs): # pylint: disable=unused-argument """ Returns the MAC Address Table on the device. :param address: MAC address to filter on :param interface: Interface name to filter on :param vlan: VLAN identifier :return: A list of dictionaries representing the entries in the MAC Address Table CLI Example: .. code-block:: bash salt '*' net.mac salt '*' net.mac vlan=10 Example output: .. code-block:: python [ { 'mac' : '00:1c:58:29:4a:71', 'interface' : 'xe-3/0/2', 'static' : False, 'active' : True, 'moves' : 1, 'vlan' : 10, 'last_move' : 1454417742.58 }, { 'mac' : '8c:60:4f:58:e1:c1', 'interface' : 'xe-1/0/1', 'static' : False, 'active' : True, 'moves' : 2, 'vlan' : 42, 'last_move' : 1453191948.11 } ] """ proxy_output = salt.utils.napalm.call( napalm_device, # pylint: disable=undefined-variable "get_mac_address_table", **{} ) if not proxy_output.get("result"): # if negative, leave the output unchanged return proxy_output mac_address_table = proxy_output.get("out") if vlan and isinstance(vlan, int): mac_address_table = _filter_list(mac_address_table, "vlan", vlan) if address: mac_address_table = _filter_list(mac_address_table, "mac", address) if interface: mac_address_table = _filter_list(mac_address_table, "interface", interface) proxy_output.update({"out": mac_address_table}) return proxy_output @salt.utils.napalm.proxy_napalm_wrap def config(source=None, **kwargs): # pylint: disable=unused-argument """ .. versionadded:: 2017.7.0 Return the whole configuration of the network device. By default, it will return all possible configuration sources supported by the network device. At most, there will be: - running config - startup config - candidate config To return only one of the configurations, you can use the ``source`` argument. source Which configuration type you want to display, default is all of them. Options: - running - candidate - startup :return: The object returned is a dictionary with the following keys: - running (string): Representation of the native running configuration. - candidate (string): Representation of the native candidate configuration. If the device doesn't differentiate between running and startup configuration this will an empty string. - startup (string): Representation of the native startup configuration. If the device doesn't differentiate between running and startup configuration this will an empty string. CLI Example: .. code-block:: bash salt '*' net.config salt '*' net.config source=candidate """ return salt.utils.napalm.call( napalm_device, # pylint: disable=undefined-variable "get_config", **{"retrieve": source} ) @salt.utils.napalm.proxy_napalm_wrap def optics(**kwargs): # pylint: disable=unused-argument """ .. versionadded:: 2017.7.0 Fetches the power usage on the various transceivers installed on the network device (in dBm), and returns a view that conforms with the OpenConfig model openconfig-platform-transceiver.yang. :return: Returns a dictionary where the keys are as listed below: * intf_name (unicode) * physical_channels * channels (list of dicts) * index (int) * state * input_power * instant (float) * avg (float) * min (float) * max (float) * output_power * instant (float) * avg (float) * min (float) * max (float) * laser_bias_current * instant (float) * avg (float) * min (float) * max (float) CLI Example: .. code-block:: bash salt '*' net.optics """ return salt.utils.napalm.call( napalm_device, "get_optics", **{} # pylint: disable=undefined-variable ) # <---- Call NAPALM getters -------------------------------------------------------------------------------------------- # ----- Configuration specific functions ------------------------------------------------------------------------------> @salt.utils.napalm.proxy_napalm_wrap def load_config( filename=None, text=None, test=False, commit=True, debug=False, replace=False, commit_in=None, commit_at=None, revert_in=None, revert_at=None, commit_jid=None, inherit_napalm_device=None, saltenv="base", **kwargs ): # pylint: disable=unused-argument """ Applies configuration changes on the device. It can be loaded from a file or from inline string. If you send both a filename and a string containing the configuration, the file has higher precedence. By default this function will commit the changes. If there are no changes, it does not commit and the flag ``already_configured`` will be set as ``True`` to point this out. To avoid committing the configuration, set the argument ``test`` to ``True`` and will discard (dry run). To keep the changes but not commit, set ``commit`` to ``False``. To replace the config, set ``replace`` to ``True``. filename Path to the file containing the desired configuration. This can be specified using the absolute path to the file, or using one of the following URL schemes: - ``salt://``, to fetch the template from the Salt fileserver. - ``http://`` or ``https://`` - ``ftp://`` - ``s3://`` - ``swift://`` .. versionchanged:: 2018.3.0 text String containing the desired configuration. This argument is ignored when ``filename`` is specified. test: False Dry run? If set as ``True``, will apply the config, discard and return the changes. Default: ``False`` and will commit the changes on the device. commit: True Commit? Default: ``True``. debug: False Debug mode. Will insert a new key under the output dictionary, as ``loaded_config`` containing the raw configuration loaded on the device. .. versionadded:: 2016.11.2 replace: False Load and replace the configuration. Default: ``False``. .. versionadded:: 2016.11.2 commit_in: ``None`` Commit the changes in a specific number of minutes / hours. Example of accepted formats: ``5`` (commit in 5 minutes), ``2m`` (commit in 2 minutes), ``1h`` (commit the changes in 1 hour)`, ``5h30m`` (commit the changes in 5 hours and 30 minutes). .. note:: This feature works on any platforms, as it does not rely on the native features of the network operating system. .. note:: After the command is executed and the ``diff`` is not satisfactory, or for any other reasons you have to discard the commit, you are able to do so using the :py:func:`net.cancel_commit <salt.modules.napalm_network.cancel_commit>` execution function, using the commit ID returned by this function. .. warning:: Using this feature, Salt will load the exact configuration you expect, however the diff may change in time (i.e., if an user applies a manual configuration change, or a different process or command changes the configuration in the meanwhile). .. versionadded:: 2019.2.0 commit_at: ``None`` Commit the changes at a specific time. Example of accepted formats: ``1am`` (will commit the changes at the next 1AM), ``13:20`` (will commit at 13:20), ``1:20am``, etc. .. note:: This feature works on any platforms, as it does not rely on the native features of the network operating system. .. note:: After the command is executed and the ``diff`` is not satisfactory, or for any other reasons you have to discard the commit, you are able to do so using the :py:func:`net.cancel_commit <salt.modules.napalm_network.cancel_commit>` execution function, using the commit ID returned by this function. .. warning:: Using this feature, Salt will load the exact configuration you expect, however the diff may change in time (i.e., if an user applies a manual configuration change, or a different process or command changes the configuration in the meanwhile). .. versionadded:: 2019.2.0 revert_in: ``None`` Commit and revert the changes in a specific number of minutes / hours. Example of accepted formats: ``5`` (revert in 5 minutes), ``2m`` (revert in 2 minutes), ``1h`` (revert the changes in 1 hour)`, ``5h30m`` (revert the changes in 5 hours and 30 minutes). .. note:: To confirm the commit, and prevent reverting the changes, you will have to execute the :mod:`net.confirm_commit <salt.modules.napalm_network.confirm_commit>` function, using the commit ID returned by this function. .. warning:: This works on any platform, regardless if they have or don't have native capabilities to confirming a commit. However, please be *very* cautious when using this feature: on Junos (as it is the only NAPALM core platform supporting this natively) it executes a commit confirmed as you would do from the command line. All the other platforms don't have this capability natively, therefore the revert is done via Salt. That means, your device needs to be reachable at the moment when Salt will attempt to revert your changes. Be cautious when pushing configuration changes that would prevent you reach the device. Similarly, if an user or a different process apply other configuration changes in the meanwhile (between the moment you commit and till the changes are reverted), these changes would be equally reverted, as Salt cannot be aware of them. .. versionadded:: 2019.2.0 revert_at: ``None`` Commit and revert the changes at a specific time. Example of accepted formats: ``1am`` (will commit and revert the changes at the next 1AM), ``13:20`` (will commit and revert at 13:20), ``1:20am``, etc. .. note:: To confirm the commit, and prevent reverting the changes, you will have to execute the :mod:`net.confirm_commit <salt.modules.napalm_network.confirm_commit>` function, using the commit ID returned by this function. .. warning:: This works on any platform, regardless if they have or don't have native capabilities to confirming a commit. However, please be *very* cautious when using this feature: on Junos (as it is the only NAPALM core platform supporting this natively) it executes a commit confirmed as you would do from the command line. All the other platforms don't have this capability natively, therefore the revert is done via Salt. That means, your device needs to be reachable at the moment when Salt will attempt to revert your changes. Be cautious when pushing configuration changes that would prevent you reach the device. Similarly, if an user or a different process apply other configuration changes in the meanwhile (between the moment you commit and till the changes are reverted), these changes would be equally reverted, as Salt cannot be aware of them. .. versionadded:: 2019.2.0 saltenv: ``base`` Specifies the Salt environment name. .. versionadded:: 2018.3.0 :return: a dictionary having the following keys: * result (bool): if the config was applied successfully. It is ``False`` only in case of failure. In case \ there are no changes to be applied and successfully performs all operations it is still ``True`` and so will be \ the ``already_configured`` flag (example below) * comment (str): a message for the user * already_configured (bool): flag to check if there were no changes applied * loaded_config (str): the configuration loaded on the device. Requires ``debug`` to be set as ``True`` * diff (str): returns the config changes applied CLI Example: .. code-block:: bash salt '*' net.load_config text='ntp peer 192.168.0.1' salt '*' net.load_config filename='/absolute/path/to/your/file' salt '*' net.load_config filename='/absolute/path/to/your/file' test=True salt '*' net.load_config filename='/absolute/path/to/your/file' commit=False Example output: .. code-block:: python { 'comment': 'Configuration discarded.', 'already_configured': False, 'result': True, 'diff': '[edit interfaces xe-0/0/5]+ description "Adding a description";' } """ fun = "load_merge_candidate" if replace: fun = "load_replace_candidate" if salt.utils.napalm.not_always_alive(__opts__): # if a not-always-alive proxy # or regular minion # do not close the connection after loading the config # this will be handled in _config_logic # after running the other features: # compare_config, discard / commit # which have to be over the same session napalm_device["CLOSE"] = False # pylint: disable=undefined-variable if filename: text = __salt__["cp.get_file_str"](filename, saltenv=saltenv) if text is False: # When using salt:// or https://, if the resource is not available, # it will either raise an exception, or return False. ret = {"result": False, "out": None} ret[ "comment" ] = "Unable to read from {}. Please specify a valid file or text.".format( filename ) log.error(ret["comment"]) return ret if commit_jid: # When the commit_jid argument is passed, it probably is a scheduled # commit to be executed, and filename is a temporary file which # can be removed after reading it. salt.utils.files.safe_rm(filename) _loaded = salt.utils.napalm.call( napalm_device, fun, **{"config": text} # pylint: disable=undefined-variable ) return _config_logic( napalm_device, # pylint: disable=undefined-variable _loaded, test=test, debug=debug, replace=replace, commit_config=commit, loaded_config=text, commit_at=commit_at, commit_in=commit_in, revert_in=revert_in, revert_at=revert_at, commit_jid=commit_jid, **kwargs ) @salt.utils.napalm.proxy_napalm_wrap def load_template( template_name=None, template_source=None, context=None, defaults=None, template_engine="jinja", saltenv="base", template_hash=None, template_hash_name=None, skip_verify=False, test=False, commit=True, debug=False, replace=False, commit_in=None, commit_at=None, revert_in=None, revert_at=None, inherit_napalm_device=None, # pylint: disable=unused-argument **template_vars ): """ Renders a configuration template (default: Jinja) and loads the result on the device. By default this function will commit the changes. If there are no changes, it does not commit, discards he config and the flag ``already_configured`` will be set as ``True`` to point this out. To avoid committing the configuration, set the argument ``test`` to ``True`` and will discard (dry run). To preserve the changes, set ``commit`` to ``False``. However, this is recommended to be used only in exceptional cases when there are applied few consecutive states and/or configuration changes. Otherwise the user might forget that the config DB is locked and the candidate config buffer is not cleared/merged in the running config. To replace the config, set ``replace`` to ``True``. template_name Identifies path to the template source. The template can be either stored on the local machine, either remotely. The recommended location is under the ``file_roots`` as specified in the master config file. For example, let's suppose the ``file_roots`` is configured as: .. code-block:: yaml file_roots: base: - /etc/salt/states Placing the template under ``/etc/salt/states/templates/example.jinja``, it can be used as ``salt://templates/example.jinja``. Alternatively, for local files, the user can specify the absolute path. If remotely, the source can be retrieved via ``http``, ``https`` or ``ftp``. Examples: - ``salt://my_template.jinja`` - ``/absolute/path/to/my_template.jinja`` - ``http://example.com/template.cheetah`` - ``https:/example.com/template.mako`` - ``ftp://example.com/template.py`` .. versionchanged:: 2019.2.0 This argument can now support a list of templates to be rendered. The resulting configuration text is loaded at once, as a single configuration chunk. template_source: None Inline config template to be rendered and loaded on the device. template_hash: None Hash of the template file. Format: ``{hash_type: 'md5', 'hsum': <md5sum>}`` .. versionadded:: 2016.11.2 context: None Overrides default context variables passed to the template. .. versionadded:: 2019.2.0 template_hash_name: None When ``template_hash`` refers to a remote file, this specifies the filename to look for in that file. .. versionadded:: 2016.11.2 saltenv: ``base`` Specifies the template environment. This will influence the relative imports inside the templates. .. versionadded:: 2016.11.2 template_engine: jinja The following templates engines are supported: - :mod:`cheetah<salt.renderers.cheetah>` - :mod:`genshi<salt.renderers.genshi>` - :mod:`jinja<salt.renderers.jinja>` - :mod:`mako<salt.renderers.mako>` - :mod:`py<salt.renderers.py>` - :mod:`wempy<salt.renderers.wempy>` .. versionadded:: 2016.11.2 skip_verify: True If ``True``, hash verification of remote file sources (``http://``, ``https://``, ``ftp://``) will be skipped, and the ``source_hash`` argument will be ignored. .. versionadded:: 2016.11.2 test: False Dry run? If set to ``True``, will apply the config, discard and return the changes. Default: ``False`` and will commit the changes on the device. commit: True Commit? (default: ``True``) debug: False Debug mode. Will insert a new key under the output dictionary, as ``loaded_config`` containing the raw result after the template was rendered. .. versionadded:: 2016.11.2 replace: False Load and replace the configuration. .. versionadded:: 2016.11.2 commit_in: ``None`` Commit the changes in a specific number of minutes / hours. Example of accepted formats: ``5`` (commit in 5 minutes), ``2m`` (commit in 2 minutes), ``1h`` (commit the changes in 1 hour)`, ``5h30m`` (commit the changes in 5 hours and 30 minutes). .. note:: This feature works on any platforms, as it does not rely on the native features of the network operating system. .. note:: After the command is executed and the ``diff`` is not satisfactory, or for any other reasons you have to discard the commit, you are able to do so using the :py:func:`net.cancel_commit <salt.modules.napalm_network.cancel_commit>` execution function, using the commit ID returned by this function. .. warning:: Using this feature, Salt will load the exact configuration you expect, however the diff may change in time (i.e., if an user applies a manual configuration change, or a different process or command changes the configuration in the meanwhile). .. versionadded:: 2019.2.0 commit_at: ``None`` Commit the changes at a specific time. Example of accepted formats: ``1am`` (will commit the changes at the next 1AM), ``13:20`` (will commit at 13:20), ``1:20am``, etc. .. note:: This feature works on any platforms, as it does not rely on the native features of the network operating system. .. note:: After the command is executed and the ``diff`` is not satisfactory, or for any other reasons you have to discard the commit, you are able to do so using the :py:func:`net.cancel_commit <salt.modules.napalm_network.cancel_commit>` execution function, using the commit ID returned by this function. .. warning:: Using this feature, Salt will load the exact configuration you expect, however the diff may change in time (i.e., if an user applies a manual configuration change, or a different process or command changes the configuration in the meanwhile). .. versionadded:: 2019.2.0 revert_in: ``None`` Commit and revert the changes in a specific number of minutes / hours. Example of accepted formats: ``5`` (revert in 5 minutes), ``2m`` (revert in 2 minutes), ``1h`` (revert the changes in 1 hour)`, ``5h30m`` (revert the changes in 5 hours and 30 minutes). .. note:: To confirm the commit, and prevent reverting the changes, you will have to execute the :mod:`net.confirm_commit <salt.modules.napalm_network.confirm_commit>` function, using the commit ID returned by this function. .. warning:: This works on any platform, regardless if they have or don't have native capabilities to confirming a commit. However, please be *very* cautious when using this feature: on Junos (as it is the only NAPALM core platform supporting this natively) it executes a commit confirmed as you would do from the command line. All the other platforms don't have this capability natively, therefore the revert is done via Salt. That means, your device needs to be reachable at the moment when Salt will attempt to revert your changes. Be cautious when pushing configuration changes that would prevent you reach the device. Similarly, if an user or a different process apply other configuration changes in the meanwhile (between the moment you commit and till the changes are reverted), these changes would be equally reverted, as Salt cannot be aware of them. .. versionadded:: 2019.2.0 revert_at: ``None`` Commit and revert the changes at a specific time. Example of accepted formats: ``1am`` (will commit and revert the changes at the next 1AM), ``13:20`` (will commit and revert at 13:20), ``1:20am``, etc. .. note:: To confirm the commit, and prevent reverting the changes, you will have to execute the :mod:`net.confirm_commit <salt.modules.napalm_network.confirm_commit>` function, using the commit ID returned by this function. .. warning:: This works on any platform, regardless if they have or don't have native capabilities to confirming a commit. However, please be *very* cautious when using this feature: on Junos (as it is the only NAPALM core platform supporting this natively) it executes a commit confirmed as you would do from the command line. All the other platforms don't have this capability natively, therefore the revert is done via Salt. That means, your device needs to be reachable at the moment when Salt will attempt to revert your changes. Be cautious when pushing configuration changes that would prevent you reach the device. Similarly, if an user or a different process apply other configuration changes in the meanwhile (between the moment you commit and till the changes are reverted), these changes would be equally reverted, as Salt cannot be aware of them. .. versionadded:: 2019.2.0 defaults: None Default variables/context passed to the template. .. versionadded:: 2016.11.2 template_vars Dictionary with the arguments/context to be used when the template is rendered. .. note:: Do not explicitly specify this argument. This represents any other variable that will be sent to the template rendering system. Please see the examples below! .. note:: It is more recommended to use the ``context`` argument to avoid conflicts between CLI arguments and template variables. :return: a dictionary having the following keys: - result (bool): if the config was applied successfully. It is ``False`` only in case of failure. In case there are no changes to be applied and successfully performs all operations it is still ``True`` and so will be the ``already_configured`` flag (example below) - comment (str): a message for the user - already_configured (bool): flag to check if there were no changes applied - loaded_config (str): the configuration loaded on the device, after rendering the template. Requires ``debug`` to be set as ``True`` - diff (str): returns the config changes applied The template can use variables from the ``grains``, ``pillar`` or ``opts``, for example: .. code-block:: jinja {% set router_model = grains.get('model') -%} {% set router_vendor = grains.get('vendor') -%} {% set os_version = grains.get('version') -%} {% set hostname = pillar.get('proxy', {}).get('host') -%} {% if router_vendor|lower == 'juniper' %} system { host-name {{hostname}}; } {% elif router_vendor|lower == 'cisco' %} hostname {{hostname}} {% endif %} CLI Examples: .. code-block:: bash salt '*' net.load_template set_ntp_peers peers=[192.168.0.1] # uses NAPALM default templates # inline template: salt -G 'os:junos' net.load_template template_source='system { host-name {{host_name}}; }' \ host_name='MX480.lab' # inline template using grains info: salt -G 'os:junos' net.load_template \ template_source='system { host-name {{grains.model}}.lab; }' # if the device is a MX480, the command above will set the hostname as: MX480.lab # inline template using pillar data: salt -G 'os:junos' net.load_template template_source='system { host-name {{pillar.proxy.host}}; }' salt '*' net.load_template https://bit.ly/2OhSgqP hostname=example # will commit salt '*' net.load_template https://bit.ly/2OhSgqP hostname=example test=True # dry run salt '*' net.load_template salt://templates/example.jinja debug=True # Using the salt:// URI # render a mako template: salt '*' net.load_template salt://templates/example.mako template_engine=mako debug=True # render remote template salt -G 'os:junos' net.load_template http://bit.ly/2fReJg7 test=True debug=True peers=['192.168.0.1'] salt -G 'os:ios' net.load_template http://bit.ly/2gKOj20 test=True debug=True peers=['192.168.0.1'] # render multiple templates at once salt '*' net.load_template "['https://bit.ly/2OhSgqP', 'salt://templates/example.jinja']" context="{'hostname': 'example'}" Example output: .. code-block:: python { 'comment': '', 'already_configured': False, 'result': True, 'diff': '[edit system]+ host-name edge01.bjm01', 'loaded_config': 'system { host-name edge01.bjm01; }'' } """ _rendered = "" _loaded = {"result": True, "comment": "", "out": None} loaded_config = None # prechecks if template_engine not in salt.utils.templates.TEMPLATE_REGISTRY: _loaded.update( { "result": False, "comment": ( "Invalid templating engine! Choose between: {tpl_eng_opts}".format( tpl_eng_opts=", ".join( list(salt.utils.templates.TEMPLATE_REGISTRY.keys()) ) ) ), } ) return _loaded # exit # to check if will be rendered by salt or NAPALM salt_render_prefixes = ("salt://", "http://", "https://", "ftp://") salt_render = False file_exists = False if not isinstance(template_name, (tuple, list)): for salt_render_prefix in salt_render_prefixes: if not salt_render: salt_render = salt_render or template_name.startswith( salt_render_prefix ) file_exists = __salt__["file.file_exists"](template_name) if context is None: context = {} context.update(template_vars) # if needed to render the template send as inline arg if template_source: # render the content _rendered = __salt__["file.apply_template_on_contents"]( contents=template_source, template=template_engine, context=context, defaults=defaults, saltenv=saltenv, ) if not isinstance(_rendered, str): if "result" in _rendered: _loaded["result"] = _rendered["result"] else: _loaded["result"] = False if "comment" in _rendered: _loaded["comment"] = _rendered["comment"] else: _loaded["comment"] = "Error while rendering the template." return _loaded else: # render the file - either local, either remote if not isinstance(template_name, (list, tuple)): template_name = [template_name] if template_hash_name and not isinstance(template_hash_name, (list, tuple)): template_hash_name = [template_hash_name] elif not template_hash_name: template_hash_name = [None] * len(template_name) if ( template_hash and isinstance(template_hash, str) and not ( template_hash.startswith("salt://") or template_hash.startswith("file://") ) ): # If the template hash is passed as string, and it's not a file # (starts with the salt:// or file:// URI), then make it a list # of 1 element (for the iteration below) template_hash = [template_hash] elif ( template_hash and isinstance(template_hash, str) and ( template_hash.startswith("salt://") or template_hash.startswith("file://") ) ): # If the template hash is a file URI, then provide the same value # for each of the templates in the list, as probably they all # share the same hash file, otherwise the user should provide # this as a list template_hash = [template_hash] * len(template_name) elif not template_hash: template_hash = [None] * len(template_name) for tpl_index, tpl_name in enumerate(template_name): tpl_hash = template_hash[tpl_index] tpl_hash_name = template_hash_name[tpl_index] _rand_filename = __salt__["random.hash"](tpl_name, "md5") _temp_file = __salt__["file.join"]("/tmp", _rand_filename) _managed = __salt__["file.get_managed"]( name=_temp_file, source=tpl_name, source_hash=tpl_hash, source_hash_name=tpl_hash_name, user=None, group=None, mode=None, attrs=None, template=template_engine, context=context, defaults=defaults, saltenv=saltenv, skip_verify=skip_verify, ) if not isinstance(_managed, (list, tuple)) and isinstance(_managed, str): _loaded["comment"] += _managed _loaded["result"] = False elif isinstance(_managed, (list, tuple)) and not len(_managed) > 0: _loaded["result"] = False _loaded["comment"] += "Error while rendering the template." elif isinstance(_managed, (list, tuple)) and not len(_managed[0]) > 0: _loaded["result"] = False _loaded["comment"] += _managed[-1] # contains the error message if _loaded["result"]: # all good _temp_tpl_file = _managed[0] _temp_tpl_file_exists = __salt__["file.file_exists"](_temp_tpl_file) if not _temp_tpl_file_exists: _loaded["result"] = False _loaded["comment"] += "Error while rendering the template." return _loaded _rendered += __salt__["file.read"](_temp_tpl_file) __salt__["file.remove"](_temp_tpl_file) else: return _loaded # exit loaded_config = _rendered if _loaded["result"]: # all good fun = "load_merge_candidate" if replace: # replace requested fun = "load_replace_candidate" if salt.utils.napalm.not_always_alive(__opts__): # if a not-always-alive proxy # or regular minion # do not close the connection after loading the config # this will be handled in _config_logic # after running the other features: # compare_config, discard / commit # which have to be over the same session napalm_device["CLOSE"] = False # pylint: disable=undefined-variable _loaded = salt.utils.napalm.call( napalm_device, # pylint: disable=undefined-variable fun, **{"config": _rendered} ) return _config_logic( napalm_device, # pylint: disable=undefined-variable _loaded, test=test, debug=debug, replace=replace, commit_config=commit, loaded_config=loaded_config, commit_at=commit_at, commit_in=commit_in, revert_in=revert_in, revert_at=revert_at, **template_vars ) @salt.utils.napalm.proxy_napalm_wrap def commit(inherit_napalm_device=None, **kwargs): # pylint: disable=unused-argument """ Commits the configuration changes made on the network device. CLI Example: .. code-block:: bash salt '*' net.commit """ return salt.utils.napalm.call( napalm_device, "commit_config", **{} # pylint: disable=undefined-variable ) @salt.utils.napalm.proxy_napalm_wrap def discard_config( inherit_napalm_device=None, **kwargs ): # pylint: disable=unused-argument """ Discards the changes applied. CLI Example: .. code-block:: bash salt '*' net.discard_config """ return salt.utils.napalm.call( napalm_device, "discard_config", **{} # pylint: disable=undefined-variable ) @salt.utils.napalm.proxy_napalm_wrap def compare_config( inherit_napalm_device=None, **kwargs ): # pylint: disable=unused-argument """ Returns the difference between the running config and the candidate config. CLI Example: .. code-block:: bash salt '*' net.compare_config """ return salt.utils.napalm.call( napalm_device, "compare_config", **{} # pylint: disable=undefined-variable ) @salt.utils.napalm.proxy_napalm_wrap def rollback(inherit_napalm_device=None, **kwargs): # pylint: disable=unused-argument """ Rollbacks the configuration. CLI Example: .. code-block:: bash salt '*' net.rollback """ return salt.utils.napalm.call( napalm_device, "rollback", **{} # pylint: disable=undefined-variable ) @salt.utils.napalm.proxy_napalm_wrap def config_changed( inherit_napalm_device=None, **kwargs ): # pylint: disable=unused-argument """ Will prompt if the configuration has been changed. :return: A tuple with a boolean that specifies if the config was changed on the device.\ And a string that provides more details of the reason why the configuration was not changed. CLI Example: .. code-block:: bash salt '*' net.config_changed """ is_config_changed = False reason = "" # pylint: disable=undefined-variable try_compare = compare_config(inherit_napalm_device=napalm_device) # pylint: enable=undefined-variable if try_compare.get("result"): if try_compare.get("out"): is_config_changed = True else: reason = "Configuration was not changed on the device." else: reason = try_compare.get("comment") return is_config_changed, reason @salt.utils.napalm.proxy_napalm_wrap def config_control( inherit_napalm_device=None, **kwargs ): # pylint: disable=unused-argument """ Will check if the configuration was changed. If differences found, will try to commit. In case commit unsuccessful, will try to rollback. :return: A tuple with a boolean that specifies if the config was changed/committed/rollbacked on the device.\ And a string that provides more details of the reason why the configuration was not committed properly. CLI Example: .. code-block:: bash salt '*' net.config_control """ result = True comment = "" # pylint: disable=undefined-variable changed, not_changed_rsn = config_changed(inherit_napalm_device=napalm_device) # pylint: enable=undefined-variable if not changed: return (changed, not_changed_rsn) # config changed, thus let's try to commit try_commit = commit() if not try_commit.get("result"): result = False comment = ( "Unable to commit the changes: {reason}.\nWill try to rollback now!".format( reason=try_commit.get("comment") ) ) try_rollback = rollback() if not try_rollback.get("result"): comment += "\nCannot rollback! {reason}".format( reason=try_rollback.get("comment") ) return result, comment def cancel_commit(jid): """ .. versionadded:: 2019.2.0 Cancel a commit scheduled to be executed via the ``commit_in`` and ``commit_at`` arguments from the :py:func:`net.load_template <salt.modules.napalm_network.load_template>` or :py:func:`net.load_config <salt.modules.napalm_network.load_config>` execution functions. The commit ID is displayed when the commit is scheduled via the functions named above. CLI Example: .. code-block:: bash salt '*' net.cancel_commit 20180726083540640360 """ job_name = "__napalm_commit_{}".format(jid) removed = __salt__["schedule.delete"](job_name) if removed["result"]: saved = __salt__["schedule.save"]() removed["comment"] = "Commit #{jid} cancelled.".format(jid=jid) else: removed["comment"] = "Unable to find commit #{jid}.".format(jid=jid) return removed def confirm_commit(jid): """ .. versionadded:: 2019.2.0 Confirm a commit scheduled to be reverted via the ``revert_in`` and ``revert_at`` arguments from the :mod:`net.load_template <salt.modules.napalm_network.load_template>` or :mod:`net.load_config <salt.modules.napalm_network.load_config>` execution functions. The commit ID is displayed when the commit confirmed is scheduled via the functions named above. CLI Example: .. code-block:: bash salt '*' net.confirm_commit 20180726083540640360 """ if __grains__["os"] == "junos": # Confirm the commit, by committing (i.e., invoking the RPC call) confirmed = __salt__["napalm.junos_commit"]() confirmed["result"] = confirmed.pop("out") confirmed["comment"] = confirmed.pop("message") else: confirmed = cancel_commit(jid) if confirmed["result"]: confirmed["comment"] = "Commit #{jid} confirmed.".format(jid=jid) return confirmed def save_config(source=None, path=None): """ .. versionadded:: 2019.2.0 Save the configuration to a file on the local file system. source: ``running`` The configuration source. Choose from: ``running``, ``candidate``, ``startup``. Default: ``running``. path Absolute path to file where to save the configuration. To push the files to the Master, use :mod:`cp.push <salt.modules.cp.push>` Execution function. CLI Example: .. code-block:: bash salt '*' net.save_config source=running """ if not source: source = "running" if not path: path = salt.utils.files.mkstemp() running_config = __salt__["net.config"](source=source) if not running_config or not running_config["result"]: log.error("Unable to retrieve the config") return running_config with salt.utils.files.fopen(path, "w") as fh_: fh_.write(running_config["out"][source]) return { "result": True, "out": path, "comment": "{source} config saved to {path}".format(source=source, path=path), } def replace_pattern( pattern, repl, count=0, flags=8, bufsize=1, append_if_not_found=False, prepend_if_not_found=False, not_found_content=None, search_only=False, show_changes=True, backslash_literal=False, source=None, path=None, test=False, replace=True, debug=False, commit=True, ): """ .. versionadded:: 2019.2.0 Replace occurrences of a pattern in the configuration source. If ``show_changes`` is ``True``, then a diff of what changed will be returned, otherwise a ``True`` will be returned when changes are made, and ``False`` when no changes are made. This is a pure Python implementation that wraps Python's :py:func:`~re.sub`. pattern A regular expression, to be matched using Python's :py:func:`~re.search`. repl The replacement text. count: ``0`` Maximum number of pattern occurrences to be replaced. If count is a positive integer ``n``, only ``n`` occurrences will be replaced, otherwise all occurrences will be replaced. flags (list or int): ``8`` A list of flags defined in the ``re`` module documentation from the Python standard library. Each list item should be a string that will correlate to the human-friendly flag name. E.g., ``['IGNORECASE', 'MULTILINE']``. Optionally, ``flags`` may be an int, with a value corresponding to the XOR (``|``) of all the desired flags. Defaults to 8 (which supports 'MULTILINE'). bufsize (int or str): ``1`` How much of the configuration to buffer into memory at once. The default value ``1`` processes one line at a time. The special value ``file`` may be specified which will read the entire file into memory before processing. append_if_not_found: ``False`` If set to ``True``, and pattern is not found, then the content will be appended to the file. prepend_if_not_found: ``False`` If set to ``True`` and pattern is not found, then the content will be prepended to the file. not_found_content Content to use for append/prepend if not found. If None (default), uses ``repl``. Useful when ``repl`` uses references to group in pattern. search_only: ``False`` If set to true, this no changes will be performed on the file, and this function will simply return ``True`` if the pattern was matched, and ``False`` if not. show_changes: ``True`` If ``True``, return a diff of changes made. Otherwise, return ``True`` if changes were made, and ``False`` if not. backslash_literal: ``False`` Interpret backslashes as literal backslashes for the repl and not escape characters. This will help when using append/prepend so that the backslashes are not interpreted for the repl on the second run of the state. source: ``running`` The configuration source. Choose from: ``running``, ``candidate``, or ``startup``. Default: ``running``. path Save the temporary configuration to a specific path, then read from there. test: ``False`` Dry run? If set as ``True``, will apply the config, discard and return the changes. Default: ``False`` and will commit the changes on the device. commit: ``True`` Commit the configuration changes? Default: ``True``. debug: ``False`` Debug mode. Will insert a new key in the output dictionary, as ``loaded_config`` containing the raw configuration loaded on the device. replace: ``True`` Load and replace the configuration. Default: ``True``. If an equal sign (``=``) appears in an argument to a Salt command it is interpreted as a keyword argument in the format ``key=val``. That processing can be bypassed in order to pass an equal sign through to the remote shell command by manually specifying the kwarg: .. code-block:: bash salt '*' net.replace_pattern "bind-address\\s*=" "bind-address:" CLI Example: .. code-block:: bash salt '*' net.replace_pattern PREFIX-LIST_NAME new-prefix-list-name salt '*' net.replace_pattern bgp-group-name new-bgp-group-name count=1 """ config_saved = save_config(source=source, path=path) if not config_saved or not config_saved["result"]: return config_saved path = config_saved["out"] replace_pattern = __salt__["file.replace"]( path, pattern, repl, count=count, flags=flags, bufsize=bufsize, append_if_not_found=append_if_not_found, prepend_if_not_found=prepend_if_not_found, not_found_content=not_found_content, search_only=search_only, show_changes=show_changes, backslash_literal=backslash_literal, ) with salt.utils.files.fopen(path, "r") as fh_: updated_config = fh_.read() return __salt__["net.load_config"]( text=updated_config, test=test, debug=debug, replace=replace, commit=commit ) def blockreplace( marker_start, marker_end, content="", append_if_not_found=False, prepend_if_not_found=False, show_changes=True, append_newline=False, source="running", path=None, test=False, commit=True, debug=False, replace=True, ): """ .. versionadded:: 2019.2.0 Replace content of the configuration source, delimited by the line markers. A block of content delimited by comments can help you manage several lines without worrying about old entries removal. marker_start The line content identifying a line as the start of the content block. Note that the whole line containing this marker will be considered, so whitespace or extra content before or after the marker is included in final output. marker_end The line content identifying a line as the end of the content block. Note that the whole line containing this marker will be considered, so whitespace or extra content before or after the marker is included in final output. content The content to be used between the two lines identified by ``marker_start`` and ``marker_stop``. append_if_not_found: ``False`` If markers are not found and set to True then, the markers and content will be appended to the file. prepend_if_not_found: ``False`` If markers are not found and set to True then, the markers and content will be prepended to the file. append_newline: ``False`` Controls whether or not a newline is appended to the content block. If the value of this argument is ``True`` then a newline will be added to the content block. If it is ``False``, then a newline will not be added to the content block. If it is ``None`` then a newline will only be added to the content block if it does not already end in a newline. show_changes: ``True`` Controls how changes are presented. If ``True``, this function will return the of the changes made. If ``False``, then it will return a boolean (``True`` if any changes were made, otherwise False). source: ``running`` The configuration source. Choose from: ``running``, ``candidate``, or ``startup``. Default: ``running``. path: ``None`` Save the temporary configuration to a specific path, then read from there. This argument is optional, can be used when you prefers a particular location of the temporary file. test: ``False`` Dry run? If set as ``True``, will apply the config, discard and return the changes. Default: ``False`` and will commit the changes on the device. commit: ``True`` Commit the configuration changes? Default: ``True``. debug: ``False`` Debug mode. Will insert a new key in the output dictionary, as ``loaded_config`` containing the raw configuration loaded on the device. replace: ``True`` Load and replace the configuration. Default: ``True``. CLI Example: .. code-block:: bash salt '*' net.blockreplace 'ntp' 'interface' '' """ config_saved = save_config(source=source, path=path) if not config_saved or not config_saved["result"]: return config_saved path = config_saved["out"] replace_pattern = __salt__["file.blockreplace"]( path, marker_start=marker_start, marker_end=marker_end, content=content, append_if_not_found=append_if_not_found, prepend_if_not_found=prepend_if_not_found, show_changes=show_changes, append_newline=append_newline, ) with salt.utils.files.fopen(path, "r") as fh_: updated_config = fh_.read() return __salt__["net.load_config"]( text=updated_config, test=test, debug=debug, replace=replace, commit=commit ) def patch( patchfile, options="", saltenv="base", source_hash=None, show_changes=True, source="running", path=None, test=False, commit=True, debug=False, replace=True, ): """ .. versionadded:: 2019.2.0 Apply a patch to the configuration source, and load the result into the running config of the device. patchfile A patch file to apply to the configuration source. options Options to pass to patch. source_hash If the patch file (specified via the ``patchfile`` argument) is an HTTP(S) or FTP URL and the file exists in the minion's file cache, this option can be passed to keep the minion from re-downloading the file if the cached copy matches the specified hash. show_changes: ``True`` Controls how changes are presented. If ``True``, this function will return the of the changes made. If ``False``, then it will return a boolean (``True`` if any changes were made, otherwise False). source: ``running`` The configuration source. Choose from: ``running``, ``candidate``, or ``startup``. Default: ``running``. path: ``None`` Save the temporary configuration to a specific path, then read from there. This argument is optional, can the user prefers a particular location of the temporary file. test: ``False`` Dry run? If set as ``True``, will apply the config, discard and return the changes. Default: ``False`` and will commit the changes on the device. commit: ``True`` Commit the configuration changes? Default: ``True``. debug: ``False`` Debug mode. Will insert a new key in the output dictionary, as ``loaded_config`` containing the raw configuration loaded on the device. replace: ``True`` Load and replace the configuration. Default: ``True``. CLI Example: .. code-block:: bash salt '*' net.patch https://example.com/running_config.patch """ config_saved = save_config(source=source, path=path) if not config_saved or not config_saved["result"]: return config_saved path = config_saved["out"] patchfile_cache = __salt__["cp.cache_file"](patchfile) if patchfile_cache is False: return { "out": None, "result": False, "comment": 'The file "{}" does not exist.'.format(patchfile), } replace_pattern = __salt__["file.patch"](path, patchfile_cache, options=options) with salt.utils.files.fopen(path, "r") as fh_: updated_config = fh_.read() return __salt__["net.load_config"]( text=updated_config, test=test, debug=debug, replace=replace, commit=commit ) # <---- Configuration specific functions -------------------------------------------------------------------------------
Save