Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / connector.py @ bf968b7f

History | View | Annotate | Download (5.6 kB)

1
#
2
#
3

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

    
21
"""Remote API connection map.
22

23
"""
24

    
25
import cgi
26
import re
27

    
28
from ganeti import constants
29
from ganeti import http
30

    
31
from ganeti.rapi import baserlib
32
from ganeti.rapi import rlib2
33

    
34

    
35
_NAME_PATTERN = r"[\w\._-]+"
36

    
37
# the connection map is created at the end of this file
38
CONNECTOR = {}
39

    
40

    
41
class Mapper:
42
  """Map resource to method.
43

44
  """
45
  def __init__(self, connector=CONNECTOR):
46
    """Resource mapper constructor.
47

48
    @param connector: a dictionary, mapping method name with URL path regexp
49

50
    """
51
    self._connector = connector
52

    
53
  def getController(self, uri):
54
    """Find method for a given URI.
55

56
    @param uri: string with URI
57

58
    @return: None if no method is found or a tuple containing
59
        the following fields:
60
            - method: name of method mapped to URI
61
            - items: a list of variable intems in the path
62
            - args: a dictionary with additional parameters from URL
63

64
    """
65
    if '?' in uri:
66
      (path, query) = uri.split('?', 1)
67
      args = cgi.parse_qs(query)
68
    else:
69
      path = uri
70
      query = None
71
      args = {}
72

    
73
    result = None
74

    
75
    for key, handler in self._connector.iteritems():
76
      # Regex objects
77
      if hasattr(key, "match"):
78
        m = key.match(path)
79
        if m:
80
          result = (handler, list(m.groups()), args)
81
          break
82

    
83
      # String objects
84
      elif key == path:
85
        result = (handler, [], args)
86
        break
87

    
88
    if result:
89
      return result
90
    else:
91
      raise http.HttpNotFound()
92

    
93

    
94
class R_root(baserlib.R_Generic):
95
  """/ resource.
96

97
  """
98
  def GET(self):
99
    """Show the list of mapped resources.
100

101
    @return: a dictionary with 'name' and 'uri' keys for each of them.
102

103
    """
104
    root_pattern = re.compile('^R_([a-zA-Z0-9]+)$')
105

    
106
    rootlist = []
107
    for handler in CONNECTOR.values():
108
      m = root_pattern.match(handler.__name__)
109
      if m:
110
        name = m.group(1)
111
        if name != 'root':
112
          rootlist.append(name)
113

    
114
    return baserlib.BuildUriList(rootlist, "/%s")
115

    
116

    
117
def _getResources(id):
118
  """Return a list of resources underneath given id.
119

120
  This is to generalize querying of version resources lists.
121

122
  @return: a list of resources names.
123

124
  """
125
  r_pattern = re.compile('^R_%s_([a-zA-Z0-9]+)$' % id)
126

    
127
  rlist = []
128
  for handler in CONNECTOR.values():
129
    m = r_pattern.match(handler.__name__)
130
    if m:
131
      name = m.group(1)
132
      rlist.append(name)
133

    
134
  return rlist
135

    
136

    
137
class R_2(baserlib.R_Generic):
138
  """ /2 resource, the root of the version 2 API.
139

140
  """
141
  def GET(self):
142
    """Show the list of mapped resources.
143

144
    @return: a dictionary with 'name' and 'uri' keys for each of them.
145

146
    """
147
    return baserlib.BuildUriList(_getResources("2"), "/2/%s")
148

    
149

    
150
def GetHandlers(node_name_pattern, instance_name_pattern, job_id_pattern):
151
  """Returns all supported resources and their handlers.
152

153
  """
154
  return {
155
    "/": R_root,
156

    
157
    "/version": rlib2.R_version,
158

    
159
    "/2": R_2,
160

    
161
    "/2/nodes": rlib2.R_2_nodes,
162
    re.compile(r'^/2/nodes/(%s)$' % node_name_pattern):
163
      rlib2.R_2_nodes_name,
164
    re.compile(r'^/2/nodes/(%s)/tags$' % node_name_pattern):
165
      rlib2.R_2_nodes_name_tags,
166
    re.compile(r'^/2/nodes/(%s)/role$' % node_name_pattern):
167
      rlib2.R_2_nodes_name_role,
168
    re.compile(r'^/2/nodes/(%s)/evacuate$' % node_name_pattern):
169
      rlib2.R_2_nodes_name_evacuate,
170
    re.compile(r'^/2/nodes/(%s)/migrate$' % node_name_pattern):
171
      rlib2.R_2_nodes_name_migrate,
172
    re.compile(r'^/2/nodes/(%s)/storage$' % node_name_pattern):
173
      rlib2.R_2_nodes_name_storage,
174
    re.compile(r'^/2/nodes/(%s)/storage/modify$' % node_name_pattern):
175
      rlib2.R_2_nodes_name_storage_modify,
176
    re.compile(r'^/2/nodes/(%s)/storage/repair$' % node_name_pattern):
177
      rlib2.R_2_nodes_name_storage_repair,
178

    
179
    "/2/instances": rlib2.R_2_instances,
180
    re.compile(r'^/2/instances/(%s)$' % instance_name_pattern):
181
      rlib2.R_2_instances_name,
182
    re.compile(r'^/2/instances/(%s)/info$' % instance_name_pattern):
183
      rlib2.R_2_instances_name_info,
184
    re.compile(r'^/2/instances/(%s)/tags$' % instance_name_pattern):
185
      rlib2.R_2_instances_name_tags,
186
    re.compile(r'^/2/instances/(%s)/reboot$' % instance_name_pattern):
187
      rlib2.R_2_instances_name_reboot,
188
    re.compile(r'^/2/instances/(%s)/reinstall$' % instance_name_pattern):
189
      rlib2.R_2_instances_name_reinstall,
190
    re.compile(r'^/2/instances/(%s)/replace-disks$' % instance_name_pattern):
191
      rlib2.R_2_instances_name_replace_disks,
192
    re.compile(r'^/2/instances/(%s)/shutdown$' % instance_name_pattern):
193
      rlib2.R_2_instances_name_shutdown,
194
    re.compile(r'^/2/instances/(%s)/startup$' % instance_name_pattern):
195
      rlib2.R_2_instances_name_startup,
196

    
197
    "/2/jobs": rlib2.R_2_jobs,
198
    re.compile(r'/2/jobs/(%s)$' % job_id_pattern):
199
      rlib2.R_2_jobs_id,
200

    
201
    "/2/tags": rlib2.R_2_tags,
202
    "/2/info": rlib2.R_2_info,
203
    "/2/os": rlib2.R_2_os,
204
    }
205

    
206

    
207
CONNECTOR.update(GetHandlers(_NAME_PATTERN, _NAME_PATTERN,
208
                             constants.JOB_ID_TEMPLATE))