#!/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 = # RACKSPACE_PROJECT_ID = # RACKSPACE_API_KEY = # 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_href(server): if not hasattr(server, 'links'): return None for link in server.links: if link['rel'] == 'self': return link['href'] 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 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: raw_server = cloud.compute.get_server(server.id) except AttributeError: print("Please update your version of shade/openstacksdk." " openstacksdk >= 0.12 is required") raise href = get_href(raw_server) # Reads default config file /etc/rax-rdns-auth.conf and calls to # API to set reverse dns for RAX servers. auth = get_auth() rax_rdns(server.name, href, ip4, ip6, 3600, auth) 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', required=False, help='If server_href is not supplied then href, ' 'and ip addresses are fetched from the cloud ' 'using name.') 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 if args.server_href: auth = get_auth(args.config) rax_rdns(args.name, args.server_href, args.ip4, args.ip6, args.ttl, auth) else: import openstack cloud = openstack.connect() # Get the server using the shade layer so that we have server.public_v4 # and server.public_v6 try: server = cloud.get_server(args.name) except AttributeError: print("Please update your version of shade/openstacksdk." " openstacksdk >= 0.12 is required") raise set_rax_reverse_dns(cloud, server, server.public_v4, server.public_v6)