Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / connector.py @ 7eac4a4d

History | View | Annotate | Download (6.2 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 fe267188 Iustin Pop
# pylint: disable-msg=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 10b207d4 Oleksiy Mishchenko
35 a2f92677 Michael Hanselmann
from ganeti.rapi import baserlib
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 bf968b7f Michael Hanselmann
41 a2f92677 Michael Hanselmann
# the connection map is created at the end of this file
42 10b207d4 Oleksiy Mishchenko
CONNECTOR = {}
43 10b207d4 Oleksiy Mishchenko
44 10b207d4 Oleksiy Mishchenko
45 10b207d4 Oleksiy Mishchenko
class Mapper:
46 10b207d4 Oleksiy Mishchenko
  """Map resource to method.
47 10b207d4 Oleksiy Mishchenko

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

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

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

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

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

70 10b207d4 Oleksiy Mishchenko
    """
71 10b207d4 Oleksiy Mishchenko
    if '?' in uri:
72 10b207d4 Oleksiy Mishchenko
      (path, query) = uri.split('?', 1)
73 10b207d4 Oleksiy Mishchenko
      args = cgi.parse_qs(query)
74 10b207d4 Oleksiy Mishchenko
    else:
75 10b207d4 Oleksiy Mishchenko
      path = uri
76 10b207d4 Oleksiy Mishchenko
      query = None
77 10b207d4 Oleksiy Mishchenko
      args = {}
78 10b207d4 Oleksiy Mishchenko
79 10b207d4 Oleksiy Mishchenko
    result = None
80 10b207d4 Oleksiy Mishchenko
81 10b207d4 Oleksiy Mishchenko
    for key, handler in self._connector.iteritems():
82 10b207d4 Oleksiy Mishchenko
      # Regex objects
83 10b207d4 Oleksiy Mishchenko
      if hasattr(key, "match"):
84 10b207d4 Oleksiy Mishchenko
        m = key.match(path)
85 10b207d4 Oleksiy Mishchenko
        if m:
86 10b207d4 Oleksiy Mishchenko
          result = (handler, list(m.groups()), args)
87 10b207d4 Oleksiy Mishchenko
          break
88 10b207d4 Oleksiy Mishchenko
89 10b207d4 Oleksiy Mishchenko
      # String objects
90 10b207d4 Oleksiy Mishchenko
      elif key == path:
91 10b207d4 Oleksiy Mishchenko
        result = (handler, [], args)
92 10b207d4 Oleksiy Mishchenko
        break
93 10b207d4 Oleksiy Mishchenko
94 a0638838 Oleksiy Mishchenko
    if result:
95 10b207d4 Oleksiy Mishchenko
      return result
96 10b207d4 Oleksiy Mishchenko
    else:
97 84f2756e Michael Hanselmann
      raise http.HttpNotFound()
98 10b207d4 Oleksiy Mishchenko
99 10b207d4 Oleksiy Mishchenko
100 10b207d4 Oleksiy Mishchenko
class R_root(baserlib.R_Generic):
101 10b207d4 Oleksiy Mishchenko
  """/ resource.
102 10b207d4 Oleksiy Mishchenko

103 10b207d4 Oleksiy Mishchenko
  """
104 7e950d31 Iustin Pop
  @staticmethod
105 7e950d31 Iustin Pop
  def GET():
106 10b207d4 Oleksiy Mishchenko
    """Show the list of mapped resources.
107 a2f92677 Michael Hanselmann

108 c41eea6e Iustin Pop
    @return: a dictionary with 'name' and 'uri' keys for each of them.
109 10b207d4 Oleksiy Mishchenko

110 10b207d4 Oleksiy Mishchenko
    """
111 10b207d4 Oleksiy Mishchenko
    root_pattern = re.compile('^R_([a-zA-Z0-9]+)$')
112 10b207d4 Oleksiy Mishchenko
113 10b207d4 Oleksiy Mishchenko
    rootlist = []
114 10b207d4 Oleksiy Mishchenko
    for handler in CONNECTOR.values():
115 10b207d4 Oleksiy Mishchenko
      m = root_pattern.match(handler.__name__)
116 10b207d4 Oleksiy Mishchenko
      if m:
117 10b207d4 Oleksiy Mishchenko
        name = m.group(1)
118 10b207d4 Oleksiy Mishchenko
        if name != 'root':
119 10b207d4 Oleksiy Mishchenko
          rootlist.append(name)
120 10b207d4 Oleksiy Mishchenko
121 10b207d4 Oleksiy Mishchenko
    return baserlib.BuildUriList(rootlist, "/%s")
122 10b207d4 Oleksiy Mishchenko
123 10b207d4 Oleksiy Mishchenko
124 69b99987 Michael Hanselmann
def _getResources(id_):
125 fc72a3a3 Oleksiy Mishchenko
  """Return a list of resources underneath given id.
126 fc72a3a3 Oleksiy Mishchenko

127 fc72a3a3 Oleksiy Mishchenko
  This is to generalize querying of version resources lists.
128 fc72a3a3 Oleksiy Mishchenko

129 fc72a3a3 Oleksiy Mishchenko
  @return: a list of resources names.
130 fc72a3a3 Oleksiy Mishchenko

131 fc72a3a3 Oleksiy Mishchenko
  """
132 69b99987 Michael Hanselmann
  r_pattern = re.compile('^R_%s_([a-zA-Z0-9]+)$' % id_)
133 fc72a3a3 Oleksiy Mishchenko
134 fc72a3a3 Oleksiy Mishchenko
  rlist = []
135 fc72a3a3 Oleksiy Mishchenko
  for handler in CONNECTOR.values():
136 fc72a3a3 Oleksiy Mishchenko
    m = r_pattern.match(handler.__name__)
137 fc72a3a3 Oleksiy Mishchenko
    if m:
138 fc72a3a3 Oleksiy Mishchenko
      name = m.group(1)
139 fc72a3a3 Oleksiy Mishchenko
      rlist.append(name)
140 fc72a3a3 Oleksiy Mishchenko
141 fc72a3a3 Oleksiy Mishchenko
  return rlist
142 fc72a3a3 Oleksiy Mishchenko
143 fc72a3a3 Oleksiy Mishchenko
144 fc72a3a3 Oleksiy Mishchenko
class R_2(baserlib.R_Generic):
145 bf4a90af Iustin Pop
  """ /2 resource, the root of the version 2 API.
146 fc72a3a3 Oleksiy Mishchenko

147 fc72a3a3 Oleksiy Mishchenko
  """
148 7e950d31 Iustin Pop
  @staticmethod
149 7e950d31 Iustin Pop
  def GET():
150 fc72a3a3 Oleksiy Mishchenko
    """Show the list of mapped resources.
151 fc72a3a3 Oleksiy Mishchenko

152 fc72a3a3 Oleksiy Mishchenko
    @return: a dictionary with 'name' and 'uri' keys for each of them.
153 fc72a3a3 Oleksiy Mishchenko

154 fc72a3a3 Oleksiy Mishchenko
    """
155 fc72a3a3 Oleksiy Mishchenko
    return baserlib.BuildUriList(_getResources("2"), "/2/%s")
156 fc72a3a3 Oleksiy Mishchenko
157 fc72a3a3 Oleksiy Mishchenko
158 bf968b7f Michael Hanselmann
def GetHandlers(node_name_pattern, instance_name_pattern, job_id_pattern):
159 bf968b7f Michael Hanselmann
  """Returns all supported resources and their handlers.
160 bf968b7f Michael Hanselmann

161 bf968b7f Michael Hanselmann
  """
162 bf968b7f Michael Hanselmann
  return {
163 bf968b7f Michael Hanselmann
    "/": R_root,
164 bf968b7f Michael Hanselmann
165 bf968b7f Michael Hanselmann
    "/version": rlib2.R_version,
166 10b207d4 Oleksiy Mishchenko
167 bf968b7f Michael Hanselmann
    "/2": R_2,
168 10b207d4 Oleksiy Mishchenko
169 bf968b7f Michael Hanselmann
    "/2/nodes": rlib2.R_2_nodes,
170 bf968b7f Michael Hanselmann
    re.compile(r'^/2/nodes/(%s)$' % node_name_pattern):
171 bf968b7f Michael Hanselmann
      rlib2.R_2_nodes_name,
172 bf968b7f Michael Hanselmann
    re.compile(r'^/2/nodes/(%s)/tags$' % node_name_pattern):
173 bf968b7f Michael Hanselmann
      rlib2.R_2_nodes_name_tags,
174 bf968b7f Michael Hanselmann
    re.compile(r'^/2/nodes/(%s)/role$' % node_name_pattern):
175 bf968b7f Michael Hanselmann
      rlib2.R_2_nodes_name_role,
176 bf968b7f Michael Hanselmann
    re.compile(r'^/2/nodes/(%s)/evacuate$' % node_name_pattern):
177 73452f12 Michael Hanselmann
      rlib2.R_2_nodes_name_evacuate,
178 bf968b7f Michael Hanselmann
    re.compile(r'^/2/nodes/(%s)/migrate$' % node_name_pattern):
179 1c482bab Michael Hanselmann
      rlib2.R_2_nodes_name_migrate,
180 bf968b7f Michael Hanselmann
    re.compile(r'^/2/nodes/(%s)/storage$' % node_name_pattern):
181 7a95a954 Michael Hanselmann
      rlib2.R_2_nodes_name_storage,
182 bf968b7f Michael Hanselmann
    re.compile(r'^/2/nodes/(%s)/storage/modify$' % node_name_pattern):
183 1e82bc80 Michael Hanselmann
      rlib2.R_2_nodes_name_storage_modify,
184 bf968b7f Michael Hanselmann
    re.compile(r'^/2/nodes/(%s)/storage/repair$' % node_name_pattern):
185 723f4565 Michael Hanselmann
      rlib2.R_2_nodes_name_storage_repair,
186 bf968b7f Michael Hanselmann
187 bf968b7f Michael Hanselmann
    "/2/instances": rlib2.R_2_instances,
188 bf968b7f Michael Hanselmann
    re.compile(r'^/2/instances/(%s)$' % instance_name_pattern):
189 bf968b7f Michael Hanselmann
      rlib2.R_2_instances_name,
190 bf968b7f Michael Hanselmann
    re.compile(r'^/2/instances/(%s)/info$' % instance_name_pattern):
191 d8260842 Michael Hanselmann
      rlib2.R_2_instances_name_info,
192 bf968b7f Michael Hanselmann
    re.compile(r'^/2/instances/(%s)/tags$' % instance_name_pattern):
193 bf968b7f Michael Hanselmann
      rlib2.R_2_instances_name_tags,
194 bf968b7f Michael Hanselmann
    re.compile(r'^/2/instances/(%s)/reboot$' % instance_name_pattern):
195 2276aa29 Oleksiy Mishchenko
      rlib2.R_2_instances_name_reboot,
196 bf968b7f Michael Hanselmann
    re.compile(r'^/2/instances/(%s)/reinstall$' % instance_name_pattern):
197 e5b7c4ca Iustin Pop
      rlib2.R_2_instances_name_reinstall,
198 bf968b7f Michael Hanselmann
    re.compile(r'^/2/instances/(%s)/replace-disks$' % instance_name_pattern):
199 4c98b915 Michael Hanselmann
      rlib2.R_2_instances_name_replace_disks,
200 bf968b7f Michael Hanselmann
    re.compile(r'^/2/instances/(%s)/shutdown$' % instance_name_pattern):
201 0c55c24b Oleksiy Mishchenko
      rlib2.R_2_instances_name_shutdown,
202 bf968b7f Michael Hanselmann
    re.compile(r'^/2/instances/(%s)/startup$' % instance_name_pattern):
203 0c55c24b Oleksiy Mishchenko
      rlib2.R_2_instances_name_startup,
204 2197b66f René Nussbaumer
    re.compile(r'^/2/instances/(%s)/activate-disks$' % instance_name_pattern):
205 2197b66f René Nussbaumer
      rlib2.R_2_instances_name_activate_disks,
206 0a37de5f René Nussbaumer
    re.compile(r'^/2/instances/(%s)/deactivate-disks$' % instance_name_pattern):
207 0a37de5f René Nussbaumer
      rlib2.R_2_instances_name_deactivate_disks,
208 bf968b7f Michael Hanselmann
209 bf968b7f Michael Hanselmann
    "/2/jobs": rlib2.R_2_jobs,
210 bf968b7f Michael Hanselmann
    re.compile(r'/2/jobs/(%s)$' % job_id_pattern):
211 bf968b7f Michael Hanselmann
      rlib2.R_2_jobs_id,
212 793a8f7c Michael Hanselmann
    re.compile(r'/2/jobs/(%s)/wait$' % job_id_pattern):
213 793a8f7c Michael Hanselmann
      rlib2.R_2_jobs_id_wait,
214 bf968b7f Michael Hanselmann
215 bf968b7f Michael Hanselmann
    "/2/tags": rlib2.R_2_tags,
216 bf968b7f Michael Hanselmann
    "/2/info": rlib2.R_2_info,
217 bf968b7f Michael Hanselmann
    "/2/os": rlib2.R_2_os,
218 508e9b20 Michael Hanselmann
    "/2/redistribute-config": rlib2.R_2_redist_config,
219 7eac4a4d Michael Hanselmann
    "/2/features": rlib2.R_2_features,
220 bf968b7f Michael Hanselmann
    }
221 bf968b7f Michael Hanselmann
222 bf968b7f Michael Hanselmann
223 bf968b7f Michael Hanselmann
CONNECTOR.update(GetHandlers(_NAME_PATTERN, _NAME_PATTERN,
224 bf968b7f Michael Hanselmann
                             constants.JOB_ID_TEMPLATE))