Statistics
| Branch: | Tag: | Revision:

root / lib / rapi / connector.py @ 6e8091f9

History | View | Annotate | Download (7.9 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, network_name_pattern,
93
                job_id_pattern, disk_pattern,
94
                query_res_pattern):
95
  """Returns all supported resources and their handlers.
96

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

    
106
    "/version": rlib2.R_version,
107

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

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

    
171
    "/2/networks": rlib2.R_2_networks,
172
    re.compile(r"^/2/networks/(%s)$" % network_name_pattern):
173
      rlib2.R_2_networks_name,
174
    re.compile(r"^/2/networks/(%s)/connect$" % network_name_pattern):
175
      rlib2.R_2_networks_name_connect,
176
    re.compile(r"^/2/networks/(%s)/disconnect$" % network_name_pattern):
177
      rlib2.R_2_networks_name_disconnect,
178
    re.compile(r"^/2/networks/(%s)/modify$" % network_name_pattern):
179
      rlib2.R_2_networks_name_modify,
180
    re.compile(r"^/2/networks/(%s)/tags$" % network_name_pattern):
181
      rlib2.R_2_networks_name_tags,
182

    
183
    "/2/groups": rlib2.R_2_groups,
184
    re.compile(r"^/2/groups/(%s)$" % group_name_pattern):
185
      rlib2.R_2_groups_name,
186
    re.compile(r"^/2/groups/(%s)/modify$" % group_name_pattern):
187
      rlib2.R_2_groups_name_modify,
188
    re.compile(r"^/2/groups/(%s)/rename$" % group_name_pattern):
189
      rlib2.R_2_groups_name_rename,
190
    re.compile(r"^/2/groups/(%s)/assign-nodes$" % group_name_pattern):
191
      rlib2.R_2_groups_name_assign_nodes,
192
    re.compile(r"^/2/groups/(%s)/tags$" % group_name_pattern):
193
      rlib2.R_2_groups_name_tags,
194

    
195
    "/2/jobs": rlib2.R_2_jobs,
196
    re.compile(r"^/2/jobs/(%s)$" % job_id_pattern):
197
      rlib2.R_2_jobs_id,
198
    re.compile(r"^/2/jobs/(%s)/wait$" % job_id_pattern):
199
      rlib2.R_2_jobs_id_wait,
200

    
201
    "/2/instances-multi-alloc": rlib2.R_2_instances_multi_alloc,
202
    "/2/tags": rlib2.R_2_tags,
203
    "/2/info": rlib2.R_2_info,
204
    "/2/os": rlib2.R_2_os,
205
    "/2/redistribute-config": rlib2.R_2_redist_config,
206
    "/2/features": rlib2.R_2_features,
207
    "/2/modify": rlib2.R_2_cluster_modify,
208
    re.compile(r"^/2/query/(%s)$" % query_res_pattern): rlib2.R_2_query,
209
    re.compile(r"^/2/query/(%s)/fields$" % query_res_pattern):
210
      rlib2.R_2_query_fields,
211
    }
212

    
213

    
214
CONNECTOR.update(GetHandlers(_NAME_PATTERN, _NAME_PATTERN,
215
                             _NAME_PATTERN, _NAME_PATTERN,
216
                             constants.JOB_ID_TEMPLATE, _DISK_PATTERN,
217
                             _NAME_PATTERN))