From ccfdcd1e8459509cf4521c49c789a2822baf32ca Mon Sep 17 00:00:00 2001 From: "James E. Blair" Date: Thu, 1 Aug 2019 14:44:49 -0700 Subject: [PATCH] Support Rackspace in upload-logs-swift Rackspace only provides unauthenticated access to object storage via CDN in a non-openstack-standard way, so we need to do some extra work to support that. This also adds a helper script for testing which deletes a container (since in order to do so, you may need to delete all the contents first). Some commented-out debug configuration lines are added for the convenience of future developers. Change-Id: I3d1fce824fb40136048f0988939d22f755236a59 --- .../library/delete_container.py | 65 +++++++++++++++++++ .../library/zuul_swift_upload.py | 29 ++++++++- 2 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 roles/upload-logs-swift/library/delete_container.py diff --git a/roles/upload-logs-swift/library/delete_container.py b/roles/upload-logs-swift/library/delete_container.py new file mode 100644 index 000000000..31e768ff7 --- /dev/null +++ b/roles/upload-logs-swift/library/delete_container.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# +# Copyright 2019 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. + +import argparse +import openstack +import requests +import logging +import os + +logging.basicConfig(level=logging.INFO) +# logging.getLogger("requests").setLevel(logging.DEBUG) +# logging.getLogger("keystoneauth").setLevel(logging.INFO) +# logging.getLogger("stevedore").setLevel(logging.INFO) +logging.captureWarnings(True) + + +def main(): + parser = argparse.ArgumentParser( + description="Delete a swift container" + ) + parser.add_argument('cloud', + help='Name of the cloud to use when uploading') + parser.add_argument('container', + help='Name of the container to use when uploading') + + args = parser.parse_args() + + cloud = openstack.connect(cloud=args.cloud) + + sess = cloud.config.get_session() + adapter = requests.adapters.HTTPAdapter(pool_maxsize=100) + sess.mount('https://', adapter) + + container = cloud.get_container(args.container) + print('Found container', container) + print() + for x in cloud.object_store.objects(args.container): + print('Delete object', x.name) + if x.name == '/': + endpoint = cloud.object_store.get_endpoint() + container = os.path.join(endpoint, args.container) + cloud.session.delete(container + '//') + else: + cloud.object_store.delete_object(x) + + print() + print('Delete container', container) + cloud.object_store.delete_container(args.container) + + +if __name__ == "__main__": + main() diff --git a/roles/upload-logs-swift/library/zuul_swift_upload.py b/roles/upload-logs-swift/library/zuul_swift_upload.py index ffa7398d7..0a113b5ab 100755 --- a/roles/upload-logs-swift/library/zuul_swift_upload.py +++ b/roles/upload-logs-swift/library/zuul_swift_upload.py @@ -45,6 +45,7 @@ import openstack import requests import requests.exceptions import requestsexceptions +import keystoneauth1 from ansible.module_utils.basic import AnsibleModule @@ -474,6 +475,17 @@ class Uploader(): adapter = requests.adapters.HTTPAdapter(pool_maxsize=100) sess.mount('https://', adapter) + # If we're in Rackspace, there's some non-standard stuff we + # need to do to get the public endpoint. + try: + cdn_endpoint = self.cloud.session.auth.get_endpoint( + self.cloud.session, service_type='rax:object-cdn', + region_name=self.cloud.config.region_name, + interface=self.cloud.config.interface) + cdn_url = os.path.join(cdn_endpoint, self.container) + except keystoneauth1.exceptions.catalog.EndpointNotFound: + cdn_url = None + if not self.cloud.get_container(self.container): self.cloud.create_container(name=self.container, public=public) self.cloud.update_container( @@ -488,8 +500,19 @@ class Uploader(): name='index.html', data='', content_type='text/html') - self.url = os.path.join(self.cloud.object_store.get_endpoint(), - self.container, self.prefix) + # Enable the CDN in rax + if cdn_url: + self.cloud.session.put(cdn_url) + + if cdn_url: + endpoint = (self.cloud.session.head(cdn_url) + .headers['X-Cdn-Ssl-Uri']) + container = endpoint + else: + endpoint = self.cloud.object_store.get_endpoint() + container = os.path.join(endpoint, self.container) + + self.url = os.path.join(container, self.prefix) def upload(self, file_list): """Spin up thread pool to upload to swift""" @@ -701,6 +724,8 @@ def cli_main(): logging.basicConfig(level=logging.DEBUG) # Set requests log level accordingly logging.getLogger("requests").setLevel(logging.DEBUG) + # logging.getLogger("keystoneauth").setLevel(logging.INFO) + # logging.getLogger("stevedore").setLevel(logging.INFO) logging.captureWarnings(True) append_footer = args.append_footer