Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / connector.py @ 798f1ac9

History | View | Annotate | Download (9.1 kB)

1 10b207d4 Oleksiy Mishchenko
#
2 10b207d4 Oleksiy Mishchenko
#
3 10b207d4 Oleksiy Mishchenko
4 10b207d4 Oleksiy Mishchenko
# Copyright (C) 2006, 2007, 2008 Google Inc.
5 10b207d4 Oleksiy Mishchenko
#
6 10b207d4 Oleksiy Mishchenko
# This program is free software; you can redistribute it and/or modify
7 10b207d4 Oleksiy Mishchenko
# it under the terms of the GNU General Public License as published by
8 10b207d4 Oleksiy Mishchenko
# the Free Software Foundation; either version 2 of the License, or
9 10b207d4 Oleksiy Mishchenko
# (at your option) any later version.
10 10b207d4 Oleksiy Mishchenko
#
11 10b207d4 Oleksiy Mishchenko
# This program is distributed in the hope that it will be useful, but
12 10b207d4 Oleksiy Mishchenko
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 10b207d4 Oleksiy Mishchenko
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 10b207d4 Oleksiy Mishchenko
# General Public License for more details.
15 10b207d4 Oleksiy Mishchenko
#
16 10b207d4 Oleksiy Mishchenko
# You should have received a copy of the GNU General Public License
17 10b207d4 Oleksiy Mishchenko
# along with this program; if not, write to the Free Software
18 10b207d4 Oleksiy Mishchenko
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 10b207d4 Oleksiy Mishchenko
# 02110-1301, USA.
20 10b207d4 Oleksiy Mishchenko
21 10b207d4 Oleksiy Mishchenko
"""Remote API connection map.
22 10b207d4 Oleksiy Mishchenko

23 10b207d4 Oleksiy Mishchenko
"""
24 10b207d4 Oleksiy Mishchenko
25 b459a848 Andrea Spadaccini
# pylint: disable=C0103
26 fe267188 Iustin Pop
27 fe267188 Iustin Pop
# C0103: Invalid name, since the R_* names are not conforming
28 fe267188 Iustin Pop
29 10b207d4 Oleksiy Mishchenko
import cgi
30 10b207d4 Oleksiy Mishchenko
import re
31 10b207d4 Oleksiy Mishchenko
32 a2f92677 Michael Hanselmann
from ganeti import constants
33 a2f92677 Michael Hanselmann
from ganeti import http
34 691c81b7 Michael Hanselmann
from ganeti import utils
35 10b207d4 Oleksiy Mishchenko
36 10b207d4 Oleksiy Mishchenko
from ganeti.rapi import rlib2
37 10b207d4 Oleksiy Mishchenko
38 bf968b7f Michael Hanselmann
39 bf968b7f Michael Hanselmann
_NAME_PATTERN = r"[\w\._-]+"
40 e23881ed Michael Hanselmann
_DISK_PATTERN = r"\d+"
41 bf968b7f Michael Hanselmann
42 a2f92677 Michael Hanselmann
# the connection map is created at the end of this file
43 10b207d4 Oleksiy Mishchenko
CONNECTOR = {}
44 10b207d4 Oleksiy Mishchenko
45 10b207d4 Oleksiy Mishchenko
46 10b207d4 Oleksiy Mishchenko
class Mapper:
47 10b207d4 Oleksiy Mishchenko
  """Map resource to method.
48 10b207d4 Oleksiy Mishchenko

49 10b207d4 Oleksiy Mishchenko
  """
50 e11ddf13 Iustin Pop
  def __init__(self, connector=None):
51 10b207d4 Oleksiy Mishchenko
    """Resource mapper constructor.
52 10b207d4 Oleksiy Mishchenko

53 c41eea6e Iustin Pop
    @param connector: a dictionary, mapping method name with URL path regexp
54 10b207d4 Oleksiy Mishchenko

55 10b207d4 Oleksiy Mishchenko
    """
56 e11ddf13 Iustin Pop
    if connector is None:
57 e11ddf13 Iustin Pop
      connector = CONNECTOR
58 10b207d4 Oleksiy Mishchenko
    self._connector = connector
59 10b207d4 Oleksiy Mishchenko
60 10b207d4 Oleksiy Mishchenko
  def getController(self, uri):
61 10b207d4 Oleksiy Mishchenko
    """Find method for a given URI.
62 10b207d4 Oleksiy Mishchenko

63 c41eea6e Iustin Pop
    @param uri: string with URI
64 10b207d4 Oleksiy Mishchenko

65 c41eea6e Iustin Pop
    @return: None if no method is found or a tuple containing
66 c41eea6e Iustin Pop
        the following fields:
67 c41eea6e Iustin Pop
            - method: name of method mapped to URI
68 c41eea6e Iustin Pop
            - items: a list of variable intems in the path
69 c41eea6e Iustin Pop
            - args: a dictionary with additional parameters from URL
70 10b207d4 Oleksiy Mishchenko

71 10b207d4 Oleksiy Mishchenko
    """
72 d0c8c01d Iustin Pop
    if "?" in uri:
73 d0c8c01d Iustin Pop
      (path, query) = uri.split("?", 1)
74 10b207d4 Oleksiy Mishchenko
      args = cgi.parse_qs(query)
75 10b207d4 Oleksiy Mishchenko
    else:
76 10b207d4 Oleksiy Mishchenko
      path = uri
77 10b207d4 Oleksiy Mishchenko
      query = None
78 10b207d4 Oleksiy Mishchenko
      args = {}
79 10b207d4 Oleksiy Mishchenko
80 691c81b7 Michael Hanselmann
    # Try to find handler for request path
81 691c81b7 Michael Hanselmann
    result = utils.FindMatch(self._connector, path)
82 10b207d4 Oleksiy Mishchenko
83 691c81b7 Michael Hanselmann
    if result is None:
84 691c81b7 Michael Hanselmann
      raise http.HttpNotFound()
85 10b207d4 Oleksiy Mishchenko
86 691c81b7 Michael Hanselmann
    (handler, groups) = result
87 10b207d4 Oleksiy Mishchenko
88 691c81b7 Michael Hanselmann
    return (handler, groups, args)
89 10b207d4 Oleksiy Mishchenko
90 10b207d4 Oleksiy Mishchenko
91 798f1ac9 Michael Hanselmann
def _ConvertPattern(value):
92 798f1ac9 Michael Hanselmann
  """Converts URI pattern into a regular expression group.
93 798f1ac9 Michael Hanselmann

94 798f1ac9 Michael Hanselmann
  Used by L{_CompileHandlerPath}.
95 798f1ac9 Michael Hanselmann

96 798f1ac9 Michael Hanselmann
  """
97 798f1ac9 Michael Hanselmann
  if isinstance(value, UriPattern):
98 798f1ac9 Michael Hanselmann
    return "(%s)" % value.content
99 798f1ac9 Michael Hanselmann
  else:
100 798f1ac9 Michael Hanselmann
    return value
101 798f1ac9 Michael Hanselmann
102 798f1ac9 Michael Hanselmann
103 798f1ac9 Michael Hanselmann
def _CompileHandlerPath(*args):
104 798f1ac9 Michael Hanselmann
  """Compiles path for RAPI resource into regular expression.
105 798f1ac9 Michael Hanselmann

106 798f1ac9 Michael Hanselmann
  @return: Compiled regular expression object
107 798f1ac9 Michael Hanselmann

108 798f1ac9 Michael Hanselmann
  """
109 798f1ac9 Michael Hanselmann
  return re.compile("^%s$" % "".join(map(_ConvertPattern, args)))
110 798f1ac9 Michael Hanselmann
111 798f1ac9 Michael Hanselmann
112 798f1ac9 Michael Hanselmann
class UriPattern(object):
113 798f1ac9 Michael Hanselmann
  __slots__ = [
114 798f1ac9 Michael Hanselmann
    "content",
115 798f1ac9 Michael Hanselmann
    ]
116 798f1ac9 Michael Hanselmann
117 798f1ac9 Michael Hanselmann
  def __init__(self, content):
118 798f1ac9 Michael Hanselmann
    self.content = content
119 798f1ac9 Michael Hanselmann
120 798f1ac9 Michael Hanselmann
121 0897dc97 Adeodato Simo
def GetHandlers(node_name_pattern, instance_name_pattern,
122 4588b4bd Dimitris Aragiorgis
                group_name_pattern, network_name_pattern,
123 4588b4bd Dimitris Aragiorgis
                job_id_pattern, disk_pattern,
124 798f1ac9 Michael Hanselmann
                query_res_pattern,
125 798f1ac9 Michael Hanselmann
                translate=None):
126 bf968b7f Michael Hanselmann
  """Returns all supported resources and their handlers.
127 bf968b7f Michael Hanselmann

128 798f1ac9 Michael Hanselmann
  C{node_name_pattern} and the other C{*_pattern} parameters are wrapped in
129 798f1ac9 Michael Hanselmann
  L{UriPattern} and, if used in a URI, passed to the function specified using
130 798f1ac9 Michael Hanselmann
  C{translate}. C{translate} receives 1..N parameters which are either plain
131 798f1ac9 Michael Hanselmann
  strings or instances of L{UriPattern} and returns a dictionary key suitable
132 798f1ac9 Michael Hanselmann
  for the caller of C{GetHandlers}. The default implementation in
133 798f1ac9 Michael Hanselmann
  L{_CompileHandlerPath} returns a compiled regular expression in which each
134 798f1ac9 Michael Hanselmann
  pattern is a group.
135 798f1ac9 Michael Hanselmann

136 798f1ac9 Michael Hanselmann
  @rtype: dict
137 798f1ac9 Michael Hanselmann

138 bf968b7f Michael Hanselmann
  """
139 798f1ac9 Michael Hanselmann
  if translate is None:
140 798f1ac9 Michael Hanselmann
    translate_fn = _CompileHandlerPath
141 798f1ac9 Michael Hanselmann
  else:
142 798f1ac9 Michael Hanselmann
    translate_fn = translate
143 798f1ac9 Michael Hanselmann
144 798f1ac9 Michael Hanselmann
  node_name = UriPattern(node_name_pattern)
145 798f1ac9 Michael Hanselmann
  instance_name = UriPattern(instance_name_pattern)
146 798f1ac9 Michael Hanselmann
  group_name = UriPattern(group_name_pattern)
147 798f1ac9 Michael Hanselmann
  network_name = UriPattern(network_name_pattern)
148 798f1ac9 Michael Hanselmann
  job_id = UriPattern(job_id_pattern)
149 798f1ac9 Michael Hanselmann
  disk = UriPattern(disk_pattern)
150 798f1ac9 Michael Hanselmann
  query_res = UriPattern(query_res_pattern)
151 798f1ac9 Michael Hanselmann
152 2c0be3d0 Michael Hanselmann
  # Important note: New resources should always be added under /2. During a
153 2c0be3d0 Michael Hanselmann
  # discussion in July 2010 it was decided that having per-resource versions
154 2c0be3d0 Michael Hanselmann
  # is more flexible and future-compatible than versioning the whole remote
155 2c0be3d0 Michael Hanselmann
  # API.
156 798f1ac9 Michael Hanselmann
  # TODO: Consider a different data structure where all keys are of the same
157 798f1ac9 Michael Hanselmann
  # type. Strings are faster to look up in a dictionary than iterating and
158 798f1ac9 Michael Hanselmann
  # matching regular expressions, therefore maybe two separate dictionaries
159 798f1ac9 Michael Hanselmann
  # should be used.
160 bf968b7f Michael Hanselmann
  return {
161 0f945c65 Michael Hanselmann
    "/": rlib2.R_root,
162 132cdb87 Michael Hanselmann
    "/2": rlib2.R_2,
163 bf968b7f Michael Hanselmann
164 bf968b7f Michael Hanselmann
    "/version": rlib2.R_version,
165 10b207d4 Oleksiy Mishchenko
166 bf968b7f Michael Hanselmann
    "/2/nodes": rlib2.R_2_nodes,
167 798f1ac9 Michael Hanselmann
168 798f1ac9 Michael Hanselmann
    translate_fn("/2/nodes/", node_name):
169 bf968b7f Michael Hanselmann
      rlib2.R_2_nodes_name,
170 798f1ac9 Michael Hanselmann
    translate_fn("/2/nodes/", node_name, "/powercycle"):
171 42d4d8b9 Michael Hanselmann
      rlib2.R_2_nodes_name_powercycle,
172 798f1ac9 Michael Hanselmann
    translate_fn("/2/nodes/", node_name, "/tags"):
173 bf968b7f Michael Hanselmann
      rlib2.R_2_nodes_name_tags,
174 798f1ac9 Michael Hanselmann
    translate_fn("/2/nodes/", node_name, "/role"):
175 bf968b7f Michael Hanselmann
      rlib2.R_2_nodes_name_role,
176 798f1ac9 Michael Hanselmann
    translate_fn("/2/nodes/", node_name, "/evacuate"):
177 73452f12 Michael Hanselmann
      rlib2.R_2_nodes_name_evacuate,
178 798f1ac9 Michael Hanselmann
    translate_fn("/2/nodes/", node_name, "/migrate"):
179 1c482bab Michael Hanselmann
      rlib2.R_2_nodes_name_migrate,
180 798f1ac9 Michael Hanselmann
    translate_fn("/2/nodes/", node_name, "/modify"):
181 94497dd1 Michael Hanselmann
      rlib2.R_2_nodes_name_modify,
182 798f1ac9 Michael Hanselmann
    translate_fn("/2/nodes/", node_name, "/storage"):
183 7a95a954 Michael Hanselmann
      rlib2.R_2_nodes_name_storage,
184 798f1ac9 Michael Hanselmann
    translate_fn("/2/nodes/", node_name, "/storage/modify"):
185 1e82bc80 Michael Hanselmann
      rlib2.R_2_nodes_name_storage_modify,
186 798f1ac9 Michael Hanselmann
    translate_fn("/2/nodes/", node_name, "/storage/repair"):
187 723f4565 Michael Hanselmann
      rlib2.R_2_nodes_name_storage_repair,
188 bf968b7f Michael Hanselmann
189 bf968b7f Michael Hanselmann
    "/2/instances": rlib2.R_2_instances,
190 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name):
191 bf968b7f Michael Hanselmann
      rlib2.R_2_instances_name,
192 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/info"):
193 d8260842 Michael Hanselmann
      rlib2.R_2_instances_name_info,
194 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/tags"):
195 bf968b7f Michael Hanselmann
      rlib2.R_2_instances_name_tags,
196 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/reboot"):
197 2276aa29 Oleksiy Mishchenko
      rlib2.R_2_instances_name_reboot,
198 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/reinstall"):
199 e5b7c4ca Iustin Pop
      rlib2.R_2_instances_name_reinstall,
200 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/replace-disks"):
201 4c98b915 Michael Hanselmann
      rlib2.R_2_instances_name_replace_disks,
202 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/shutdown"):
203 0c55c24b Oleksiy Mishchenko
      rlib2.R_2_instances_name_shutdown,
204 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/startup"):
205 0c55c24b Oleksiy Mishchenko
      rlib2.R_2_instances_name_startup,
206 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/activate-disks"):
207 2197b66f René Nussbaumer
      rlib2.R_2_instances_name_activate_disks,
208 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/deactivate-disks"):
209 0a37de5f René Nussbaumer
      rlib2.R_2_instances_name_deactivate_disks,
210 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/recreate-disks"):
211 a52978c7 Michael Hanselmann
      rlib2.R_2_instances_name_recreate_disks,
212 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/prepare-export"):
213 ebeb600f Michael Hanselmann
      rlib2.R_2_instances_name_prepare_export,
214 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/export"):
215 ebeb600f Michael Hanselmann
      rlib2.R_2_instances_name_export,
216 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/migrate"):
217 5823e0d2 Michael Hanselmann
      rlib2.R_2_instances_name_migrate,
218 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/failover"):
219 c0a146a1 Michael Hanselmann
      rlib2.R_2_instances_name_failover,
220 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/rename"):
221 d56e7dc7 Michael Hanselmann
      rlib2.R_2_instances_name_rename,
222 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/modify"):
223 3882937a Michael Hanselmann
      rlib2.R_2_instances_name_modify,
224 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/disk/", disk, "/grow"):
225 e23881ed Michael Hanselmann
      rlib2.R_2_instances_name_disk_grow,
226 798f1ac9 Michael Hanselmann
    translate_fn("/2/instances/", instance_name, "/console"):
227 b82d4c5e Michael Hanselmann
      rlib2.R_2_instances_name_console,
228 bf968b7f Michael Hanselmann
229 4588b4bd Dimitris Aragiorgis
    "/2/networks": rlib2.R_2_networks,
230 798f1ac9 Michael Hanselmann
    translate_fn("/2/networks/", network_name):
231 4588b4bd Dimitris Aragiorgis
      rlib2.R_2_networks_name,
232 798f1ac9 Michael Hanselmann
    translate_fn("/2/networks/", network_name, "/connect"):
233 4588b4bd Dimitris Aragiorgis
      rlib2.R_2_networks_name_connect,
234 798f1ac9 Michael Hanselmann
    translate_fn("/2/networks/", network_name, "/disconnect"):
235 4588b4bd Dimitris Aragiorgis
      rlib2.R_2_networks_name_disconnect,
236 798f1ac9 Michael Hanselmann
    translate_fn("/2/networks/", network_name, "/modify"):
237 6e8091f9 Dimitris Aragiorgis
      rlib2.R_2_networks_name_modify,
238 798f1ac9 Michael Hanselmann
    translate_fn("/2/networks/", network_name, "/tags"):
239 6e8091f9 Dimitris Aragiorgis
      rlib2.R_2_networks_name_tags,
240 4588b4bd Dimitris Aragiorgis
241 0897dc97 Adeodato Simo
    "/2/groups": rlib2.R_2_groups,
242 798f1ac9 Michael Hanselmann
    translate_fn("/2/groups/", group_name):
243 0897dc97 Adeodato Simo
      rlib2.R_2_groups_name,
244 798f1ac9 Michael Hanselmann
    translate_fn("/2/groups/", group_name, "/modify"):
245 f18fab7d Adeodato Simo
      rlib2.R_2_groups_name_modify,
246 798f1ac9 Michael Hanselmann
    translate_fn("/2/groups/", group_name, "/rename"):
247 0dbaa9ca Adeodato Simo
      rlib2.R_2_groups_name_rename,
248 798f1ac9 Michael Hanselmann
    translate_fn("/2/groups/", group_name, "/assign-nodes"):
249 4245446f Adeodato Simo
      rlib2.R_2_groups_name_assign_nodes,
250 798f1ac9 Michael Hanselmann
    translate_fn("/2/groups/", group_name, "/tags"):
251 414ebaf1 Michael Hanselmann
      rlib2.R_2_groups_name_tags,
252 0897dc97 Adeodato Simo
253 bf968b7f Michael Hanselmann
    "/2/jobs": rlib2.R_2_jobs,
254 798f1ac9 Michael Hanselmann
    translate_fn("/2/jobs/", job_id):
255 bf968b7f Michael Hanselmann
      rlib2.R_2_jobs_id,
256 798f1ac9 Michael Hanselmann
    translate_fn("/2/jobs/", job_id, "/wait"):
257 793a8f7c Michael Hanselmann
      rlib2.R_2_jobs_id_wait,
258 bf968b7f Michael Hanselmann
259 4ee72287 René Nussbaumer
    "/2/instances-multi-alloc": rlib2.R_2_instances_multi_alloc,
260 bf968b7f Michael Hanselmann
    "/2/tags": rlib2.R_2_tags,
261 bf968b7f Michael Hanselmann
    "/2/info": rlib2.R_2_info,
262 bf968b7f Michael Hanselmann
    "/2/os": rlib2.R_2_os,
263 508e9b20 Michael Hanselmann
    "/2/redistribute-config": rlib2.R_2_redist_config,
264 7eac4a4d Michael Hanselmann
    "/2/features": rlib2.R_2_features,
265 62e999a5 Michael Hanselmann
    "/2/modify": rlib2.R_2_cluster_modify,
266 798f1ac9 Michael Hanselmann
267 798f1ac9 Michael Hanselmann
    translate_fn("/2/query/", query_res):
268 798f1ac9 Michael Hanselmann
      rlib2.R_2_query,
269 798f1ac9 Michael Hanselmann
    translate_fn("/2/query/", query_res, "/fields"):
270 208a6cff Michael Hanselmann
      rlib2.R_2_query_fields,
271 bf968b7f Michael Hanselmann
    }
272 bf968b7f Michael Hanselmann
273 bf968b7f Michael Hanselmann
274 4588b4bd Dimitris Aragiorgis
CONNECTOR.update(GetHandlers(_NAME_PATTERN, _NAME_PATTERN,
275 4588b4bd Dimitris Aragiorgis
                             _NAME_PATTERN, _NAME_PATTERN,
276 1c7fd467 Michael Hanselmann
                             constants.JOB_ID_TEMPLATE, _DISK_PATTERN,
277 1c7fd467 Michael Hanselmann
                             _NAME_PATTERN))