[MediaWiki-commits] [Gerrit] operations/puppet[production]: Openstack: Added 'dnsleaks.py' script.
Andrew Bogott has submitted this change and it was merged. ( https://gerrit.wikimedia.org/r/358124 ) Change subject: Openstack: Added 'dnsleaks.py' script. .. Openstack: Added 'dnsleaks.py' script. This hunts and (optionally) kills duplicate and leaked DNS entries. The battle to actually /prevent/ the leaks continues... Change-Id: Iaaf90e5e20fb35257cdfd9b10dd6f1a953f8e152 --- A modules/openstack/files/novastats/dnsleaks.py M modules/openstack/manifests/adminscripts.pp 2 files changed, 158 insertions(+), 0 deletions(-) Approvals: Andrew Bogott: Looks good to me, approved jenkins-bot: Verified diff --git a/modules/openstack/files/novastats/dnsleaks.py b/modules/openstack/files/novastats/dnsleaks.py new file mode 100755 index 000..b3b0e30 --- /dev/null +++ b/modules/openstack/files/novastats/dnsleaks.py @@ -0,0 +1,150 @@ +#!/usr/bin/python +# +# Copyright 2017 Wikimedia Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +""" +Dig through designate records, find and correct inconsistencies. + +- Arecs that point to multiple IPs +- Arecs that resolve nova VMs that don't exist anymore +- PTRs for nova VMs that don't exist anymore + +Be default this just reports on issues but with the --delete +command it will attempt to clean up as well. + + +Note that this is potentially racy and may misfire for instances that +are already mid-deletion. In that case it should be safe to re-run. +""" + +import argparse +import mwopenstackclients + +import requests +import yaml +import time + +clients = mwopenstackclients.clients() + + +def designate_endpoint_and_token(): +services = clients.keystoneclient().services.list() +for service in services: +if service.type == 'dns': +serviceid = service.id +break +endpoints = clients.keystoneclient().endpoints.list(serviceid) +for endpoint in endpoints: +if endpoint.interface == 'public': +url = endpoint.url + +session = clients.session() +token = session.get_token() + +return (url, token) + + +def delete_recordset(endpoint, token, zoneid, recordsetid): +headers = {'X-Auth-Token': token, + 'X-Auth-Sudo-Tenant-ID': 'noauth-project', + 'X-Designate-Edit-Managed-Records': 'true'} +recordseturl = "%s/v2/zones/%s/recordsets/%s" % (endpoint, zoneid, recordsetid) +print("Deleting %s with %s" % (recordsetid, recordseturl)) +req = requests.delete(recordseturl, + headers=headers, verify=False) +req.raise_for_status() +time.sleep(1) + + +def edit_recordset(endpoint, token, zoneid, recordset, newrecords): +headers = {'X-Auth-Token': token, + 'X-Auth-Sudo-Tenant-ID': 'noauth-project', + 'X-Designate-Edit-Managed-Records': 'true'} + +patch = {"records": newrecords} + +print("Updating %s with %s" % (recordset['id'], newrecords)) +recordseturl = "%s/v2/zones/%s/recordsets/%s" % (endpoint, zoneid, recordset['id']) + +req = requests.put(recordseturl, + headers=headers, verify=False, + json=patch) +req.raise_for_status() + + +def purge_duplicates(delete=False): +(endpoint, token) = designate_endpoint_and_token() + +headers = {'X-Auth-Token': token, 'X-Auth-Sudo-Tenant-ID': 'noauth-project'} +req = requests.get("%s/v2/zones" % (endpoint), headers=headers, verify=False) +req.raise_for_status() +zones = yaml.safe_load(req.text)['zones'] + +for zone in zones: +req = requests.get("%s/v2/zones/%s/recordsets" % (endpoint, zone['id']), + headers=headers, verify=False) +req.raise_for_status() +recordsets = yaml.safe_load(req.text)['recordsets'] + +# we need a fresh copy of all instances so we don't accidentally +# delete things that have been created since we last checked. +instances = clients.allinstances() +all_nova_instances = ["%s.%s.eqiad.wmflabs." % (instance.name, instance.tenant_id) + for instance in instances] +all_nova_shortname_instances = ["%s.eqiad.wmflabs." % (instance.name) +for instance in instances] + +for recordset in recordsets: +name = recordset['name'] +recordsetid = recordset['id'] +if recordset['type'] == 'A': +
[MediaWiki-commits] [Gerrit] operations/puppet[production]: Openstack: Added 'dnsleaks.py' script.
Andrew Bogott has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/358124 ) Change subject: Openstack: Added 'dnsleaks.py' script. .. Openstack: Added 'dnsleaks.py' script. This hunts and (optionally) kills duplicate and leaked DNS entries. The battle to actually /prevent/ the leaks continues... Change-Id: Iaaf90e5e20fb35257cdfd9b10dd6f1a953f8e152 --- A modules/openstack/files/novastats/dnsleaks.py M modules/openstack/manifests/adminscripts.pp 2 files changed, 157 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/operations/puppet refs/changes/24/358124/1 diff --git a/modules/openstack/files/novastats/dnsleaks.py b/modules/openstack/files/novastats/dnsleaks.py new file mode 100755 index 000..c3d5b2e --- /dev/null +++ b/modules/openstack/files/novastats/dnsleaks.py @@ -0,0 +1,149 @@ +#!/usr/bin/python +# +# Copyright 2017 Wikimedia Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +""" +Dig through designate records, find and correct inconsistencies. + +- Arecs that point to multiple IPs +- Arecs that resolve nova VMs that don't exist anymore +- PTRs for nova VMs that don't exist anymore + +Be default this just reports on issues but with the --delete +command it will attempt to clean up as well. + + +Note that this is potentially racy and may misfire for instances that +are already mid-deletion. In that case it should be safe to re-run. +""" + +import argparse +import mwopenstackclients + +import requests +import yaml +import time + +clients = mwopenstackclients.clients() + + +def designate_endpoint_and_token(): +services = clients.keystoneclient().services.list() +for service in services: +if service.type == 'dns': +serviceid = service.id +break +endpoints = clients.keystoneclient().endpoints.list(serviceid) +for endpoint in endpoints: +if endpoint.interface == 'public': +url = endpoint.url + +session = clients.session() +token = session.get_token() + +return (url, token) + + +def delete_recordset(endpoint, token, zoneid, recordsetid): +headers = {'X-Auth-Token': token, + 'X-Auth-Sudo-Tenant-ID': 'noauth-project', + 'X-Designate-Edit-Managed-Records': 'true'} +recordseturl = "%s/v2/zones/%s/recordsets/%s" % (endpoint, zoneid, recordsetid) +print("Deleting %s with %s" % (recordsetid, recordseturl)) +req = requests.delete(recordseturl, + headers=headers, verify=False) +req.raise_for_status() +time.sleep(1) + + +def edit_recordset(endpoint, token, zoneid, recordset, newrecords): +headers = {'X-Auth-Token': token, + 'X-Auth-Sudo-Tenant-ID': 'noauth-project', + 'X-Designate-Edit-Managed-Records': 'true'} + +patch = {"records": newrecords} + +print("Updating %s with %s" % (recordset['id'], newrecords)) +recordseturl = "%s/v2/zones/%s/recordsets/%s" % (endpoint, zoneid, recordset['id']) + +req = requests.put(recordseturl, + headers=headers, verify=False, + json=patch) +req.raise_for_status() + + +def purge_duplicates(delete=False): +(endpoint, token) = designate_endpoint_and_token() + +headers = {'X-Auth-Token': token, 'X-Auth-Sudo-Tenant-ID': 'noauth-project'} +req = requests.get("%s/v2/zones" % (endpoint), headers=headers, verify=False) +req.raise_for_status() +zones = yaml.safe_load(req.text)['zones'] + +for zone in zones: +req = requests.get("%s/v2/zones/%s/recordsets" % (endpoint, zone['id']), + headers=headers, verify=False) +req.raise_for_status() +recordsets = yaml.safe_load(req.text)['recordsets'] + +# we need a fresh copy of all instances so we don't accidentally +# delete things that have been created since we last checked. +instances = clients.allinstances() +all_nova_instances = ["%s.%s.eqiad.wmflabs." % (instance.name, instance.tenant_id) + for instance in instances] +all_nova_shortname_instances = ["%s.eqiad.wmflabs." % (instance.name) +for instance in instances] + +for recordset in recordsets: +name = recordset['name'] +recordsetid = recordset['id'] +if recordset['type'] == 'A': +