Linux server.edchosting.com 4.18.0-553.79.1.lve.el7h.x86_64 #1 SMP Wed Oct 15 16:34:46 UTC 2025 x86_64
LiteSpeed
Server IP : 75.98.162.185 & Your IP : 216.73.216.163
Domains :
Cant Read [ /etc/named.conf ]
User : goons4good
Terminal
Auto Root
Create File
Create Folder
Localroot Suggester
Backdoor Destroyer
Readme
/
lib /
python3.6 /
site-packages /
salt /
states /
Delete
Unzip
Name
Size
Permission
Date
Action
__pycache__
[ DIR ]
drwxr-xr-x
2022-10-11 05:09
__init__.py
25
B
-rw-r--r--
2022-05-16 09:16
acme.py
5.08
KB
-rw-r--r--
2022-05-16 09:16
alias.py
2.49
KB
-rw-r--r--
2022-05-16 09:16
alternatives.py
6.75
KB
-rw-r--r--
2022-05-16 09:16
ansiblegate.py
7.61
KB
-rw-r--r--
2022-05-16 09:16
apache.py
3.95
KB
-rw-r--r--
2022-05-16 09:16
apache_conf.py
2.72
KB
-rw-r--r--
2022-05-16 09:16
apache_module.py
2.73
KB
-rw-r--r--
2022-05-16 09:16
apache_site.py
2.66
KB
-rw-r--r--
2022-05-16 09:16
aptpkg.py
1.42
KB
-rw-r--r--
2022-05-16 09:16
archive.py
67.76
KB
-rw-r--r--
2022-05-16 09:16
artifactory.py
6.84
KB
-rw-r--r--
2022-05-16 09:16
at.py
7.54
KB
-rw-r--r--
2022-05-16 09:16
augeas.py
10.57
KB
-rw-r--r--
2022-05-16 09:16
aws_sqs.py
2.59
KB
-rw-r--r--
2022-05-16 09:16
azurearm_compute.py
10.86
KB
-rw-r--r--
2022-05-16 09:16
azurearm_dns.py
25.09
KB
-rw-r--r--
2022-05-16 09:16
azurearm_network.py
87.86
KB
-rw-r--r--
2022-05-16 09:16
azurearm_resource.py
27.22
KB
-rw-r--r--
2022-05-16 09:16
beacon.py
7.58
KB
-rw-r--r--
2022-05-16 09:16
bigip.py
96.63
KB
-rw-r--r--
2022-05-16 09:16
blockdev.py
5.13
KB
-rw-r--r--
2022-05-16 09:16
boto3_elasticache.py
48.01
KB
-rw-r--r--
2022-05-16 09:16
boto3_elasticsearch.py
32.6
KB
-rw-r--r--
2022-05-16 09:16
boto3_route53.py
37.54
KB
-rw-r--r--
2022-05-16 09:16
boto3_sns.py
12.69
KB
-rw-r--r--
2022-05-16 09:16
boto_apigateway.py
82.78
KB
-rw-r--r--
2022-05-16 09:16
boto_asg.py
31.93
KB
-rw-r--r--
2022-05-16 09:16
boto_cfn.py
11.53
KB
-rw-r--r--
2022-05-16 09:16
boto_cloudfront.py
6.01
KB
-rw-r--r--
2022-05-16 09:16
boto_cloudtrail.py
13.18
KB
-rw-r--r--
2022-05-16 09:16
boto_cloudwatch_alarm.py
6.4
KB
-rw-r--r--
2022-05-16 09:16
boto_cloudwatch_event.py
12.33
KB
-rw-r--r--
2022-05-16 09:16
boto_cognitoidentity.py
13.69
KB
-rw-r--r--
2022-05-16 09:16
boto_datapipeline.py
18.5
KB
-rw-r--r--
2022-05-16 09:16
boto_dynamodb.py
29.32
KB
-rw-r--r--
2022-05-16 09:16
boto_ec2.py
71.98
KB
-rw-r--r--
2022-05-16 09:16
boto_elasticache.py
16.75
KB
-rw-r--r--
2022-05-16 09:16
boto_elasticsearch_domain.py
12.27
KB
-rw-r--r--
2022-05-16 09:16
boto_elb.py
55.1
KB
-rw-r--r--
2022-05-16 09:16
boto_elbv2.py
12.19
KB
-rw-r--r--
2022-05-16 09:16
boto_iam.py
69.16
KB
-rw-r--r--
2022-05-16 09:16
boto_iam_role.py
27.12
KB
-rw-r--r--
2022-05-16 09:16
boto_iot.py
25.33
KB
-rw-r--r--
2022-05-16 09:16
boto_kinesis.py
16.69
KB
-rw-r--r--
2022-05-16 09:16
boto_kms.py
12.11
KB
-rw-r--r--
2022-05-16 09:16
boto_lambda.py
35.52
KB
-rw-r--r--
2022-05-16 09:16
boto_lc.py
11.04
KB
-rw-r--r--
2022-05-16 09:16
boto_rds.py
26
KB
-rw-r--r--
2022-05-16 09:16
boto_route53.py
19.38
KB
-rw-r--r--
2022-05-16 09:16
boto_s3.py
9.32
KB
-rw-r--r--
2022-05-16 09:16
boto_s3_bucket.py
24.67
KB
-rw-r--r--
2022-05-16 09:16
boto_secgroup.py
32.62
KB
-rw-r--r--
2022-05-16 09:16
boto_sns.py
8.92
KB
-rw-r--r--
2022-05-16 09:16
boto_sqs.py
7.97
KB
-rw-r--r--
2022-05-16 09:16
boto_vpc.py
61.77
KB
-rw-r--r--
2022-05-16 09:16
bower.py
8.26
KB
-rw-r--r--
2022-05-16 09:16
btrfs.py
10.31
KB
-rw-r--r--
2022-05-16 09:16
cabal.py
5.73
KB
-rw-r--r--
2022-05-16 09:16
ceph.py
1.9
KB
-rw-r--r--
2022-05-16 09:16
chef.py
3.68
KB
-rw-r--r--
2022-05-16 09:16
chocolatey.py
17.33
KB
-rw-r--r--
2022-05-16 09:16
chronos_job.py
4.6
KB
-rw-r--r--
2022-05-16 09:16
cimc.py
14.32
KB
-rw-r--r--
2022-05-16 09:16
cisconso.py
3.14
KB
-rw-r--r--
2022-05-16 09:16
cloud.py
14.4
KB
-rw-r--r--
2022-05-16 09:16
cmd.py
41.24
KB
-rw-r--r--
2022-05-16 09:16
composer.py
8.38
KB
-rw-r--r--
2022-05-16 09:16
cron.py
23.39
KB
-rw-r--r--
2022-05-16 09:16
cryptdev.py
6.17
KB
-rw-r--r--
2022-05-16 09:16
csf.py
9.98
KB
-rw-r--r--
2022-05-16 09:16
cyg.py
7.05
KB
-rw-r--r--
2022-05-16 09:16
ddns.py
4.2
KB
-rw-r--r--
2022-05-16 09:16
debconfmod.py
6.33
KB
-rw-r--r--
2022-05-16 09:16
dellchassis.py
24.49
KB
-rw-r--r--
2022-05-16 09:16
disk.py
6.49
KB
-rw-r--r--
2022-05-16 09:16
docker_container.py
85.27
KB
-rw-r--r--
2022-05-16 09:16
docker_image.py
16.38
KB
-rw-r--r--
2022-05-16 09:16
docker_network.py
36.34
KB
-rw-r--r--
2022-05-16 09:16
docker_volume.py
6.72
KB
-rw-r--r--
2022-05-16 09:16
drac.py
4.17
KB
-rw-r--r--
2022-05-16 09:16
dvs.py
26.29
KB
-rw-r--r--
2022-05-16 09:16
elasticsearch.py
20.38
KB
-rw-r--r--
2022-05-16 09:16
elasticsearch_index.py
3.25
KB
-rw-r--r--
2022-05-16 09:16
elasticsearch_index_template.py
3.67
KB
-rw-r--r--
2022-05-16 09:16
environ.py
5.81
KB
-rw-r--r--
2022-05-16 09:16
eselect.py
2.27
KB
-rw-r--r--
2022-05-16 09:16
esxcluster.py
21.16
KB
-rw-r--r--
2022-05-16 09:16
esxdatacenter.py
3.24
KB
-rw-r--r--
2022-05-16 09:16
esxi.py
61.77
KB
-rw-r--r--
2022-05-16 09:16
esxvm.py
18.86
KB
-rw-r--r--
2022-05-16 09:16
etcd_mod.py
8.36
KB
-rw-r--r--
2022-05-16 09:16
ethtool.py
7.84
KB
-rw-r--r--
2022-05-16 09:16
event.py
2.48
KB
-rw-r--r--
2022-05-16 09:16
file.py
299.79
KB
-rw-r--r--
2022-05-16 09:16
firewall.py
1.33
KB
-rw-r--r--
2022-05-16 09:16
firewalld.py
26.08
KB
-rw-r--r--
2022-05-16 09:16
gem.py
7.13
KB
-rw-r--r--
2022-05-16 09:16
git.py
124.23
KB
-rw-r--r--
2022-05-16 09:16
github.py
27.25
KB
-rw-r--r--
2022-05-16 09:16
glance_image.py
2.26
KB
-rw-r--r--
2022-05-16 09:16
glassfish.py
21.47
KB
-rw-r--r--
2022-05-16 09:16
glusterfs.py
12.12
KB
-rw-r--r--
2022-05-16 09:16
gnomedesktop.py
7.47
KB
-rw-r--r--
2022-05-16 09:16
gpg.py
5.28
KB
-rw-r--r--
2022-05-16 09:16
grafana.py
12.11
KB
-rw-r--r--
2022-05-16 09:16
grafana4_dashboard.py
17.31
KB
-rw-r--r--
2022-05-16 09:16
grafana4_datasource.py
6.15
KB
-rw-r--r--
2022-05-16 09:16
grafana4_org.py
7.73
KB
-rw-r--r--
2022-05-16 09:16
grafana4_user.py
5.52
KB
-rw-r--r--
2022-05-16 09:16
grafana_dashboard.py
17.74
KB
-rw-r--r--
2022-05-16 09:16
grafana_datasource.py
5.31
KB
-rw-r--r--
2022-05-16 09:16
grains.py
15.57
KB
-rw-r--r--
2022-05-16 09:16
group.py
9.57
KB
-rw-r--r--
2022-05-16 09:16
heat.py
9.69
KB
-rw-r--r--
2022-05-16 09:16
helm.py
10.39
KB
-rw-r--r--
2022-05-16 09:16
hg.py
6.33
KB
-rw-r--r--
2022-05-16 09:16
highstate_doc.py
1.41
KB
-rw-r--r--
2022-05-16 09:16
host.py
8.64
KB
-rw-r--r--
2022-05-16 09:16
http.py
7.43
KB
-rw-r--r--
2022-05-16 09:16
icinga2.py
9.07
KB
-rw-r--r--
2022-05-16 09:16
idem.py
3.91
KB
-rw-r--r--
2022-05-16 09:16
ifttt.py
2.12
KB
-rw-r--r--
2022-05-16 09:16
incron.py
5.71
KB
-rw-r--r--
2022-05-16 09:16
influxdb08_database.py
2.85
KB
-rw-r--r--
2022-05-16 09:16
influxdb08_user.py
3.39
KB
-rw-r--r--
2022-05-16 09:16
influxdb_continuous_query.py
2.81
KB
-rw-r--r--
2022-05-16 09:16
influxdb_database.py
2.11
KB
-rw-r--r--
2022-05-16 09:16
influxdb_retention_policy.py
4.82
KB
-rw-r--r--
2022-05-16 09:16
influxdb_user.py
4.84
KB
-rw-r--r--
2022-05-16 09:16
infoblox_a.py
4.24
KB
-rw-r--r--
2022-05-16 09:16
infoblox_cname.py
4.19
KB
-rw-r--r--
2022-05-16 09:16
infoblox_host_record.py
6.59
KB
-rw-r--r--
2022-05-16 09:16
infoblox_range.py
6.85
KB
-rw-r--r--
2022-05-16 09:16
ini_manage.py
12.67
KB
-rw-r--r--
2022-05-16 09:16
ipmi.py
8.39
KB
-rw-r--r--
2022-05-16 09:16
ipset.py
9.66
KB
-rw-r--r--
2022-05-16 09:16
iptables.py
25.96
KB
-rw-r--r--
2022-05-16 09:16
jboss7.py
23.95
KB
-rw-r--r--
2022-05-16 09:16
jenkins.py
3.36
KB
-rw-r--r--
2022-05-16 09:16
junos.py
17.78
KB
-rw-r--r--
2022-05-16 09:16
kapacitor.py
6.46
KB
-rw-r--r--
2022-05-16 09:16
kernelpkg.py
6.42
KB
-rw-r--r--
2022-05-16 09:16
keyboard.py
2.01
KB
-rw-r--r--
2022-05-16 09:16
keystone.py
27.12
KB
-rw-r--r--
2022-05-16 09:16
keystone_domain.py
2.81
KB
-rw-r--r--
2022-05-16 09:16
keystone_endpoint.py
4.69
KB
-rw-r--r--
2022-05-16 09:16
keystone_group.py
3.25
KB
-rw-r--r--
2022-05-16 09:16
keystone_project.py
3.36
KB
-rw-r--r--
2022-05-16 09:16
keystone_role.py
2.33
KB
-rw-r--r--
2022-05-16 09:16
keystone_role_grant.py
4.08
KB
-rw-r--r--
2022-05-16 09:16
keystone_service.py
2.89
KB
-rw-r--r--
2022-05-16 09:16
keystone_user.py
3.47
KB
-rw-r--r--
2022-05-16 09:16
keystore.py
5.29
KB
-rw-r--r--
2022-05-16 09:16
kmod.py
8.38
KB
-rw-r--r--
2022-05-16 09:16
kubernetes.py
24.87
KB
-rw-r--r--
2022-05-16 09:16
layman.py
2.44
KB
-rw-r--r--
2022-05-16 09:16
ldap.py
19.78
KB
-rw-r--r--
2022-05-16 09:16
libcloud_dns.py
5.7
KB
-rw-r--r--
2022-05-16 09:16
libcloud_loadbalancer.py
5.66
KB
-rw-r--r--
2022-05-16 09:16
libcloud_storage.py
5.13
KB
-rw-r--r--
2022-05-16 09:16
linux_acl.py
24.43
KB
-rw-r--r--
2022-05-16 09:16
locale.py
2.52
KB
-rw-r--r--
2022-05-16 09:16
logadm.py
4.73
KB
-rw-r--r--
2022-05-16 09:16
logrotate.py
3.86
KB
-rw-r--r--
2022-05-16 09:16
loop.py
7.74
KB
-rw-r--r--
2022-05-16 09:16
lvm.py
13.33
KB
-rw-r--r--
2022-05-16 09:16
lvs_server.py
6.28
KB
-rw-r--r--
2022-05-16 09:16
lvs_service.py
4.38
KB
-rw-r--r--
2022-05-16 09:16
lxc.py
22.17
KB
-rw-r--r--
2022-05-16 09:16
lxd.py
7.88
KB
-rw-r--r--
2022-05-16 09:16
lxd_container.py
22.25
KB
-rw-r--r--
2022-05-16 09:16
lxd_image.py
10.59
KB
-rw-r--r--
2022-05-16 09:16
lxd_profile.py
7.11
KB
-rw-r--r--
2022-05-16 09:16
mac_assistive.py
1.59
KB
-rw-r--r--
2022-05-16 09:16
mac_keychain.py
5.59
KB
-rw-r--r--
2022-05-16 09:16
mac_xattr.py
3.15
KB
-rw-r--r--
2022-05-16 09:16
macdefaults.py
2.65
KB
-rw-r--r--
2022-05-16 09:16
macpackage.py
6.76
KB
-rw-r--r--
2022-05-16 09:16
makeconf.py
6.87
KB
-rw-r--r--
2022-05-16 09:16
marathon_app.py
4.45
KB
-rw-r--r--
2022-05-16 09:16
mdadm_raid.py
6.41
KB
-rw-r--r--
2022-05-16 09:16
memcached.py
3.95
KB
-rw-r--r--
2022-05-16 09:16
modjk.py
2.84
KB
-rw-r--r--
2022-05-16 09:16
modjk_worker.py
6.49
KB
-rw-r--r--
2022-05-16 09:16
module.py
17.99
KB
-rw-r--r--
2022-05-16 09:16
mongodb_database.py
1.65
KB
-rw-r--r--
2022-05-16 09:16
mongodb_user.py
6.26
KB
-rw-r--r--
2022-05-16 09:16
monit.py
2.68
KB
-rw-r--r--
2022-05-16 09:16
mount.py
49.55
KB
-rw-r--r--
2022-05-16 09:16
mssql_database.py
3
KB
-rw-r--r--
2022-05-16 09:16
mssql_login.py
3.64
KB
-rw-r--r--
2022-05-16 09:16
mssql_role.py
2.37
KB
-rw-r--r--
2022-05-16 09:16
mssql_user.py
3.51
KB
-rw-r--r--
2022-05-16 09:16
msteams.py
2.53
KB
-rw-r--r--
2022-05-16 09:16
mysql_database.py
6.05
KB
-rw-r--r--
2022-05-16 09:16
mysql_grants.py
8.49
KB
-rw-r--r--
2022-05-16 09:16
mysql_query.py
13.07
KB
-rw-r--r--
2022-05-16 09:16
mysql_user.py
9.51
KB
-rw-r--r--
2022-05-16 09:16
net_napalm_yang.py
9.15
KB
-rw-r--r--
2022-05-16 09:16
netacl.py
31.92
KB
-rw-r--r--
2022-05-16 09:16
netconfig.py
33.42
KB
-rw-r--r--
2022-05-16 09:16
netntp.py
12.48
KB
-rw-r--r--
2022-05-16 09:16
netsnmp.py
11.33
KB
-rw-r--r--
2022-05-16 09:16
netusers.py
16.1
KB
-rw-r--r--
2022-05-16 09:16
network.py
23.7
KB
-rw-r--r--
2022-05-16 09:16
neutron_network.py
3.96
KB
-rw-r--r--
2022-05-16 09:16
neutron_secgroup.py
4
KB
-rw-r--r--
2022-05-16 09:16
neutron_secgroup_rule.py
4.75
KB
-rw-r--r--
2022-05-16 09:16
neutron_subnet.py
4.29
KB
-rw-r--r--
2022-05-16 09:16
nexus.py
4.97
KB
-rw-r--r--
2022-05-16 09:16
nfs_export.py
4.92
KB
-rw-r--r--
2022-05-16 09:16
nftables.py
19.5
KB
-rw-r--r--
2022-05-16 09:16
npm.py
11.21
KB
-rw-r--r--
2022-05-16 09:16
ntp.py
2.12
KB
-rw-r--r--
2022-05-16 09:16
nxos.py
10.67
KB
-rw-r--r--
2022-05-16 09:16
nxos_upgrade.py
3.5
KB
-rw-r--r--
2022-05-16 09:16
openstack_config.py
3.26
KB
-rw-r--r--
2022-05-16 09:16
openvswitch_bridge.py
3.13
KB
-rw-r--r--
2022-05-16 09:16
openvswitch_port.py
17.25
KB
-rw-r--r--
2022-05-16 09:16
opsgenie.py
4.07
KB
-rw-r--r--
2022-05-16 09:16
pagerduty.py
1.89
KB
-rw-r--r--
2022-05-16 09:16
pagerduty_escalation_policy.py
5.42
KB
-rw-r--r--
2022-05-16 09:16
pagerduty_schedule.py
6.09
KB
-rw-r--r--
2022-05-16 09:16
pagerduty_service.py
3.93
KB
-rw-r--r--
2022-05-16 09:16
pagerduty_user.py
1.18
KB
-rw-r--r--
2022-05-16 09:16
panos.py
48.13
KB
-rw-r--r--
2022-05-16 09:16
pbm.py
20.46
KB
-rw-r--r--
2022-05-16 09:16
pcs.py
36.46
KB
-rw-r--r--
2022-05-16 09:16
pdbedit.py
3.48
KB
-rw-r--r--
2022-05-16 09:16
pecl.py
3.65
KB
-rw-r--r--
2022-05-16 09:16
pip_state.py
37.55
KB
-rw-r--r--
2022-05-16 09:16
pkg.py
127.05
KB
-rw-r--r--
2022-05-16 09:16
pkgbuild.py
11.37
KB
-rw-r--r--
2022-05-16 09:16
pkgng.py
685
B
-rw-r--r--
2022-05-16 09:16
pkgrepo.py
23.59
KB
-rw-r--r--
2022-05-16 09:16
portage_config.py
5.01
KB
-rw-r--r--
2022-05-16 09:16
ports.py
5.65
KB
-rw-r--r--
2022-05-16 09:16
postgres_cluster.py
4.19
KB
-rw-r--r--
2022-05-16 09:16
postgres_database.py
6.08
KB
-rw-r--r--
2022-05-16 09:16
postgres_extension.py
5.68
KB
-rw-r--r--
2022-05-16 09:16
postgres_group.py
8.52
KB
-rw-r--r--
2022-05-16 09:16
postgres_initdb.py
2.84
KB
-rw-r--r--
2022-05-16 09:16
postgres_language.py
3.94
KB
-rw-r--r--
2022-05-16 09:16
postgres_privileges.py
7.86
KB
-rw-r--r--
2022-05-16 09:16
postgres_schema.py
4.34
KB
-rw-r--r--
2022-05-16 09:16
postgres_tablespace.py
6.62
KB
-rw-r--r--
2022-05-16 09:16
postgres_user.py
9.49
KB
-rw-r--r--
2022-05-16 09:16
powerpath.py
2.34
KB
-rw-r--r--
2022-05-16 09:16
probes.py
15.06
KB
-rw-r--r--
2022-05-16 09:16
process.py
1.32
KB
-rw-r--r--
2022-05-16 09:16
proxy.py
4.94
KB
-rw-r--r--
2022-05-16 09:16
pushover.py
3.13
KB
-rw-r--r--
2022-05-16 09:16
pyenv.py
6.07
KB
-rw-r--r--
2022-05-16 09:16
pyrax_queues.py
2.97
KB
-rw-r--r--
2022-05-16 09:16
quota.py
1.4
KB
-rw-r--r--
2022-05-16 09:16
rabbitmq_cluster.py
1.84
KB
-rw-r--r--
2022-05-16 09:16
rabbitmq_plugin.py
2.77
KB
-rw-r--r--
2022-05-16 09:16
rabbitmq_policy.py
4.58
KB
-rw-r--r--
2022-05-16 09:16
rabbitmq_upstream.py
7.9
KB
-rw-r--r--
2022-05-16 09:16
rabbitmq_user.py
8.89
KB
-rw-r--r--
2022-05-16 09:16
rabbitmq_vhost.py
3.04
KB
-rw-r--r--
2022-05-16 09:16
rbac_solaris.py
6.67
KB
-rw-r--r--
2022-05-16 09:16
rbenv.py
7.36
KB
-rw-r--r--
2022-05-16 09:16
rdp.py
1.28
KB
-rw-r--r--
2022-05-16 09:16
redismod.py
4.76
KB
-rw-r--r--
2022-05-16 09:16
reg.py
19.22
KB
-rw-r--r--
2022-05-16 09:16
rsync.py
4.45
KB
-rw-r--r--
2022-05-16 09:16
rvm.py
6.56
KB
-rw-r--r--
2022-05-16 09:16
salt_proxy.py
1.34
KB
-rw-r--r--
2022-05-16 09:16
saltmod.py
30.88
KB
-rw-r--r--
2022-05-16 09:16
saltutil.py
8.91
KB
-rw-r--r--
2022-05-16 09:16
schedule.py
11.89
KB
-rw-r--r--
2022-05-16 09:16
selinux.py
18.61
KB
-rw-r--r--
2022-05-16 09:16
serverdensity_device.py
6.41
KB
-rw-r--r--
2022-05-16 09:16
service.py
37.06
KB
-rw-r--r--
2022-05-16 09:16
slack.py
4.98
KB
-rw-r--r--
2022-05-16 09:16
smartos.py
44.89
KB
-rw-r--r--
2022-05-16 09:16
smtp.py
2.3
KB
-rw-r--r--
2022-05-16 09:16
snapper.py
7.24
KB
-rw-r--r--
2022-05-16 09:16
solrcloud.py
4.48
KB
-rw-r--r--
2022-05-16 09:16
splunk.py
4.32
KB
-rw-r--r--
2022-05-16 09:16
splunk_search.py
3.17
KB
-rw-r--r--
2022-05-16 09:16
sqlite3.py
14.7
KB
-rw-r--r--
2022-05-16 09:16
ssh_auth.py
19.1
KB
-rw-r--r--
2022-05-16 09:16
ssh_known_hosts.py
7.87
KB
-rw-r--r--
2022-05-16 09:16
stateconf.py
494
B
-rw-r--r--
2022-05-16 09:16
status.py
2.21
KB
-rw-r--r--
2022-05-16 09:16
statuspage.py
17.29
KB
-rw-r--r--
2022-05-16 09:16
supervisord.py
10.48
KB
-rw-r--r--
2022-05-16 09:16
svn.py
8.14
KB
-rw-r--r--
2022-05-16 09:16
sysctl.py
3.82
KB
-rw-r--r--
2022-05-16 09:16
syslog_ng.py
2.97
KB
-rw-r--r--
2022-05-16 09:16
sysrc.py
2.82
KB
-rw-r--r--
2022-05-16 09:16
telemetry_alert.py
7.04
KB
-rw-r--r--
2022-05-16 09:16
test.py
13.09
KB
-rw-r--r--
2022-05-16 09:16
testinframod.py
1.35
KB
-rw-r--r--
2022-05-16 09:16
timezone.py
3.42
KB
-rw-r--r--
2022-05-16 09:16
tls.py
1.81
KB
-rw-r--r--
2022-05-16 09:16
tomcat.py
9.72
KB
-rw-r--r--
2022-05-16 09:16
trafficserver.py
8.82
KB
-rw-r--r--
2022-05-16 09:16
tuned.py
3.32
KB
-rw-r--r--
2022-05-16 09:16
uptime.py
1.87
KB
-rw-r--r--
2022-05-16 09:16
user.py
35.43
KB
-rw-r--r--
2022-05-16 09:16
vagrant.py
11.4
KB
-rw-r--r--
2022-05-16 09:16
vault.py
3.28
KB
-rw-r--r--
2022-05-16 09:16
vbox_guest.py
4.05
KB
-rw-r--r--
2022-05-16 09:16
victorops.py
3.32
KB
-rw-r--r--
2022-05-16 09:16
virt.py
80.06
KB
-rw-r--r--
2022-05-16 09:16
virtualenv_mod.py
11.21
KB
-rw-r--r--
2022-05-16 09:16
webutil.py
3.78
KB
-rw-r--r--
2022-05-16 09:16
win_certutil.py
2.88
KB
-rw-r--r--
2022-05-16 09:16
win_dacl.py
7.96
KB
-rw-r--r--
2022-05-16 09:16
win_dism.py
13.02
KB
-rw-r--r--
2022-05-16 09:16
win_dns_client.py
8.32
KB
-rw-r--r--
2022-05-16 09:16
win_firewall.py
6.87
KB
-rw-r--r--
2022-05-16 09:16
win_iis.py
31.56
KB
-rw-r--r--
2022-05-16 09:16
win_lgpo.py
25.41
KB
-rw-r--r--
2022-05-16 09:16
win_license.py
1.6
KB
-rw-r--r--
2022-05-16 09:16
win_network.py
14.18
KB
-rw-r--r--
2022-05-16 09:16
win_path.py
6.39
KB
-rw-r--r--
2022-05-16 09:16
win_pki.py
5.56
KB
-rw-r--r--
2022-05-16 09:16
win_powercfg.py
3.79
KB
-rw-r--r--
2022-05-16 09:16
win_servermanager.py
10.4
KB
-rw-r--r--
2022-05-16 09:16
win_smtp_server.py
10.01
KB
-rw-r--r--
2022-05-16 09:16
win_snmp.py
6.64
KB
-rw-r--r--
2022-05-16 09:16
win_system.py
13.78
KB
-rw-r--r--
2022-05-16 09:16
win_wua.py
14.47
KB
-rw-r--r--
2022-05-16 09:16
win_wusa.py
3.53
KB
-rw-r--r--
2022-05-16 09:16
winrepo.py
2.74
KB
-rw-r--r--
2022-05-16 09:16
wordpress.py
4.82
KB
-rw-r--r--
2022-05-16 09:16
x509.py
26.98
KB
-rw-r--r--
2022-05-16 09:16
xml.py
1.75
KB
-rw-r--r--
2022-05-16 09:16
xmpp.py
2.61
KB
-rw-r--r--
2022-05-16 09:16
zabbix_action.py
9.35
KB
-rw-r--r--
2022-05-16 09:16
zabbix_host.py
27.25
KB
-rw-r--r--
2022-05-16 09:16
zabbix_hostgroup.py
5.64
KB
-rw-r--r--
2022-05-16 09:16
zabbix_mediatype.py
16.89
KB
-rw-r--r--
2022-05-16 09:16
zabbix_template.py
35.14
KB
-rw-r--r--
2022-05-16 09:16
zabbix_user.py
15.76
KB
-rw-r--r--
2022-05-16 09:16
zabbix_usergroup.py
9.64
KB
-rw-r--r--
2022-05-16 09:16
zabbix_usermacro.py
9.69
KB
-rw-r--r--
2022-05-16 09:16
zabbix_valuemap.py
8.11
KB
-rw-r--r--
2022-05-16 09:16
zcbuildout.py
5.16
KB
-rw-r--r--
2022-05-16 09:16
zenoss.py
2.89
KB
-rw-r--r--
2022-05-16 09:16
zfs.py
34.27
KB
-rw-r--r--
2022-05-16 09:16
zk_concurrency.py
5.81
KB
-rw-r--r--
2022-05-16 09:16
zone.py
46.49
KB
-rw-r--r--
2022-05-16 09:16
zookeeper.py
11.53
KB
-rw-r--r--
2022-05-16 09:16
zpool.py
13.08
KB
-rw-r--r--
2022-05-16 09:16
Save
Rename
""" Management of SmartOS Standalone Compute Nodes :maintainer: Jorge Schrauwen <sjorge@blackdot.be> :maturity: new :depends: vmadm, imgadm :platform: smartos .. versionadded:: 2016.3.0 .. code-block:: yaml vmtest.example.org: smartos.vm_present: - config: reprovision: true - vmconfig: image_uuid: c02a2044-c1bd-11e4-bd8c-dfc1db8b0182 brand: joyent alias: vmtest quota: 5 max_physical_memory: 512 tags: label: 'test vm' owner: 'sjorge' nics: "82:1b:8e:49:e9:12": nic_tag: trunk mtu: 1500 ips: - 172.16.1.123/16 - 192.168.2.123/24 vlan_id: 10 "82:1b:8e:49:e9:13": nic_tag: trunk mtu: 1500 ips: - dhcp vlan_id: 30 filesystems: "/bigdata": source: "/bulk/data" type: lofs options: - ro - nodevices kvmtest.example.org: smartos.vm_present: - vmconfig: brand: kvm alias: kvmtest cpu_type: host ram: 512 vnc_port: 9 tags: label: 'test kvm' owner: 'sjorge' disks: disk0: size: 2048 model: virtio compression: lz4 boot: true nics: "82:1b:8e:49:e9:15": nic_tag: trunk mtu: 1500 ips: - dhcp vlan_id: 30 docker.example.org: smartos.vm_present: - config: auto_import: true reprovision: true - vmconfig: image_uuid: emby/embyserver:latest brand: lx alias: mydockervm quota: 5 max_physical_memory: 1024 tags: label: 'my emby docker' owner: 'sjorge' resolvers: - 172.16.1.1 nics: "82:1b:8e:49:e9:18": nic_tag: trunk mtu: 1500 ips: - 172.16.1.118/24 vlan_id: 10 filesystems: "/config: source: "/vmdata/emby_config" type: lofs options: - nodevices cleanup_images: smartos.image_vacuum .. note:: Keep in mind that when removing properties from vmconfig they will not get removed from the vm's current configuration, except for nics, disk, tags, ... they get removed via add_*, set_*, update_*, and remove_*. Properties must be manually reset to their default value. The same behavior as when using 'vmadm update'. .. warning:: For HVM (bhyve and KVM) brands the `image_uuid` field should go on the boot disks, this disk should NOT have a size specified. (See man vmadm) """ import json import logging import os import salt.utils.atomicfile import salt.utils.data import salt.utils.files log = logging.getLogger(__name__) # Define the state's virtual name __virtualname__ = "smartos" def __virtual__(): """ Provides smartos state provided for SmartOS """ if "vmadm.create" in __salt__ and "imgadm.list" in __salt__: return True else: return ( False, "{} state module can only be loaded on SmartOS compute nodes".format( __virtualname__ ), ) def _split_docker_uuid(uuid): """ Split a smartos docker uuid into repo and tag """ if uuid: uuid = uuid.split(":") if len(uuid) == 2: tag = uuid[1] repo = uuid[0] return repo, tag return None, None def _is_uuid(uuid): """ Check if uuid is a valid smartos uuid Example: e69a0918-055d-11e5-8912-e3ceb6df4cf8 """ if uuid and list(len(x) for x in uuid.split("-")) == [8, 4, 4, 4, 12]: return True return False def _is_docker_uuid(uuid): """ Check if uuid is a valid smartos docker uuid Example plexinc/pms-docker:plexpass """ repo, tag = _split_docker_uuid(uuid) return not (not repo and not tag) def _load_config(): """ Loads and parses /usbkey/config """ config = {} if os.path.isfile("/usbkey/config"): with salt.utils.files.fopen("/usbkey/config", "r") as config_file: for optval in config_file: optval = salt.utils.stringutils.to_unicode(optval) if optval[0] == "#": continue if "=" not in optval: continue optval = optval.split("=") config[optval[0].lower()] = optval[1].strip().strip('"') log.debug("smartos.config - read /usbkey/config: %s", config) return config def _write_config(config): """ writes /usbkey/config """ try: with salt.utils.atomicfile.atomic_open("/usbkey/config", "w") as config_file: config_file.write("#\n# This file was generated by salt\n#\n") for prop in salt.utils.odict.OrderedDict(sorted(config.items())): if " " in str(config[prop]): if not config[prop].startswith('"') or not config[prop].endswith( '"' ): config[prop] = '"{}"'.format(config[prop]) config_file.write( salt.utils.stringutils.to_str("{}={}\n".format(prop, config[prop])) ) log.debug("smartos.config - wrote /usbkey/config: %s", config) except OSError: return False return True def _parse_vmconfig(config, instances): """ Parse vm_present vm config """ vmconfig = None if isinstance(config, (salt.utils.odict.OrderedDict)): vmconfig = salt.utils.odict.OrderedDict() for prop in config: if prop not in instances: vmconfig[prop] = config[prop] else: if not isinstance(config[prop], (salt.utils.odict.OrderedDict)): continue vmconfig[prop] = [] for instance in config[prop]: instance_config = config[prop][instance] instance_config[instances[prop]] = instance ## some property are lowercase if "mac" in instance_config: instance_config["mac"] = instance_config["mac"].lower() ## calculate mac from vrrp_vrid if "vrrp_vrid" in instance_config: instance_config["mac"] = "00:00:5e:00:01:{}".format( hex(int(instance_config["vrrp_vrid"])) .split("x")[-1] .zfill(2), ) vmconfig[prop].append(instance_config) else: log.error("smartos.vm_present::parse_vmconfig - failed to parse") return vmconfig def _get_instance_changes(current, state): """ get modified properties """ # get keys current_keys = set(current.keys()) state_keys = set(state.keys()) # compare configs changed = salt.utils.data.compare_dicts(current, state) for change in salt.utils.data.compare_dicts(current, state): if change in changed and changed[change]["old"] == "": del changed[change] if change in changed and changed[change]["new"] == "": del changed[change] return changed def _copy_lx_vars(vmconfig): # NOTE: documentation on dockerinit: https://github.com/joyent/smartos-live/blob/master/src/dockerinit/README.md if "image_uuid" in vmconfig: # NOTE: retrieve tags and type from image imgconfig = __salt__["imgadm.get"](vmconfig["image_uuid"]).get("manifest", {}) imgtype = imgconfig.get("type", "zone-dataset") imgtags = imgconfig.get("tags", {}) # NOTE: copy kernel_version (if not specified in vmconfig) if "kernel_version" not in vmconfig and "kernel_version" in imgtags: vmconfig["kernel_version"] = imgtags["kernel_version"] # NOTE: copy docker vars if imgtype == "docker": vmconfig["docker"] = True vmconfig["kernel_version"] = vmconfig.get("kernel_version", "4.3.0") if "internal_metadata" not in vmconfig: vmconfig["internal_metadata"] = {} for var in imgtags.get("docker:config", {}): val = imgtags["docker:config"][var] var = "docker:{}".format(var.lower()) # NOTE: skip empty values if not val: continue # NOTE: skip or merge user values if var == "docker:env": try: val_config = json.loads( vmconfig["internal_metadata"].get(var, "") ) except ValueError as e: val_config = [] for config_env_var in ( val_config if isinstance(val_config, list) else json.loads(val_config) ): config_env_var = config_env_var.split("=") for img_env_var in val: if img_env_var.startswith("{}=".format(config_env_var[0])): val.remove(img_env_var) val.append("=".join(config_env_var)) elif var in vmconfig["internal_metadata"]: continue if isinstance(val, list): # NOTE: string-encoded JSON arrays vmconfig["internal_metadata"][var] = json.dumps(val) else: vmconfig["internal_metadata"][var] = val return vmconfig def config_present(name, value): """ Ensure configuration property is set to value in /usbkey/config name : string name of property value : string value of property """ name = name.lower() ret = {"name": name, "changes": {}, "result": None, "comment": ""} # load confiration config = _load_config() # handle bool and None value if isinstance(value, (bool)): value = "true" if value else "false" if not value: value = "" if name in config: if str(config[name]) == str(value): # we're good ret["result"] = True ret["comment"] = 'property {} already has value "{}"'.format(name, value) else: # update property ret["result"] = True ret["comment"] = 'updated property {} with value "{}"'.format(name, value) ret["changes"][name] = value config[name] = value else: # add property ret["result"] = True ret["comment"] = 'added property {} with value "{}"'.format(name, value) ret["changes"][name] = value config[name] = value # apply change if needed if not __opts__["test"] and ret["changes"]: ret["result"] = _write_config(config) if not ret["result"]: ret[ "comment" ] = 'Could not add property {} with value "{}" to config'.format( name, value ) return ret def config_absent(name): """ Ensure configuration property is absent in /usbkey/config name : string name of property """ name = name.lower() ret = {"name": name, "changes": {}, "result": None, "comment": ""} # load configuration config = _load_config() if name in config: # delete property ret["result"] = True ret["comment"] = "property {} deleted".format(name) ret["changes"][name] = None del config[name] else: # we're good ret["result"] = True ret["comment"] = "property {} is absent".format(name) # apply change if needed if not __opts__["test"] and ret["changes"]: ret["result"] = _write_config(config) return ret def source_present(name, source_type="imgapi"): """ Ensure an image source is present on the computenode name : string source url source_type : string source type (imgapi or docker) """ ret = {"name": name, "changes": {}, "result": None, "comment": ""} if name in __salt__["imgadm.sources"](): # source is present ret["result"] = True ret["comment"] = "image source {} is present".format(name) else: # add new source if __opts__["test"]: res = {} ret["result"] = True else: res = __salt__["imgadm.source_add"](name, source_type) ret["result"] = name in res if ret["result"]: ret["comment"] = "image source {} added".format(name) ret["changes"][name] = "added" else: ret["comment"] = "image source {} not added".format(name) if "Error" in res: ret["comment"] = "{}: {}".format(ret["comment"], res["Error"]) return ret def source_absent(name): """ Ensure an image source is absent on the computenode name : string source url """ ret = {"name": name, "changes": {}, "result": None, "comment": ""} if name not in __salt__["imgadm.sources"](): # source is absent ret["result"] = True ret["comment"] = "image source {} is absent".format(name) else: # remove source if __opts__["test"]: res = {} ret["result"] = True else: res = __salt__["imgadm.source_delete"](name) ret["result"] = name not in res if ret["result"]: ret["comment"] = "image source {} deleted".format(name) ret["changes"][name] = "deleted" else: ret["comment"] = "image source {} not deleted".format(name) if "Error" in res: ret["comment"] = "{}: {}".format(ret["comment"], res["Error"]) return ret def image_present(name): """ Ensure image is present on the computenode name : string uuid of image """ ret = {"name": name, "changes": {}, "result": None, "comment": ""} if _is_docker_uuid(name) and __salt__["imgadm.docker_to_uuid"](name): # docker image was imported ret["result"] = True ret["comment"] = "image {} ({}) is present".format( name, __salt__["imgadm.docker_to_uuid"](name), ) elif name in __salt__["imgadm.list"](): # image was already imported ret["result"] = True ret["comment"] = "image {} is present".format(name) else: # add image if _is_docker_uuid(name): # NOTE: we cannot query available docker images available_images = [name] else: available_images = __salt__["imgadm.avail"]() if name in available_images: if __opts__["test"]: ret["result"] = True res = {} if _is_docker_uuid(name): res["00000000-0000-0000-0000-000000000000"] = name else: res[name] = available_images[name] else: res = __salt__["imgadm.import"](name) if _is_uuid(name): ret["result"] = name in res elif _is_docker_uuid(name): ret["result"] = __salt__["imgadm.docker_to_uuid"](name) is not None if ret["result"]: ret["comment"] = "image {} imported".format(name) ret["changes"] = res else: ret["comment"] = "image {} was unable to be imported".format(name) else: ret["result"] = False ret["comment"] = "image {} does not exists".format(name) return ret def image_absent(name): """ Ensure image is absent on the computenode name : string uuid of image .. note:: computenode.image_absent will only remove the image if it is not used by a vm. """ ret = {"name": name, "changes": {}, "result": None, "comment": ""} uuid = None if _is_uuid(name): uuid = name if _is_docker_uuid(name): uuid = __salt__["imgadm.docker_to_uuid"](name) if not uuid or uuid not in __salt__["imgadm.list"](): # image not imported ret["result"] = True ret["comment"] = "image {} is absent".format(name) else: # check if image in use by vm if uuid in __salt__["vmadm.list"](order="image_uuid"): ret["result"] = False ret["comment"] = "image {} currently in use by a vm".format(name) else: # delete image if __opts__["test"]: ret["result"] = True else: image = __salt__["imgadm.get"](uuid) image_count = 0 if image["manifest"]["name"] == "docker-layer": # NOTE: docker images are made of multiple layers, loop over them while image: image_count += 1 __salt__["imgadm.delete"](image["manifest"]["uuid"]) if "origin" in image["manifest"]: image = __salt__["imgadm.get"](image["manifest"]["origin"]) else: image = None else: # NOTE: normal images can just be delete __salt__["imgadm.delete"](uuid) ret["result"] = uuid not in __salt__["imgadm.list"]() if image_count: ret["comment"] = "image {} and {} children deleted".format( name, image_count ) else: ret["comment"] = "image {} deleted".format(name) ret["changes"][name] = None return ret def image_vacuum(name): """ Delete images not in use or installed via image_present .. warning:: Only image_present states that are included via the top file will be detected. """ name = name.lower() ret = {"name": name, "changes": {}, "result": None, "comment": ""} # list of images to keep images = [] # retrieve image_present state data for host for state in __salt__["state.show_lowstate"](): # don't throw exceptions when not highstate run if "state" not in state: continue # skip if not from this state module if state["state"] != __virtualname__: continue # skip if not image_present if state["fun"] not in ["image_present"]: continue # keep images installed via image_present if "name" in state: if _is_uuid(state["name"]): images.append(state["name"]) elif _is_docker_uuid(state["name"]): state["name"] = __salt__["imgadm.docker_to_uuid"](state["name"]) if not state["name"]: continue images.append(state["name"]) # retrieve images in use by vms for image_uuid in __salt__["vmadm.list"](order="image_uuid"): if image_uuid not in images: images.append(image_uuid) # purge unused images ret["result"] = True for image_uuid in __salt__["imgadm.list"](): if image_uuid in images: continue image = __salt__["imgadm.get"](image_uuid) if image["manifest"]["name"] == "docker-layer": # NOTE: docker images are made of multiple layers, loop over them while image: image_uuid = image["manifest"]["uuid"] if image_uuid in __salt__["imgadm.delete"](image_uuid): ret["changes"][image_uuid] = None else: ret["result"] = False ret["comment"] = "failed to delete images" if "origin" in image["manifest"]: image = __salt__["imgadm.get"](image["manifest"]["origin"]) else: image = None else: # NOTE: normal images can just be delete if image_uuid in __salt__["imgadm.delete"](image_uuid): ret["changes"][image_uuid] = None else: ret["result"] = False ret["comment"] = "failed to delete images" if ret["result"] and not ret["changes"]: ret["comment"] = "no images deleted" elif ret["result"] and ret["changes"]: ret["comment"] = "images deleted" return ret def vm_present(name, vmconfig, config=None): """ Ensure vm is present on the computenode name : string hostname of vm vmconfig : dict options to set for the vm config : dict fine grain control over vm_present .. note:: The following configuration properties can be toggled in the config parameter. - kvm_reboot (true) - reboots of kvm zones if needed for a config update - auto_import (false) - automatic importing of missing images - auto_lx_vars (true) - copy kernel_version and docker:* variables from image - reprovision (false) - reprovision on image_uuid changes - enforce_tags (true) - false = add tags only, true = add, update, and remove tags - enforce_routes (true) - false = add tags only, true = add, update, and remove routes - enforce_internal_metadata (true) - false = add metadata only, true = add, update, and remove metadata - enforce_customer_metadata (true) - false = add metadata only, true = add, update, and remove metadata .. note:: State ID is used as hostname. Hostnames must be unique. .. note:: If hostname is provided in vmconfig this will take president over the State ID. This allows multiple states to be applied to the same vm. .. note:: The following instances should have a unique ID. - nic : mac - filesystem: target - disk : path or diskN for zvols e.g. disk0 will be the first disk added, disk1 the 2nd,... .. versionchanged:: 2019.2.0 Added support for docker image uuids, added auto_lx_vars configuration, documented some missing configuration options. """ name = name.lower() ret = {"name": name, "changes": {}, "result": None, "comment": ""} # config defaults state_config = config if config else {} config = { "kvm_reboot": True, "auto_import": False, "auto_lx_vars": True, "reprovision": False, "enforce_tags": True, "enforce_routes": True, "enforce_internal_metadata": True, "enforce_customer_metadata": True, } config.update(state_config) log.debug("smartos.vm_present::%s::config - %s", name, config) # map special vmconfig parameters # collections have set/remove handlers # instances have add/update/remove handlers and a unique id vmconfig_type = { "collection": ["tags", "customer_metadata", "internal_metadata", "routes"], "instance": { "nics": "mac", "disks": "path", "filesystems": "target", "pci_devices": "path", }, "create_only": ["filesystems"], } vmconfig_docker_keep = [ "docker:id", "docker:restartcount", ] vmconfig_docker_array = [ "docker:env", "docker:cmd", "docker:entrypoint", ] # parse vmconfig vmconfig = _parse_vmconfig(vmconfig, vmconfig_type["instance"]) log.debug("smartos.vm_present::%s::vmconfig - %s", name, vmconfig) # set hostname if needed if "hostname" not in vmconfig: vmconfig["hostname"] = name # prepare image_uuid if "image_uuid" in vmconfig: # NOTE: lookup uuid from docker uuid (normal uuid's are passed throuhg unmodified) # we must do this again if we end up importing a missing image later! docker_uuid = __salt__["imgadm.docker_to_uuid"](vmconfig["image_uuid"]) vmconfig["image_uuid"] = docker_uuid if docker_uuid else vmconfig["image_uuid"] # NOTE: import image (if missing and allowed) if vmconfig["image_uuid"] not in __salt__["imgadm.list"](): if config["auto_import"]: if not __opts__["test"]: res = __salt__["imgadm.import"](vmconfig["image_uuid"]) vmconfig["image_uuid"] = __salt__["imgadm.docker_to_uuid"]( vmconfig["image_uuid"] ) if vmconfig["image_uuid"] not in res: ret["result"] = False ret["comment"] = "failed to import image {}".format( vmconfig["image_uuid"] ) else: ret["result"] = False ret["comment"] = "image {} not installed".format(vmconfig["image_uuid"]) # prepare disk.*.image_uuid for disk in vmconfig["disks"] if "disks" in vmconfig else []: if "image_uuid" in disk and disk["image_uuid"] not in __salt__["imgadm.list"](): if config["auto_import"]: if not __opts__["test"]: res = __salt__["imgadm.import"](disk["image_uuid"]) if disk["image_uuid"] not in res: ret["result"] = False ret["comment"] = "failed to import image {}".format( disk["image_uuid"] ) else: ret["result"] = False ret["comment"] = "image {} not installed".format(disk["image_uuid"]) # docker json-array handling if "internal_metadata" in vmconfig: for var in vmconfig_docker_array: if var not in vmconfig["internal_metadata"]: continue if isinstance(vmconfig["internal_metadata"][var], list): vmconfig["internal_metadata"][var] = json.dumps( vmconfig["internal_metadata"][var] ) # copy lx variables if vmconfig["brand"] == "lx" and config["auto_lx_vars"]: # NOTE: we can only copy the lx vars after the image has bene imported vmconfig = _copy_lx_vars(vmconfig) # quick abort if things look wrong # NOTE: use explicit check for false, otherwise None also matches! if ret["result"] is False: return ret # check if vm exists if vmconfig["hostname"] in __salt__["vmadm.list"](order="hostname"): # update vm ret["result"] = True # expand vmconfig vmconfig = { "state": vmconfig, "current": __salt__["vmadm.get"](vmconfig["hostname"], key="hostname"), "changed": {}, "reprovision_uuid": None, } # prepare reprovision if "image_uuid" in vmconfig["state"]: vmconfig["reprovision_uuid"] = vmconfig["state"]["image_uuid"] vmconfig["state"]["image_uuid"] = vmconfig["current"]["image_uuid"] # disks need some special care if "disks" in vmconfig["state"]: new_disks = [] for disk in vmconfig["state"]["disks"]: path = False if "disks" in vmconfig["current"]: for cdisk in vmconfig["current"]["disks"]: if cdisk["path"].endswith(disk["path"]): path = cdisk["path"] break if not path: del disk["path"] else: disk["path"] = path new_disks.append(disk) vmconfig["state"]["disks"] = new_disks # process properties for prop in vmconfig["state"]: # skip special vmconfig_types if ( prop in vmconfig_type["instance"] or prop in vmconfig_type["collection"] or prop in vmconfig_type["create_only"] ): continue # skip unchanged properties if prop in vmconfig["current"]: if isinstance(vmconfig["current"][prop], (list)) or isinstance( vmconfig["current"][prop], (dict) ): if vmconfig["current"][prop] == vmconfig["state"][prop]: continue else: if "{}".format(vmconfig["current"][prop]) == "{}".format( vmconfig["state"][prop] ): continue # add property to changeset vmconfig["changed"][prop] = vmconfig["state"][prop] # process collections for collection in vmconfig_type["collection"]: # skip create only collections if collection in vmconfig_type["create_only"]: continue # enforcement enforce = config["enforce_{}".format(collection)] log.debug("smartos.vm_present::enforce_%s = %s", collection, enforce) # dockerinit handling if collection == "internal_metadata" and vmconfig["state"].get( "docker", False ): if "internal_metadata" not in vmconfig["state"]: vmconfig["state"]["internal_metadata"] = {} # preserve some docker specific metadata (added and needed by dockerinit) for var in vmconfig_docker_keep: val = vmconfig["current"].get(collection, {}).get(var, None) if val is not None: vmconfig["state"]["internal_metadata"][var] = val # process add and update for collection if ( collection in vmconfig["state"] and vmconfig["state"][collection] is not None ): for prop in vmconfig["state"][collection]: # skip unchanged properties if ( prop in vmconfig["current"][collection] and vmconfig["current"][collection][prop] == vmconfig["state"][collection][prop] ): continue # skip update if not enforcing if not enforce and prop in vmconfig["current"][collection]: continue # create set_ dict if "set_{}".format(collection) not in vmconfig["changed"]: vmconfig["changed"]["set_{}".format(collection)] = {} # add property to changeset vmconfig["changed"]["set_{}".format(collection)][prop] = vmconfig[ "state" ][collection][prop] # process remove for collection if ( enforce and collection in vmconfig["current"] and vmconfig["current"][collection] is not None ): for prop in vmconfig["current"][collection]: # skip if exists in state if ( collection in vmconfig["state"] and vmconfig["state"][collection] is not None ): if prop in vmconfig["state"][collection]: continue # create remove_ array if "remove_{}".format(collection) not in vmconfig["changed"]: vmconfig["changed"]["remove_{}".format(collection)] = [] # remove property vmconfig["changed"]["remove_{}".format(collection)].append(prop) # process instances for instance in vmconfig_type["instance"]: # skip create only instances if instance in vmconfig_type["create_only"]: continue # add or update instances if ( instance in vmconfig["state"] and vmconfig["state"][instance] is not None ): for state_cfg in vmconfig["state"][instance]: add_instance = True # find instance with matching ids for current_cfg in vmconfig["current"][instance]: if vmconfig_type["instance"][instance] not in state_cfg: continue if ( state_cfg[vmconfig_type["instance"][instance]] == current_cfg[vmconfig_type["instance"][instance]] ): # ids have matched, disable add instance add_instance = False changed = _get_instance_changes(current_cfg, state_cfg) update_cfg = {} # handle changes for prop in changed: update_cfg[prop] = state_cfg[prop] # handle new properties for prop in state_cfg: # skip empty props like ips, options,.. if ( isinstance(state_cfg[prop], (list)) and not state_cfg[prop] ): continue if prop not in current_cfg: update_cfg[prop] = state_cfg[prop] # update instance if update_cfg: # create update_ array if ( "update_{}".format(instance) not in vmconfig["changed"] ): vmconfig["changed"][ "update_{}".format(instance) ] = [] update_cfg[ vmconfig_type["instance"][instance] ] = state_cfg[vmconfig_type["instance"][instance]] vmconfig["changed"][ "update_{}".format(instance) ].append(update_cfg) if add_instance: # create add_ array if "add_{}".format(instance) not in vmconfig["changed"]: vmconfig["changed"]["add_{}".format(instance)] = [] # add instance vmconfig["changed"]["add_{}".format(instance)].append(state_cfg) # remove instances if ( instance in vmconfig["current"] and vmconfig["current"][instance] is not None ): for current_cfg in vmconfig["current"][instance]: remove_instance = True # find instance with matching ids if ( instance in vmconfig["state"] and vmconfig["state"][instance] is not None ): for state_cfg in vmconfig["state"][instance]: if vmconfig_type["instance"][instance] not in state_cfg: continue if ( state_cfg[vmconfig_type["instance"][instance]] == current_cfg[vmconfig_type["instance"][instance]] ): # keep instance if matched remove_instance = False if remove_instance: # create remove_ array if "remove_{}".format(instance) not in vmconfig["changed"]: vmconfig["changed"]["remove_{}".format(instance)] = [] # remove instance vmconfig["changed"]["remove_{}".format(instance)].append( current_cfg[vmconfig_type["instance"][instance]] ) # update vm if we have pending changes kvm_needs_start = False if not __opts__["test"] and vmconfig["changed"]: # stop kvm if disk updates and kvm_reboot if vmconfig["current"]["brand"] == "kvm" and config["kvm_reboot"]: if ( "add_disks" in vmconfig["changed"] or "update_disks" in vmconfig["changed"] or "remove_disks" in vmconfig["changed"] ): if vmconfig["state"]["hostname"] in __salt__["vmadm.list"]( order="hostname", search="state=running" ): kvm_needs_start = True __salt__["vmadm.stop"]( vm=vmconfig["state"]["hostname"], key="hostname" ) # do update rret = __salt__["vmadm.update"]( vm=vmconfig["state"]["hostname"], key="hostname", **vmconfig["changed"] ) if not isinstance(rret, (bool)) and "Error" in rret: ret["result"] = False ret["comment"] = "{}".format(rret["Error"]) else: ret["result"] = True ret["changes"][vmconfig["state"]["hostname"]] = vmconfig["changed"] if ret["result"]: if __opts__["test"]: ret["changes"][vmconfig["state"]["hostname"]] = vmconfig["changed"] if ( vmconfig["state"]["hostname"] in ret["changes"] and ret["changes"][vmconfig["state"]["hostname"]] ): ret["comment"] = "vm {} updated".format(vmconfig["state"]["hostname"]) if ( config["kvm_reboot"] and vmconfig["current"]["brand"] == "kvm" and not __opts__["test"] ): if vmconfig["state"]["hostname"] in __salt__["vmadm.list"]( order="hostname", search="state=running" ): __salt__["vmadm.reboot"]( vm=vmconfig["state"]["hostname"], key="hostname" ) if kvm_needs_start: __salt__["vmadm.start"]( vm=vmconfig["state"]["hostname"], key="hostname" ) else: ret["changes"] = {} ret["comment"] = "vm {} is up to date".format( vmconfig["state"]["hostname"] ) # reprovision (if required and allowed) if ( "image_uuid" in vmconfig["current"] and vmconfig["reprovision_uuid"] != vmconfig["current"]["image_uuid"] ): if config["reprovision"]: rret = __salt__["vmadm.reprovision"]( vm=vmconfig["state"]["hostname"], key="hostname", image=vmconfig["reprovision_uuid"], ) if not isinstance(rret, (bool)) and "Error" in rret: ret["result"] = False ret["comment"] = "vm {} updated, reprovision failed".format( vmconfig["state"]["hostname"] ) else: ret["comment"] = "vm {} updated and reprovisioned".format( vmconfig["state"]["hostname"] ) if vmconfig["state"]["hostname"] not in ret["changes"]: ret["changes"][vmconfig["state"]["hostname"]] = {} ret["changes"][vmconfig["state"]["hostname"]][ "image_uuid" ] = vmconfig["reprovision_uuid"] else: log.warning( "smartos.vm_present::%s::reprovision - " "image_uuid in state does not match current, " "reprovision not allowed", name, ) else: ret["comment"] = "vm {} failed to be updated".format( vmconfig["state"]["hostname"] ) if not isinstance(rret, (bool)) and "Error" in rret: ret["comment"] = "{}".format(rret["Error"]) else: # check required image installed ret["result"] = True # disks need some special care if "disks" in vmconfig: new_disks = [] for disk in vmconfig["disks"]: if "path" in disk: del disk["path"] new_disks.append(disk) vmconfig["disks"] = new_disks # create vm if ret["result"]: uuid = ( __salt__["vmadm.create"](**vmconfig) if not __opts__["test"] else True ) if not isinstance(uuid, (bool)) and "Error" in uuid: ret["result"] = False ret["comment"] = "{}".format(uuid["Error"]) else: ret["result"] = True ret["changes"][vmconfig["hostname"]] = vmconfig ret["comment"] = "vm {} created".format(vmconfig["hostname"]) return ret def vm_absent(name, archive=False): """ Ensure vm is absent on the computenode name : string hostname of vm archive : boolean toggle archiving of vm on removal .. note:: State ID is used as hostname. Hostnames must be unique. """ name = name.lower() ret = {"name": name, "changes": {}, "result": None, "comment": ""} if name not in __salt__["vmadm.list"](order="hostname"): # we're good ret["result"] = True ret["comment"] = "vm {} is absent".format(name) else: # delete vm if not __opts__["test"]: # set archive to true if needed if archive: __salt__["vmadm.update"]( vm=name, key="hostname", archive_on_delete=True ) ret["result"] = __salt__["vmadm.delete"](name, key="hostname") else: ret["result"] = True if not isinstance(ret["result"], bool) and ret["result"].get("Error"): ret["result"] = False ret["comment"] = "failed to delete vm {}".format(name) else: ret["comment"] = "vm {} deleted".format(name) ret["changes"][name] = None return ret def vm_running(name): """ Ensure vm is in the running state on the computenode name : string hostname of vm .. note:: State ID is used as hostname. Hostnames must be unique. """ name = name.lower() ret = {"name": name, "changes": {}, "result": None, "comment": ""} if name in __salt__["vmadm.list"](order="hostname", search="state=running"): # we're good ret["result"] = True ret["comment"] = "vm {} already running".format(name) else: # start the vm ret["result"] = ( True if __opts__["test"] else __salt__["vmadm.start"](name, key="hostname") ) if not isinstance(ret["result"], bool) and ret["result"].get("Error"): ret["result"] = False ret["comment"] = "failed to start {}".format(name) else: ret["changes"][name] = "running" ret["comment"] = "vm {} started".format(name) return ret def vm_stopped(name): """ Ensure vm is in the stopped state on the computenode name : string hostname of vm .. note:: State ID is used as hostname. Hostnames must be unique. """ name = name.lower() ret = {"name": name, "changes": {}, "result": None, "comment": ""} if name in __salt__["vmadm.list"](order="hostname", search="state=stopped"): # we're good ret["result"] = True ret["comment"] = "vm {} already stopped".format(name) else: # stop the vm ret["result"] = ( True if __opts__["test"] else __salt__["vmadm.stop"](name, key="hostname") ) if not isinstance(ret["result"], bool) and ret["result"].get("Error"): ret["result"] = False ret["comment"] = "failed to stop {}".format(name) else: ret["changes"][name] = "stopped" ret["comment"] = "vm {} stopped".format(name) return ret # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4