Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / connector.py @ fe267188

History | View | Annotate | Download (4.4 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
# pylint: disable-msg=C0103
26

    
27
# C0103: Invalid name, since the R_* names are not conforming
28

    
29
import cgi
30
import re
31

    
32
from ganeti import constants
33
from ganeti import http
34

    
35
from ganeti.rapi import baserlib
36
from ganeti.rapi import rlib2
37

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

    
41

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

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

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

51
    """
52
    self._connector = connector
53

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

57
    @param uri: string with URI
58

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

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

    
74
    result = None
75

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

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

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

    
94

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

98
  """
99
  DOC_URI = "/"
100

    
101
  def GET(self):
102
    """Show the list of mapped resources.
103

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

106
    """
107
    root_pattern = re.compile('^R_([a-zA-Z0-9]+)$')
108

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

    
117
    return baserlib.BuildUriList(rootlist, "/%s")
118

    
119

    
120
def _getResources(id):
121
  """Return a list of resources underneath given id.
122

123
  This is to generalize querying of version resources lists.
124

125
  @return: a list of resources names.
126

127
  """
128
  r_pattern = re.compile('^R_%s_([a-zA-Z0-9]+)$' % id)
129

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

    
137
  return rlist
138

    
139

    
140
class R_2(baserlib.R_Generic):
141
  """ /2 resource, the root of the version 2 API.
142

143
  """
144
  DOC_URI = "/2"
145

    
146
  def GET(self):
147
    """Show the list of mapped resources.
148

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

151
    """
152
    return baserlib.BuildUriList(_getResources("2"), "/2/%s")
153

    
154

    
155
CONNECTOR.update({
156
  "/": R_root,
157

    
158
  "/version": rlib2.R_version,
159

    
160
  "/2": R_2,
161
  "/2/jobs": rlib2.R_2_jobs,
162
  "/2/nodes": rlib2.R_2_nodes,
163
  re.compile(r'^/2/nodes/([\w\._-]+)$'): rlib2.R_2_nodes_name,
164
  re.compile(r'^/2/nodes/([\w\._-]+)/tags$'): rlib2.R_2_nodes_name_tags,
165
  "/2/instances": rlib2.R_2_instances,
166
  re.compile(r'^/2/instances/([\w\._-]+)$'): rlib2.R_2_instances_name,
167
  re.compile(r'^/2/instances/([\w\._-]+)/tags$'): rlib2.R_2_instances_name_tags,
168
  re.compile(r'^/2/instances/([\w\._-]+)/reboot$'):
169
      rlib2.R_2_instances_name_reboot,
170
  re.compile(r'^/2/instances/([\w\._-]+)/reinstall$'):
171
      rlib2.R_2_instances_name_reinstall,
172
  re.compile(r'^/2/instances/([\w\._-]+)/shutdown$'):
173
      rlib2.R_2_instances_name_shutdown,
174
  re.compile(r'^/2/instances/([\w\._-]+)/startup$'):
175
      rlib2.R_2_instances_name_startup,
176
  re.compile(r'/2/jobs/(%s)$' % constants.JOB_ID_TEMPLATE): rlib2.R_2_jobs_id,
177
  "/2/tags": rlib2.R_2_tags,
178
  "/2/info": rlib2.R_2_info,
179
  "/2/os": rlib2.R_2_os,
180
  })