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  # All rights reserved. 
  6  # 
  7  # Redistribution and use in source and binary forms, with or without 
  8  # modification, are permitted provided that the following conditions are 
  9  # met: 
 10  # 
 11  # 1. Redistributions of source code must retain the above copyright notice, 
 12  # this list of conditions and the following disclaimer. 
 13  # 
 14  # 2. Redistributions in binary form must reproduce the above copyright 
 15  # notice, this list of conditions and the following disclaimer in the 
 16  # documentation and/or other materials provided with the distribution. 
 17  # 
 18  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
 19  # IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
 20  # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 
 21  # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
 22  # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 23  # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 24  # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 25  # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 26  # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 27  # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 28  # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 29   
 30  """Remote API connection map. 
 31   
 32  """ 
 33   
 34  # pylint: disable=C0103 
 35   
 36  # C0103: Invalid name, since the R_* names are not conforming 
 37   
 38  import re 
 39  import urlparse 
 40   
 41  from ganeti import constants 
 42  from ganeti import http 
 43  from ganeti import utils 
 44   
 45  from ganeti.rapi import rlib2 
 46   
 47   
 48  _NAME_PATTERN = r"[\w\._-]+" 
 49  _DISK_PATTERN = r"\d+" 
 50   
 51  # the connection map is created at the end of this file 
 52  CONNECTOR = {} 
 53   
 54   
55 -class Mapper(object):
56 """Map resource to method. 57 58 """
59 - def __init__(self, connector=None):
60 """Resource mapper constructor. 61 62 @param connector: a dictionary, mapping method name with URL path regexp 63 64 """ 65 if connector is None: 66 connector = CONNECTOR 67 self._connector = connector
68
69 - def getController(self, uri):
70 """Find method for a given URI. 71 72 @param uri: string with URI 73 74 @return: None if no method is found or a tuple containing 75 the following fields: 76 - method: name of method mapped to URI 77 - items: a list of variable intems in the path 78 - args: a dictionary with additional parameters from URL 79 80 """ 81 if "?" in uri: 82 (path, query) = uri.split("?", 1) 83 args = urlparse.parse_qs(query) 84 else: 85 path = uri 86 query = None 87 args = {} 88 89 # Try to find handler for request path 90 result = utils.FindMatch(self._connector, path) 91 92 if result is None: 93 raise http.HttpNotFound() 94 95 (handler, groups) = result 96 97 return (handler, groups, args)
98 99
100 -def _ConvertPattern(value):
101 """Converts URI pattern into a regular expression group. 102 103 Used by L{_CompileHandlerPath}. 104 105 """ 106 if isinstance(value, UriPattern): 107 return "(%s)" % value.content 108 else: 109 return value
110 111
112 -def _CompileHandlerPath(*args):
113 """Compiles path for RAPI resource into regular expression. 114 115 @return: Compiled regular expression object 116 117 """ 118 return re.compile("^%s$" % "".join(map(_ConvertPattern, args)))
119 120
121 -class UriPattern(object):
122 __slots__ = [ 123 "content", 124 ] 125
126 - def __init__(self, content):
127 self.content = content
128 129
130 -def GetHandlers(node_name_pattern, instance_name_pattern, 131 group_name_pattern, network_name_pattern, 132 job_id_pattern, disk_pattern, filter_pattern, 133 query_res_pattern, 134 translate=None):
135 """Returns all supported resources and their handlers. 136 137 C{node_name_pattern} and the other C{*_pattern} parameters are wrapped in 138 L{UriPattern} and, if used in a URI, passed to the function specified using 139 C{translate}. C{translate} receives 1..N parameters which are either plain 140 strings or instances of L{UriPattern} and returns a dictionary key suitable 141 for the caller of C{GetHandlers}. The default implementation in 142 L{_CompileHandlerPath} returns a compiled regular expression in which each 143 pattern is a group. 144 145 @rtype: dict 146 147 """ 148 if translate is None: 149 translate_fn = _CompileHandlerPath 150 else: 151 translate_fn = translate 152 153 node_name = UriPattern(node_name_pattern) 154 instance_name = UriPattern(instance_name_pattern) 155 group_name = UriPattern(group_name_pattern) 156 network_name = UriPattern(network_name_pattern) 157 job_id = UriPattern(job_id_pattern) 158 disk = UriPattern(disk_pattern) 159 filter_uuid = UriPattern(filter_pattern) 160 query_res = UriPattern(query_res_pattern) 161 162 # Important note: New resources should always be added under /2. During a 163 # discussion in July 2010 it was decided that having per-resource versions 164 # is more flexible and future-compatible than versioning the whole remote 165 # API. 166 # TODO: Consider a different data structure where all keys are of the same 167 # type. Strings are faster to look up in a dictionary than iterating and 168 # matching regular expressions, therefore maybe two separate dictionaries 169 # should be used. 170 return { 171 "/": rlib2.R_root, 172 "/2": rlib2.R_2, 173 174 "/version": rlib2.R_version, 175 176 "/2/nodes": rlib2.R_2_nodes, 177 178 translate_fn("/2/nodes/", node_name): 179 rlib2.R_2_nodes_name, 180 translate_fn("/2/nodes/", node_name, "/powercycle"): 181 rlib2.R_2_nodes_name_powercycle, 182 translate_fn("/2/nodes/", node_name, "/tags"): 183 rlib2.R_2_nodes_name_tags, 184 translate_fn("/2/nodes/", node_name, "/role"): 185 rlib2.R_2_nodes_name_role, 186 translate_fn("/2/nodes/", node_name, "/evacuate"): 187 rlib2.R_2_nodes_name_evacuate, 188 translate_fn("/2/nodes/", node_name, "/migrate"): 189 rlib2.R_2_nodes_name_migrate, 190 translate_fn("/2/nodes/", node_name, "/modify"): 191 rlib2.R_2_nodes_name_modify, 192 translate_fn("/2/nodes/", node_name, "/storage"): 193 rlib2.R_2_nodes_name_storage, 194 translate_fn("/2/nodes/", node_name, "/storage/modify"): 195 rlib2.R_2_nodes_name_storage_modify, 196 translate_fn("/2/nodes/", node_name, "/storage/repair"): 197 rlib2.R_2_nodes_name_storage_repair, 198 199 "/2/instances": rlib2.R_2_instances, 200 translate_fn("/2/instances/", instance_name): 201 rlib2.R_2_instances_name, 202 translate_fn("/2/instances/", instance_name, "/info"): 203 rlib2.R_2_instances_name_info, 204 translate_fn("/2/instances/", instance_name, "/tags"): 205 rlib2.R_2_instances_name_tags, 206 translate_fn("/2/instances/", instance_name, "/reboot"): 207 rlib2.R_2_instances_name_reboot, 208 translate_fn("/2/instances/", instance_name, "/reinstall"): 209 rlib2.R_2_instances_name_reinstall, 210 translate_fn("/2/instances/", instance_name, "/replace-disks"): 211 rlib2.R_2_instances_name_replace_disks, 212 translate_fn("/2/instances/", instance_name, "/shutdown"): 213 rlib2.R_2_instances_name_shutdown, 214 translate_fn("/2/instances/", instance_name, "/startup"): 215 rlib2.R_2_instances_name_startup, 216 translate_fn("/2/instances/", instance_name, "/activate-disks"): 217 rlib2.R_2_instances_name_activate_disks, 218 translate_fn("/2/instances/", instance_name, "/deactivate-disks"): 219 rlib2.R_2_instances_name_deactivate_disks, 220 translate_fn("/2/instances/", instance_name, "/recreate-disks"): 221 rlib2.R_2_instances_name_recreate_disks, 222 translate_fn("/2/instances/", instance_name, "/prepare-export"): 223 rlib2.R_2_instances_name_prepare_export, 224 translate_fn("/2/instances/", instance_name, "/export"): 225 rlib2.R_2_instances_name_export, 226 translate_fn("/2/instances/", instance_name, "/migrate"): 227 rlib2.R_2_instances_name_migrate, 228 translate_fn("/2/instances/", instance_name, "/failover"): 229 rlib2.R_2_instances_name_failover, 230 translate_fn("/2/instances/", instance_name, "/rename"): 231 rlib2.R_2_instances_name_rename, 232 translate_fn("/2/instances/", instance_name, "/modify"): 233 rlib2.R_2_instances_name_modify, 234 translate_fn("/2/instances/", instance_name, "/disk/", disk, "/grow"): 235 rlib2.R_2_instances_name_disk_grow, 236 translate_fn("/2/instances/", instance_name, "/console"): 237 rlib2.R_2_instances_name_console, 238 239 "/2/networks": rlib2.R_2_networks, 240 translate_fn("/2/networks/", network_name): 241 rlib2.R_2_networks_name, 242 translate_fn("/2/networks/", network_name, "/connect"): 243 rlib2.R_2_networks_name_connect, 244 translate_fn("/2/networks/", network_name, "/disconnect"): 245 rlib2.R_2_networks_name_disconnect, 246 translate_fn("/2/networks/", network_name, "/modify"): 247 rlib2.R_2_networks_name_modify, 248 translate_fn("/2/networks/", network_name, "/tags"): 249 rlib2.R_2_networks_name_tags, 250 251 "/2/groups": rlib2.R_2_groups, 252 translate_fn("/2/groups/", group_name): 253 rlib2.R_2_groups_name, 254 translate_fn("/2/groups/", group_name, "/modify"): 255 rlib2.R_2_groups_name_modify, 256 translate_fn("/2/groups/", group_name, "/rename"): 257 rlib2.R_2_groups_name_rename, 258 translate_fn("/2/groups/", group_name, "/assign-nodes"): 259 rlib2.R_2_groups_name_assign_nodes, 260 translate_fn("/2/groups/", group_name, "/tags"): 261 rlib2.R_2_groups_name_tags, 262 263 "/2/jobs": rlib2.R_2_jobs, 264 translate_fn("/2/jobs/", job_id): 265 rlib2.R_2_jobs_id, 266 translate_fn("/2/jobs/", job_id, "/wait"): 267 rlib2.R_2_jobs_id_wait, 268 269 "/2/instances-multi-alloc": rlib2.R_2_instances_multi_alloc, 270 "/2/tags": rlib2.R_2_tags, 271 "/2/info": rlib2.R_2_info, 272 "/2/os": rlib2.R_2_os, 273 "/2/redistribute-config": rlib2.R_2_redist_config, 274 "/2/features": rlib2.R_2_features, 275 "/2/modify": rlib2.R_2_cluster_modify, 276 277 translate_fn("/2/query/", query_res): 278 rlib2.R_2_query, 279 translate_fn("/2/query/", query_res, "/fields"): 280 rlib2.R_2_query_fields, 281 282 "/2/filters": rlib2.R_2_filters, 283 translate_fn("/2/filters/", filter_uuid): 284 rlib2.R_2_filters_uuid, 285 }
286 287 288 CONNECTOR.update(GetHandlers(_NAME_PATTERN, _NAME_PATTERN, 289 _NAME_PATTERN, _NAME_PATTERN, 290 constants.JOB_ID_TEMPLATE, _DISK_PATTERN, 291 _NAME_PATTERN, _NAME_PATTERN)) 292