Allen Li | 6a61239 | 2016-08-18 12:09:32 -0700 | [diff] [blame] | 1 | # Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
| 4 | |
| 5 | """Module for constructing links to AFE pages. |
| 6 | |
| 7 | This module defines a class for the URL construction logic to loosen the |
| 8 | coupling and make it easier to test, but also defines module functions for |
| 9 | convenience and normal usage. |
| 10 | |
| 11 | While there is a root_url property exposed, please refrain from using it to |
| 12 | construct URLs and instead add a suitable method to AfeUrls. |
| 13 | |
| 14 | """ |
| 15 | |
| 16 | import logging |
| 17 | import urllib |
| 18 | import urlparse |
| 19 | import sys |
| 20 | |
| 21 | import common |
| 22 | from autotest_lib.client.common_lib import global_config |
| 23 | |
| 24 | logger = logging.getLogger(__name__) |
| 25 | |
| 26 | |
| 27 | class AfeUrls(object): |
| 28 | |
| 29 | """Class for getting AFE URLs.""" |
| 30 | |
| 31 | def __init__(self, root_url): |
| 32 | """Initialize instance. |
| 33 | |
| 34 | @param root_url: AFE root URL. |
| 35 | |
| 36 | """ |
| 37 | self._root_url_parts = urlparse.urlsplit(root_url) |
| 38 | |
| 39 | _DEFAULT_URL = 'http://%s/afe/' |
| 40 | |
| 41 | def __hash__(self): |
| 42 | return hash(self.root_url) |
| 43 | |
| 44 | def __eq__(self, other): |
| 45 | if isinstance(other, type(self)): |
| 46 | return self.root_url == other.root_url |
| 47 | else: |
| 48 | return NotImplemented |
| 49 | |
| 50 | @classmethod |
| 51 | def from_hostname(cls, hostname): |
| 52 | """Create AfeUrls given only a hostname, assuming default URL path. |
| 53 | |
| 54 | @param hostname: Hostname of AFE. |
| 55 | @returns: AfeUrls instance. |
| 56 | |
| 57 | """ |
| 58 | return cls(cls._DEFAULT_URL % (hostname,)) |
| 59 | |
| 60 | def _geturl(self, params): |
| 61 | """Get AFE URL. |
| 62 | |
| 63 | All AFE URLs have the format: |
| 64 | |
| 65 | http://host/afe/#param1=val1¶m2=val2 |
| 66 | |
| 67 | This function constructs such a URL given a mapping of parameters. |
| 68 | |
| 69 | @param params: Mapping of URL parameters. |
| 70 | @returns: URL string. |
| 71 | |
| 72 | """ |
| 73 | scheme, netloc, path, query, _fragment = self._root_url_parts |
| 74 | fragment = urllib.urlencode(params) |
| 75 | return urlparse.SplitResult( |
| 76 | scheme, netloc, path, query, fragment).geturl() |
| 77 | |
| 78 | @property |
| 79 | def root_url(self): |
| 80 | """Canonical root URL. |
| 81 | |
| 82 | Note that this may not be the same as the URL passed into the |
| 83 | constructor, due to canonicalization. |
| 84 | |
| 85 | """ |
| 86 | return self._root_url_parts.geturl() |
| 87 | |
| 88 | def get_host_url(self, host_id): |
| 89 | """Get AFE URL for the given host. |
| 90 | |
| 91 | @param host_id: Host id. |
| 92 | @returns: URL string. |
| 93 | |
| 94 | """ |
| 95 | return self._geturl({'tab_id': 'view_host', 'object_id': host_id}) |
| 96 | |
| 97 | |
| 98 | _CONFIG = global_config.global_config |
| 99 | _HOSTNAME = _CONFIG.get_config_value('SERVER', 'hostname') |
| 100 | if not _HOSTNAME: |
| 101 | logger.critical('[SERVER] hostname missing from the config file.') |
| 102 | sys.exit(1) |
| 103 | |
| 104 | _singleton_afe_urls = AfeUrls.from_hostname(_HOSTNAME) |
| 105 | ROOT_URL = _singleton_afe_urls.root_url |
| 106 | get_host_url = _singleton_afe_urls.get_host_url |