launch: Automatically do RAX rdns updates when launching nodes

On the old bridge node we had some unmanaged venv's with a very old,
now unmaintained RAX DNS API interaction tool.

Adding the RDNS entries is fairly straight forward, and this small
tool is mostly a copy of some of the bits for our dns api backup tool.
It really just comes down to getting a token and making a post request
with the name/ip addresses.

When the cloud the node is launched as is identified as RAX, this will
automatically add the PTR records for the ip4 & 6 addresses.  It also
has an entrypoint to be called manually.

This is added and hacked in, along with a config file for the
appropriate account (I have added these details on bridge).

I've left the update of openstack.org DNS entries as a manual
procedure.  Although they could be set automatically with small
updates to the tool (just a different POST) -- details like CNAMES,
etc. and the relatively few servers we start in the RAX mangaed DNS
domains means I think it's easier to just do manually via the web ui.
The output comment is updated.

Change-Id: I8a42afdd00be2595ca73819610757ce5d4435d0a
This commit is contained in:
Ian Wienand 2022-11-24 11:16:00 +11:00
parent f40c52b01a
commit 20d2643f74
No known key found for this signature in database
6 changed files with 167 additions and 41 deletions

View File

@ -27,6 +27,7 @@ dependencies = [
[project.scripts]
launch-node = "opendev_launch:launch_node.main"
show-dns = "opendev_launch:dns.main"
rax-rdns = "opendev_launch:rax_rdns.main"
[tool.setuptools.package-data]
opendev_launch = ["*.sh"]

View File

@ -19,8 +19,10 @@
# limitations under the License.
import argparse
from . import rax_rdns
from .sshfp import sshfp_print_records
def get_href(server):
if not hasattr(server, 'links'):
return None
@ -33,18 +35,15 @@ def print_dns(cloud, server):
ip4 = server.public_v4
ip6 = server.public_v6
if 'rax' in cloud.config.name:
print_reverse_dns(cloud, server, ip4, ip6)
if server.name.endswith('opendev.org'):
print_dns_opendev(server.name.rsplit('.', 2)[0], ip4, ip6)
else:
print_dns_legacy(server, ip4, ip6)
print("Login to manage.rackspace.com and setup DNS manually.")
print_inventory_yaml(server, ip4, ip6)
def print_dns_opendev(name, ip4, ip6):
print("\n")
print("Put the following into zone-opendev.org:zones/opendev.org/zone.db")
print("{name} IN A {ip4}".format(name=name, ip4=ip4))
@ -52,7 +51,8 @@ def print_dns_opendev(name, ip4, ip6):
print("{name} IN AAAA {ip6}".format(name=name, ip6=ip6))
sshfp_print_records(name, ip4)
def print_reverse_dns(cloud, server, ip4, ip6):
def set_rax_reverse_dns(cloud, server, ip4, ip6):
# Get the server object from the sdk layer so that we can pull the
# href data out of the links dict.
try:
@ -63,43 +63,12 @@ def print_reverse_dns(cloud, server, ip4, ip6):
raise
href = get_href(raw_server)
print("\n")
print("Run the following commands to set up DNS:")
print("\n")
print(". ~root/ci-launch/openstackci-rs-nova.sh")
print(". ~root/rackdns-venv/bin/activate")
print("\n")
print(
"rackdns rdns-create --name %s \\\n"
" --data %s \\\n"
" --server-href %s \\\n"
" --ttl 3600" % (
server.name, ip6, href))
print("\n")
print(
"rackdns rdns-create --name %s \\\n"
" --data %s \\\n"
" --server-href %s \\\n"
" --ttl 3600" % (
server.name, ip4, href))
print("\n")
# Reads default config file /etc/rax-rdns-auth.conf and calls to
# API to set reverse dns for RAX servers.
auth = rax_rdns.get_auth()
rax_rdns.rax_rdns(server.name, href, ip4, ip6, 3600, auth)
def print_dns_legacy(server, ip4, ip6):
print(". ~root/ci-launch/openstack-rs-nova.sh")
print("\n")
print(
"rackdns record-create --name %s \\\n"
" --type AAAA --data %s \\\n"
" --ttl 3600 openstack.org" % (
server.name, ip6))
print("\n")
print(
"rackdns record-create --name %s \\\n"
" --type A --data %s \\\n"
" --ttl 3600 openstack.org" % (
server.name, ip4))
def print_inventory_yaml(server, ip4, ip6):
print("\n")
print("Put the following into system-config:inventory/base/hosts.yaml")
@ -130,4 +99,8 @@ def main():
print("Please update your version of shade/openstacksdk."
" openstacksdk >= 0.12 is required")
raise
if 'rax' in cloud.config.name:
set_rax_reverse_dns(cloud, server, ip4, ip6)
print_dns(cloud, server)

View File

@ -0,0 +1,136 @@
#!/usr/bin/env python3
# Copyright 2022 Red Hat, Inc.
#
# 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.
# Set RDNS values for a server
#
# Set auth in an .ini file specified with --config:
#
# [DEFAULT]
# RACKSPACE_USERNAME = <used to login to web>
# RACKSPACE_PROJECT_ID = <listed on account info>
# RACKSPACE_API_KEY = <listed in the account details page>
#
import argparse
import configparser
import collections
import logging
import os
import requests
import sys
# Verbose call debugging:
# import http.client as http_client
# http_client.HTTPConnection.debuglevel = 1
RACKSPACE_IDENTITY_ENDPOINT='https://identity.api.rackspacecloud.com/v2.0/tokens'
RACKSPACE_DNS_ENDPOINT="https://dns.api.rackspacecloud.com/v1.0"
def _get_auth_token(session, username, api_key):
# Get auth token
data = {'auth':
{
'RAX-KSKEY:apiKeyCredentials':
{
'username': username,
'apiKey': api_key
}
}
}
token_response = session.post(url=RACKSPACE_IDENTITY_ENDPOINT, json=data)
token = token_response.json()['access']['token']['id']
return token
def get_auth(config_file='/etc/rax-rdns-auth.conf'):
'''Return a tuple for passing to rax_rnds update function'''
try:
logging.info("Reading config file %s" % config_file)
config = configparser.ConfigParser()
config.read(config_file)
return (config['DEFAULT']['RACKSPACE_PROJECT_ID'],
config['DEFAULT']['RACKSPACE_USERNAME'],
config['DEFAULT']['RACKSPACE_API_KEY'])
except Exception as e:
logging.error("Can not read config: %s" % e)
sys.exit(1)
def rax_rdns(name, server_href, ip4, ip6, ttl, auth):
(rax_project_id, rax_username, rax_api_key) = auth
session = requests.Session()
token = _get_auth_token(session, rax_username, rax_api_key)
rdns_url = '%s/%s/rdns' % (RACKSPACE_DNS_ENDPOINT,
rax_project_id)
rdns_json = {
'recordsList': {
'records': [
{
'name': name,
'type': 'PTR',
'data': ip4,
'ttl': ttl
}, {
'name': name,
'type': 'PTR',
'data': ip6,
'ttl': ttl
}
]
},
'link': {
'content': '',
'href': server_href,
'rel': 'cloudServersOpenStack'
}
}
headers = {
'Accept': 'application/json',
'X-Auth-Token': token,
'X-Project-Id': rax_project_id,
'Content-Type': 'application/json'
}
r = session.post(url=rdns_url, headers=headers, json=rdns_json)
logging.info("RDNS Done: %s %s" % (r.status_code, r.reason))
def main():
parser = argparse.ArgumentParser(description='Update RDNS')
parser.add_argument('--debug', dest='debug', action='store_true')
parser.add_argument('--config', dest='config',
default='/etc/rax-rdns-auth.conf')
parser.add_argument('--ttl', dest='ttl', type=int, default=3600)
parser.add_argument('name')
parser.add_argument('server_href')
parser.add_argument('ip4')
parser.add_argument('ip6')
args = parser.parse_args()
logging.basicConfig(level=logging.INFO)
if args.debug:
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propogate = True
auth = get_auth(args.config)
rax_rdns(args.name, args.server_href, args.ip4, args.ip6, args.ttl, auth)

View File

@ -4,6 +4,14 @@
vars:
create_venv_path: '/usr/launcher-venv'
- name: Add RAX rdns credentials
template:
src: rax-rdns-auth.conf.j2
dest: /etc/rax-rdns-auth.conf
owner: root
group: root
mode: '0600'
- name: Install node launcher
pip:
name: 'file:///home/zuul/src/opendev.org/opendev/system-config/launch'

View File

@ -0,0 +1,4 @@
[DEFAULT]
RACKSPACE_USERNAME={{ rackspace_rdns_username }}
RACKSPACE_PROJECT_ID={{ rackspace_rdns_project_id }}
RACKSPACE_API_KEY={{ rackspace_rdns_api_key }}

View File

@ -7,3 +7,7 @@ extra_users: []
rackspace_dns_username: user
rackspace_dns_project_id: 1234
rackspace_dns_api_key: apikey
rackspace_rdns_username: user
rackspace_rdns_project_id: 1234
rackspace_rdns_api_key: apikey