Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / connector.py @ 18cb43a2

History | View | Annotate | Download (4.2 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
  DOC_URI = "/"
96

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

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

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

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

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

    
115

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

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

121
  @return: a list of resources names.
122

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

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

    
133
  return rlist
134

    
135

    
136
class R_2(baserlib.R_Generic):
137
  """ /2 resourse.
138

139
  """
140
  DOC_URI = "/2"
141

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

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

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

    
150

    
151
CONNECTOR.update({
152
  "/": R_root,
153

    
154
  "/version": rlib2.R_version,
155

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