Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / connector.py @ 1e82bc80

History | View | Annotate | Download (4.7 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
# the connection map is created at the end of this file
35
CONNECTOR = {}
36

    
37

    
38
class Mapper:
39
  """Map resource to method.
40

41
  """
42
  def __init__(self, connector=CONNECTOR):
43
    """Resource mapper constructor.
44

45
    @param connector: a dictionary, mapping method name with URL path regexp
46

47
    """
48
    self._connector = connector
49

    
50
  def getController(self, uri):
51
    """Find method for a given URI.
52

53
    @param uri: string with URI
54

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

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

    
70
    result = None
71

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

    
80
      # String objects
81
      elif key == path:
82
        result = (handler, [], args)
83
        break
84

    
85
    if result:
86
      return result
87
    else:
88
      raise http.HttpNotFound()
89

    
90

    
91
class R_root(baserlib.R_Generic):
92
  """/ resource.
93

94
  """
95
  def GET(self):
96
    """Show the list of mapped resources.
97

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

100
    """
101
    root_pattern = re.compile('^R_([a-zA-Z0-9]+)$')
102

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

    
111
    return baserlib.BuildUriList(rootlist, "/%s")
112

    
113

    
114
def _getResources(id):
115
  """Return a list of resources underneath given id.
116

117
  This is to generalize querying of version resources lists.
118

119
  @return: a list of resources names.
120

121
  """
122
  r_pattern = re.compile('^R_%s_([a-zA-Z0-9]+)$' % id)
123

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

    
131
  return rlist
132

    
133

    
134
class R_2(baserlib.R_Generic):
135
  """ /2 resource, the root of the version 2 API.
136

137
  """
138
  def GET(self):
139
    """Show the list of mapped resources.
140

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

143
    """
144
    return baserlib.BuildUriList(_getResources("2"), "/2/%s")
145

    
146

    
147
CONNECTOR.update({
148
  "/": R_root,
149

    
150
  "/version": rlib2.R_version,
151

    
152
  "/2": R_2,
153
  "/2/jobs": rlib2.R_2_jobs,
154
  "/2/nodes": rlib2.R_2_nodes,
155
  re.compile(r'^/2/nodes/([\w\._-]+)$'): rlib2.R_2_nodes_name,
156
  re.compile(r'^/2/nodes/([\w\._-]+)/tags$'): rlib2.R_2_nodes_name_tags,
157
  re.compile(r'^/2/nodes/([\w\._-]+)/role$'): rlib2.R_2_nodes_name_role,
158
  re.compile(r'^/2/nodes/([\w\._-]+)/evacuate$'):
159
      rlib2.R_2_nodes_name_evacuate,
160
  re.compile(r'^/2/nodes/([\w\._-]+)/migrate$'):
161
      rlib2.R_2_nodes_name_migrate,
162
  re.compile(r'^/2/nodes/([\w\._-]+)/storage$'):
163
      rlib2.R_2_nodes_name_storage,
164
  re.compile(r'^/2/nodes/([\w\._-]+)/storage/modify$'):
165
      rlib2.R_2_nodes_name_storage_modify,
166
  "/2/instances": rlib2.R_2_instances,
167
  re.compile(r'^/2/instances/([\w\._-]+)$'): rlib2.R_2_instances_name,
168
  re.compile(r'^/2/instances/([\w\._-]+)/tags$'): rlib2.R_2_instances_name_tags,
169
  re.compile(r'^/2/instances/([\w\._-]+)/reboot$'):
170
      rlib2.R_2_instances_name_reboot,
171
  re.compile(r'^/2/instances/([\w\._-]+)/reinstall$'):
172
      rlib2.R_2_instances_name_reinstall,
173
  re.compile(r'^/2/instances/([\w\._-]+)/shutdown$'):
174
      rlib2.R_2_instances_name_shutdown,
175
  re.compile(r'^/2/instances/([\w\._-]+)/startup$'):
176
      rlib2.R_2_instances_name_startup,
177
  re.compile(r'/2/jobs/(%s)$' % constants.JOB_ID_TEMPLATE): rlib2.R_2_jobs_id,
178
  "/2/tags": rlib2.R_2_tags,
179
  "/2/info": rlib2.R_2_info,
180
  "/2/os": rlib2.R_2_os,
181
  })