From bf90d30e901bf519ef288b993944c7fbba517e33 Mon Sep 17 00:00:00 2001 From: Eric Holscher Date: Tue, 4 Oct 2011 20:16:28 -0700 Subject: [PATCH] Added the filesystem layer for cnames so that we'll be able to serve them from nginx without hitting the backend. --- .gitignore | 3 ++- readthedocs/core/utils.py | 17 +++++++++++++++++ readthedocs/projects/models.py | 6 ++++++ readthedocs/projects/tasks.py | 13 ++++++++++++- readthedocs/settings/base.py | 1 + 5 files changed, 38 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 5ff1bdc13..eef91cb58 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ doc_root user_uploads user_builds +cnames local_settings.py _build media/pdf @@ -14,4 +15,4 @@ xml_output locks/* readthedocs/rtd_tests/tests/builds deploy/.vagrant -rtd.log \ No newline at end of file +rtd.log diff --git a/readthedocs/core/utils.py b/readthedocs/core/utils.py index 0230acf3c..f594769bd 100644 --- a/readthedocs/core/utils.py +++ b/readthedocs/core/utils.py @@ -28,3 +28,20 @@ def copy_file_to_app_servers(from_file, to_file): ret = os.system("rsync -e 'ssh -T' -av --delete %s %s@%s:%s" % (from_file, getpass.getuser(), server, to_file)) if ret != 0: print "COPY ERROR to app servers." + + +def run_on_app_servers(command): + """ + A helper to copy a single file across app servers + """ + print "Running %s on app servers" % command + ret_val = 0 + if getattr(settings, "MULTIPLE_APP_SERVERS", None): + for server in settings.MULTIPLE_APP_SERVERS: + ret = os.system("ssh %s@%s %s" % (getpass.getuser(), server, command)) + if ret != 0: + ret_val = ret + return ret_val + else: + ret = os.system(command) + return ret diff --git a/readthedocs/projects/models.py b/readthedocs/projects/models.py index 223e8b067..e1d8ed525 100644 --- a/readthedocs/projects/models.py +++ b/readthedocs/projects/models.py @@ -193,6 +193,12 @@ class Project(models.Model): """ return os.path.join(self.doc_path, 'rtd-builds', version) + def rtd_cname_path(self, cname): + """ + The path to the build html docs in the project. + """ + return os.path.join(settings.CNAME_ROOT, cname) + def conf_file(self, version='latest'): files = self.find('conf.py', version) if not files: diff --git a/readthedocs/projects/tasks.py b/readthedocs/projects/tasks.py index 0abf2bdf6..7c03c1c3d 100644 --- a/readthedocs/projects/tasks.py +++ b/readthedocs/projects/tasks.py @@ -28,7 +28,7 @@ from projects.utils import ( slugify_uniquely, ) from tastyapi import client -from core.utils import copy_to_app_servers +from core.utils import copy_to_app_servers, run_on_app_servers ghetto_hack = re.compile( r'(?P.*)\s*=\s*u?\[?[\'\"](?P.*)[\'\"]\]?') @@ -101,6 +101,7 @@ def update_docs(pk, record=True, pdf=True, man=True, epub=True, version_pk=None, print "HTML Build OK" purge_version(version, subdomain=True, mainsite=True, cname=True) + symlink_cname(version) update_intersphinx(version.pk) print "Purged %s" % version else: @@ -429,3 +430,13 @@ def save_term(version, term, url, title): version_slug, term), url) redis_obj.setnx('redirects:v3:%s:%s:%s:%s:%s' % (lang, project_slug, version_slug, term, url), 1) + + +def symlink_cname(version): + build_dir = version.project.rtd_build_path(version.slug) + redis_conn = redis.Redis(**settings.REDIS) + for cname in redis_conn.smembers('rtd_slug:v1:%s' % version.project.slug): + print "Symlinking %s" % cname + symlink = version.project.rtd_cname_path(cname) + run_on_app_servers('mkdir -p %s' % '/'.join(symlink.split('/')[:-1])) + run_on_app_servers('ln -nsf %s %s' % (build_dir, symlink)) diff --git a/readthedocs/settings/base.py b/readthedocs/settings/base.py index b36a9f5b6..7642bcf41 100644 --- a/readthedocs/settings/base.py +++ b/readthedocs/settings/base.py @@ -15,6 +15,7 @@ MANAGERS = ADMINS SITE_ROOT = '/'.join(os.path.dirname(__file__).split('/')[0:-2]) DOCROOT = os.path.join(SITE_ROOT, 'user_builds') UPLOAD_ROOT = os.path.join(SITE_ROOT, 'user_uploads') +CNAME_ROOT = os.path.join(SITE_ROOT, 'cnames') MEDIA_ROOT = '%s/media/' % (SITE_ROOT) MEDIA_URL = '/media/'