|  | # Copyright (c) 2014 The Chromium Authors. All rights reserved. | 
|  | # Use of this source code is governed by a BSD-style license that can be | 
|  | # found in the LICENSE file. | 
|  |  | 
|  | """Pages that redirect to the currently running Skia Buildbot master.""" | 
|  |  | 
|  | # TODO(rmistry): Delete this page when the new rebaseline server is ready. | 
|  |  | 
|  | import httplib | 
|  | import logging | 
|  | import urllib2 | 
|  |  | 
|  | import base_page | 
|  |  | 
|  |  | 
|  | # Static IP addresses of our various services. | 
|  | REBASELINE_SERVER_IPS = ['108.170.219.43'] | 
|  |  | 
|  | # Map of service type to (list_of_possible_ip_addrs, port, subpart, protocol). | 
|  | # The list_of_possible_ip_addrs, port, and protocol must be specified; | 
|  | # subpart can be an empty string if not needed. | 
|  | SERVICE_TYPE_TO_INFO = { | 
|  | 'rebaseline-server':  (REBASELINE_SERVER_IPS, 10117, '', 'http'), | 
|  | } | 
|  | # Timeout to use in urlopen when determining which IP is up. | 
|  | URLOPEN_TIMEOUT = 15 | 
|  |  | 
|  |  | 
|  | def _get_destination_url(service_type, slug, query_string=None): | 
|  | """Returns a complete destination URL from the service type and slug. | 
|  |  | 
|  | This function first determines which master from the possible_ips list is up. | 
|  | It then constructs a URL using the service type's port, subpart and protocol. | 
|  | The specified slug is then appended to this url. | 
|  |  | 
|  | Args: | 
|  | service_type: string; Which service_type to look up in SERVICE_TYPE_TO_INFO. | 
|  | If None, use the first path element within slug as the service_type. | 
|  | slug: string; Path elements that appengine handed us to deal with--we append | 
|  | this to the server-specific URL we create here. | 
|  | query_string: string; The query parameters of the URL, everything after the | 
|  | first ?. Optional. | 
|  |  | 
|  | Returns: | 
|  | A destination URL. | 
|  | """ | 
|  | if service_type: | 
|  | remaining_slug = slug | 
|  | elif '/' in slug: | 
|  | service_type, remaining_slug = slug.split('/', 1) | 
|  | else: | 
|  | service_type = slug | 
|  | remaining_slug = None | 
|  |  | 
|  | (possible_ips, port, subpart, protocol) = SERVICE_TYPE_TO_INFO[service_type] | 
|  | for ipaddr in possible_ips: | 
|  | # The test URL is used for validating that the IP + Port combination is up. | 
|  | test_url = 'http://%s:%s' % (ipaddr, port) | 
|  | try: | 
|  | urllib2.urlopen(test_url, timeout=URLOPEN_TIMEOUT).getcode() | 
|  | # Now that we verified that the test URL is up use the service's protocol | 
|  | # to construct the destination URL. | 
|  | destination_url = '%s://%s:%s' % (protocol, ipaddr, port) | 
|  | # Add the subpart and remaining_slug to the destination URL. | 
|  | if subpart: | 
|  | destination_url += '/%s' % subpart | 
|  | if remaining_slug: | 
|  | destination_url += '/%s' % remaining_slug | 
|  | if query_string: | 
|  | destination_url += '?%s' % query_string | 
|  | return destination_url | 
|  | except httplib.HTTPException, e: | 
|  | logging.warning(e) | 
|  |  | 
|  | error_msg = ('The buildbot master could not be contacted at any of %s' % | 
|  | str(possible_ips)) | 
|  | logging.error(error_msg) | 
|  | raise Exception(error_msg) | 
|  |  | 
|  |  | 
|  | class GenericRedirectionPage(base_page.BasePage): | 
|  | """Generic redirector which lets _get_destination_url() figure out the | 
|  | service_type.""" | 
|  | def get(self, slug, *args): | 
|  | destination_url = _get_destination_url( | 
|  | service_type=None, slug=slug, query_string=self.request.query_string) | 
|  | self.redirect(destination_url, True) | 
|  |  |