Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / connector.py @ a52978c7

History | View | Annotate | Download (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
# pylint: disable=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
from ganeti import utils
35

    
36
from ganeti.rapi import rlib2
37

    
38

    
39
_NAME_PATTERN = r"[\w\._-]+"
40
_DISK_PATTERN = r"\d+"
41

    
42
# the connection map is created at the end of this file
43
CONNECTOR = {}
44

    
45

    
46
class Mapper:
47
  """Map resource to method.
48

49
  """
50
  def __init__(self, connector=None):
51
    """Resource mapper constructor.
52

53
    @param connector: a dictionary, mapping method name with URL path regexp
54

55
    """
56
    if connector is None:
57
      connector = CONNECTOR
58
    self._connector = connector
59

    
60
  def getController(self, uri):
61
    """Find method for a given URI.
62

63
    @param uri: string with URI
64

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

71
    """
72
    if "?" in uri:
73
      (path, query) = uri.split("?", 1)
74
      args = cgi.parse_qs(query)
75
    else:
76
      path = uri
77
      query = None
78
      args = {}
79

    
80
    # Try to find handler for request path
81
    result = utils.FindMatch(self._connector, path)
82

    
83
    if result is None:
84
      raise http.HttpNotFound()
85

    
86
    (handler, groups) = result
87

    
88
    return (handler, groups, args)
89

    
90

    
91
def GetHandlers(node_name_pattern, instance_name_pattern,
92
                group_name_pattern, job_id_pattern, disk_pattern,
93
                query_res_pattern):
94
  """Returns all supported resources and their handlers.
95

96
  """
97
  # Important note: New resources should always be added under /2. During a
98
  # discussion in July 2010 it was decided that having per-resource versions
99
  # is more flexible and future-compatible than versioning the whole remote
100
  # API.
101
  return {
102
    "/": rlib2.R_root,
103
    "/2": rlib2.R_2,
104

    
105
    "/version": rlib2.R_version,
106

    
107
    "/2/nodes": rlib2.R_2_nodes,
108
    re.compile(r"^/2/nodes/(%s)$" % node_name_pattern):
109
      rlib2.R_2_nodes_name,
110
    re.compile(r"^/2/nodes/(%s)/tags$" % node_name_pattern):
111
      rlib2.R_2_nodes_name_tags,
112
    re.compile(r"^/2/nodes/(%s)/role$" % node_name_pattern):
113
      rlib2.R_2_nodes_name_role,
114
    re.compile(r"^/2/nodes/(%s)/evacuate$" % node_name_pattern):
115
      rlib2.R_2_nodes_name_evacuate,
116
    re.compile(r"^/2/nodes/(%s)/migrate$" % node_name_pattern):
117
      rlib2.R_2_nodes_name_migrate,
118
    re.compile(r"^/2/nodes/(%s)/storage$" % node_name_pattern):
119
      rlib2.R_2_nodes_name_storage,
120
    re.compile(r"^/2/nodes/(%s)/storage/modify$" % node_name_pattern):
121
      rlib2.R_2_nodes_name_storage_modify,
122
    re.compile(r"^/2/nodes/(%s)/storage/repair$" % node_name_pattern):
123
      rlib2.R_2_nodes_name_storage_repair,
124

    
125
    "/2/instances": rlib2.R_2_instances,
126
    re.compile(r"^/2/instances/(%s)$" % instance_name_pattern):
127
      rlib2.R_2_instances_name,
128
    re.compile(r"^/2/instances/(%s)/info$" % instance_name_pattern):
129
      rlib2.R_2_instances_name_info,
130
    re.compile(r"^/2/instances/(%s)/tags$" % instance_name_pattern):
131
      rlib2.R_2_instances_name_tags,
132
    re.compile(r"^/2/instances/(%s)/reboot$" % instance_name_pattern):
133
      rlib2.R_2_instances_name_reboot,
134
    re.compile(r"^/2/instances/(%s)/reinstall$" % instance_name_pattern):
135
      rlib2.R_2_instances_name_reinstall,
136
    re.compile(r"^/2/instances/(%s)/replace-disks$" % instance_name_pattern):
137
      rlib2.R_2_instances_name_replace_disks,
138
    re.compile(r"^/2/instances/(%s)/shutdown$" % instance_name_pattern):
139
      rlib2.R_2_instances_name_shutdown,
140
    re.compile(r"^/2/instances/(%s)/startup$" % instance_name_pattern):
141
      rlib2.R_2_instances_name_startup,
142
    re.compile(r"^/2/instances/(%s)/activate-disks$" % instance_name_pattern):
143
      rlib2.R_2_instances_name_activate_disks,
144
    re.compile(r"^/2/instances/(%s)/deactivate-disks$" % instance_name_pattern):
145
      rlib2.R_2_instances_name_deactivate_disks,
146
    re.compile(r"^/2/instances/(%s)/recreate-disks$" % instance_name_pattern):
147
      rlib2.R_2_instances_name_recreate_disks,
148
    re.compile(r"^/2/instances/(%s)/prepare-export$" % instance_name_pattern):
149
      rlib2.R_2_instances_name_prepare_export,
150
    re.compile(r"^/2/instances/(%s)/export$" % instance_name_pattern):
151
      rlib2.R_2_instances_name_export,
152
    re.compile(r"^/2/instances/(%s)/migrate$" % instance_name_pattern):
153
      rlib2.R_2_instances_name_migrate,
154
    re.compile(r"^/2/instances/(%s)/failover$" % instance_name_pattern):
155
      rlib2.R_2_instances_name_failover,
156
    re.compile(r"^/2/instances/(%s)/rename$" % instance_name_pattern):
157
      rlib2.R_2_instances_name_rename,
158
    re.compile(r"^/2/instances/(%s)/modify$" % instance_name_pattern):
159
      rlib2.R_2_instances_name_modify,
160
    re.compile(r"^/2/instances/(%s)/disk/(%s)/grow$" %
161
               (instance_name_pattern, disk_pattern)):
162
      rlib2.R_2_instances_name_disk_grow,
163
    re.compile(r"^/2/instances/(%s)/console$" % instance_name_pattern):
164
      rlib2.R_2_instances_name_console,
165

    
166
    "/2/groups": rlib2.R_2_groups,
167
    re.compile(r"^/2/groups/(%s)$" % group_name_pattern):
168
      rlib2.R_2_groups_name,
169
    re.compile(r"^/2/groups/(%s)/modify$" % group_name_pattern):
170
      rlib2.R_2_groups_name_modify,
171
    re.compile(r"^/2/groups/(%s)/rename$" % group_name_pattern):
172
      rlib2.R_2_groups_name_rename,
173
    re.compile(r"^/2/groups/(%s)/assign-nodes$" % group_name_pattern):
174
      rlib2.R_2_groups_name_assign_nodes,
175
    re.compile(r"^/2/groups/(%s)/tags$" % group_name_pattern):
176
      rlib2.R_2_groups_name_tags,
177

    
178
    "/2/jobs": rlib2.R_2_jobs,
179
    re.compile(r"^/2/jobs/(%s)$" % job_id_pattern):
180
      rlib2.R_2_jobs_id,
181
    re.compile(r"^/2/jobs/(%s)/wait$" % job_id_pattern):
182
      rlib2.R_2_jobs_id_wait,
183

    
184
    "/2/tags": rlib2.R_2_tags,
185
    "/2/info": rlib2.R_2_info,
186
    "/2/os": rlib2.R_2_os,
187
    "/2/redistribute-config": rlib2.R_2_redist_config,
188
    "/2/features": rlib2.R_2_features,
189
    "/2/modify": rlib2.R_2_cluster_modify,
190
    re.compile(r"^/2/query/(%s)$" % query_res_pattern): rlib2.R_2_query,
191
    re.compile(r"^/2/query/(%s)/fields$" % query_res_pattern):
192
      rlib2.R_2_query_fields,
193
    }
194

    
195

    
196
CONNECTOR.update(GetHandlers(_NAME_PATTERN, _NAME_PATTERN, _NAME_PATTERN,
197
                             constants.JOB_ID_TEMPLATE, _DISK_PATTERN,
198
                             _NAME_PATTERN))