Package ganeti :: Package rapi :: Module connector
[hide private]
[frames] | no frames]

Source Code for Module ganeti.rapi.connector

  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 re 
 30  import urlparse 
 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 = urlparse.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 _ConvertPattern(value):
92 """Converts URI pattern into a regular expression group. 93 94 Used by L{_CompileHandlerPath}. 95 96 """ 97 if isinstance(value, UriPattern): 98 return "(%s)" % value.content 99 else: 100 return value
101 102
103 -def _CompileHandlerPath(*args):
104 """Compiles path for RAPI resource into regular expression. 105 106 @return: Compiled regular expression object 107 108 """ 109 return re.compile("^%s$" % "".join(map(_ConvertPattern, args)))
110 111
112 -class UriPattern(object):
113 __slots__ = [ 114 "content", 115 ] 116
117 - def __init__(self, content):
118 self.content = content
119 120
121 -def GetHandlers(node_name_pattern, instance_name_pattern, 122 group_name_pattern, network_name_pattern, 123 job_id_pattern, disk_pattern, 124 query_res_pattern, 125 translate=None):
126 """Returns all supported resources and their handlers. 127 128 C{node_name_pattern} and the other C{*_pattern} parameters are wrapped in 129 L{UriPattern} and, if used in a URI, passed to the function specified using 130 C{translate}. C{translate} receives 1..N parameters which are either plain 131 strings or instances of L{UriPattern} and returns a dictionary key suitable 132 for the caller of C{GetHandlers}. The default implementation in 133 L{_CompileHandlerPath} returns a compiled regular expression in which each 134 pattern is a group. 135 136 @rtype: dict 137 138 """ 139 if translate is None: 140 translate_fn = _CompileHandlerPath 141 else: 142 translate_fn = translate 143 144 node_name = UriPattern(node_name_pattern) 145 instance_name = UriPattern(instance_name_pattern) 146 group_name = UriPattern(group_name_pattern) 147 network_name = UriPattern(network_name_pattern) 148 job_id = UriPattern(job_id_pattern) 149 disk = UriPattern(disk_pattern) 150 query_res = UriPattern(query_res_pattern) 151 152 # Important note: New resources should always be added under /2. During a 153 # discussion in July 2010 it was decided that having per-resource versions 154 # is more flexible and future-compatible than versioning the whole remote 155 # API. 156 # TODO: Consider a different data structure where all keys are of the same 157 # type. Strings are faster to look up in a dictionary than iterating and 158 # matching regular expressions, therefore maybe two separate dictionaries 159 # should be used. 160 return { 161 "/": rlib2.R_root, 162 "/2": rlib2.R_2, 163 164 "/version": rlib2.R_version, 165 166 "/2/nodes": rlib2.R_2_nodes, 167 168 translate_fn("/2/nodes/", node_name): 169 rlib2.R_2_nodes_name, 170 translate_fn("/2/nodes/", node_name, "/powercycle"): 171 rlib2.R_2_nodes_name_powercycle, 172 translate_fn("/2/nodes/", node_name, "/tags"): 173 rlib2.R_2_nodes_name_tags, 174 translate_fn("/2/nodes/", node_name, "/role"): 175 rlib2.R_2_nodes_name_role, 176 translate_fn("/2/nodes/", node_name, "/evacuate"): 177 rlib2.R_2_nodes_name_evacuate, 178 translate_fn("/2/nodes/", node_name, "/migrate"): 179 rlib2.R_2_nodes_name_migrate, 180 translate_fn("/2/nodes/", node_name, "/modify"): 181 rlib2.R_2_nodes_name_modify, 182 translate_fn("/2/nodes/", node_name, "/storage"): 183 rlib2.R_2_nodes_name_storage, 184 translate_fn("/2/nodes/", node_name, "/storage/modify"): 185 rlib2.R_2_nodes_name_storage_modify, 186 translate_fn("/2/nodes/", node_name, "/storage/repair"): 187 rlib2.R_2_nodes_name_storage_repair, 188 189 "/2/instances": rlib2.R_2_instances, 190 translate_fn("/2/instances/", instance_name): 191 rlib2.R_2_instances_name, 192 translate_fn("/2/instances/", instance_name, "/info"): 193 rlib2.R_2_instances_name_info, 194 translate_fn("/2/instances/", instance_name, "/tags"): 195 rlib2.R_2_instances_name_tags, 196 translate_fn("/2/instances/", instance_name, "/reboot"): 197 rlib2.R_2_instances_name_reboot, 198 translate_fn("/2/instances/", instance_name, "/reinstall"): 199 rlib2.R_2_instances_name_reinstall, 200 translate_fn("/2/instances/", instance_name, "/replace-disks"): 201 rlib2.R_2_instances_name_replace_disks, 202 translate_fn("/2/instances/", instance_name, "/shutdown"): 203 rlib2.R_2_instances_name_shutdown, 204 translate_fn("/2/instances/", instance_name, "/startup"): 205 rlib2.R_2_instances_name_startup, 206 translate_fn("/2/instances/", instance_name, "/activate-disks"): 207 rlib2.R_2_instances_name_activate_disks, 208 translate_fn("/2/instances/", instance_name, "/deactivate-disks"): 209 rlib2.R_2_instances_name_deactivate_disks, 210 translate_fn("/2/instances/", instance_name, "/recreate-disks"): 211 rlib2.R_2_instances_name_recreate_disks, 212 translate_fn("/2/instances/", instance_name, "/prepare-export"): 213 rlib2.R_2_instances_name_prepare_export, 214 translate_fn("/2/instances/", instance_name, "/export"): 215 rlib2.R_2_instances_name_export, 216 translate_fn("/2/instances/", instance_name, "/migrate"): 217 rlib2.R_2_instances_name_migrate, 218 translate_fn("/2/instances/", instance_name, "/failover"): 219 rlib2.R_2_instances_name_failover, 220 translate_fn("/2/instances/", instance_name, "/rename"): 221 rlib2.R_2_instances_name_rename, 222 translate_fn("/2/instances/", instance_name, "/modify"): 223 rlib2.R_2_instances_name_modify, 224 translate_fn("/2/instances/", instance_name, "/disk/", disk, "/grow"): 225 rlib2.R_2_instances_name_disk_grow, 226 translate_fn("/2/instances/", instance_name, "/console"): 227 rlib2.R_2_instances_name_console, 228 229 "/2/networks": rlib2.R_2_networks, 230 translate_fn("/2/networks/", network_name): 231 rlib2.R_2_networks_name, 232 translate_fn("/2/networks/", network_name, "/connect"): 233 rlib2.R_2_networks_name_connect, 234 translate_fn("/2/networks/", network_name, "/disconnect"): 235 rlib2.R_2_networks_name_disconnect, 236 translate_fn("/2/networks/", network_name, "/modify"): 237 rlib2.R_2_networks_name_modify, 238 translate_fn("/2/networks/", network_name, "/tags"): 239 rlib2.R_2_networks_name_tags, 240 241 "/2/groups": rlib2.R_2_groups, 242 translate_fn("/2/groups/", group_name): 243 rlib2.R_2_groups_name, 244 translate_fn("/2/groups/", group_name, "/modify"): 245 rlib2.R_2_groups_name_modify, 246 translate_fn("/2/groups/", group_name, "/rename"): 247 rlib2.R_2_groups_name_rename, 248 translate_fn("/2/groups/", group_name, "/assign-nodes"): 249 rlib2.R_2_groups_name_assign_nodes, 250 translate_fn("/2/groups/", group_name, "/tags"): 251 rlib2.R_2_groups_name_tags, 252 253 "/2/jobs": rlib2.R_2_jobs, 254 translate_fn("/2/jobs/", job_id): 255 rlib2.R_2_jobs_id, 256 translate_fn("/2/jobs/", job_id, "/wait"): 257 rlib2.R_2_jobs_id_wait, 258 259 "/2/instances-multi-alloc": rlib2.R_2_instances_multi_alloc, 260 "/2/tags": rlib2.R_2_tags, 261 "/2/info": rlib2.R_2_info, 262 "/2/os": rlib2.R_2_os, 263 "/2/redistribute-config": rlib2.R_2_redist_config, 264 "/2/features": rlib2.R_2_features, 265 "/2/modify": rlib2.R_2_cluster_modify, 266 267 translate_fn("/2/query/", query_res): 268 rlib2.R_2_query, 269 translate_fn("/2/query/", query_res, "/fields"): 270 rlib2.R_2_query_fields, 271 }
272 273 274 CONNECTOR.update(GetHandlers(_NAME_PATTERN, _NAME_PATTERN, 275 _NAME_PATTERN, _NAME_PATTERN, 276 constants.JOB_ID_TEMPLATE, _DISK_PATTERN, 277 _NAME_PATTERN)) 278