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