4 # Copyright (C) 2006, 2007, 2008 Google Inc.
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.
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.
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
21 """Remote API connection map.
25 # pylint: disable=C0103
27 # C0103: Invalid name, since the R_* names are not conforming
32 from ganeti import constants
33 from ganeti import http
34 from ganeti import utils
36 from ganeti.rapi import rlib2
39 _NAME_PATTERN = r"[\w\._-]+"
40 _DISK_PATTERN = r"\d+"
42 # the connection map is created at the end of this file
47 """Map resource to method.
50 def __init__(self, connector=None):
51 """Resource mapper constructor.
53 @param connector: a dictionary, mapping method name with URL path regexp
58 self._connector = connector
60 def getController(self, uri):
61 """Find method for a given URI.
63 @param uri: string with URI
65 @return: None if no method is found or a tuple containing
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
73 (path, query) = uri.split("?", 1)
74 args = cgi.parse_qs(query)
80 # Try to find handler for request path
81 result = utils.FindMatch(self._connector, path)
84 raise http.HttpNotFound()
86 (handler, groups) = result
88 return (handler, groups, args)
91 def GetHandlers(node_name_pattern, instance_name_pattern,
92 group_name_pattern, network_name_pattern,
93 job_id_pattern, disk_pattern,
95 """Returns all supported resources and their handlers.
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
106 "/version": rlib2.R_version,
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,
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,
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,
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,
195 "/2/jobs": rlib2.R_2_jobs,
196 re.compile(r"^/2/jobs/(%s)$" % job_id_pattern):
198 re.compile(r"^/2/jobs/(%s)/wait$" % job_id_pattern):
199 rlib2.R_2_jobs_id_wait,
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,
214 CONNECTOR.update(GetHandlers(_NAME_PATTERN, _NAME_PATTERN,
215 _NAME_PATTERN, _NAME_PATTERN,
216 constants.JOB_ID_TEMPLATE, _DISK_PATTERN,