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-msg=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 baserlib 
 37  from ganeti.rapi import rlib2 
 38   
 39   
 40  _NAME_PATTERN = r"[\w\._-]+" 
 41  _DISK_PATTERN = r"\d+" 
 42   
 43  # the connection map is created at the end of this file 
 44  CONNECTOR = {} 
45 46 47 -class Mapper:
48 """Map resource to method. 49 50 """
51 - def __init__(self, connector=None):
52 """Resource mapper constructor. 53 54 @param connector: a dictionary, mapping method name with URL path regexp 55 56 """ 57 if connector is None: 58 connector = CONNECTOR 59 self._connector = connector
60
61 - def getController(self, uri):
62 """Find method for a given URI. 63 64 @param uri: string with URI 65 66 @return: None if no method is found or a tuple containing 67 the following fields: 68 - method: name of method mapped to URI 69 - items: a list of variable intems in the path 70 - args: a dictionary with additional parameters from URL 71 72 """ 73 if '?' in uri: 74 (path, query) = uri.split('?', 1) 75 args = cgi.parse_qs(query) 76 else: 77 path = uri 78 query = None 79 args = {} 80 81 # Try to find handler for request path 82 result = utils.FindMatch(self._connector, path) 83 84 if result is None: 85 raise http.HttpNotFound() 86 87 (handler, groups) = result 88 89 return (handler, groups, args)
90
91 92 -class R_root(baserlib.R_Generic):
93 """/ resource. 94 95 """ 96 _ROOT_PATTERN = re.compile("^R_([a-zA-Z0-9]+)$") 97 98 @classmethod
99 - def GET(cls):
100 """Show the list of mapped resources. 101 102 @return: a dictionary with 'name' and 'uri' keys for each of them. 103 104 """ 105 rootlist = [] 106 for handler in CONNECTOR.values(): 107 m = cls._ROOT_PATTERN.match(handler.__name__) 108 if m: 109 name = m.group(1) 110 if name != 'root': 111 rootlist.append(name) 112 113 return baserlib.BuildUriList(rootlist, "/%s")
114
115 116 -def _getResources(id_):
117 """Return a list of resources underneath given id. 118 119 This is to generalize querying of version resources lists. 120 121 @return: a list of resources names. 122 123 """ 124 r_pattern = re.compile('^R_%s_([a-zA-Z0-9]+)$' % id_) 125 126 rlist = [] 127 for handler in CONNECTOR.values(): 128 m = r_pattern.match(handler.__name__) 129 if m: 130 name = m.group(1) 131 rlist.append(name) 132 133 return rlist
134
135 136 -class R_2(baserlib.R_Generic):
137 """/2 resource. 138 139 This is the root of the version 2 API. 140 141 """ 142 @staticmethod
143 - def GET():
144 """Show the list of mapped resources. 145 146 @return: a dictionary with 'name' and 'uri' keys for each of them. 147 148 """ 149 return baserlib.BuildUriList(_getResources("2"), "/2/%s")
150
151 152 -def GetHandlers(node_name_pattern, instance_name_pattern, 153 group_name_pattern, job_id_pattern, disk_pattern):
154 """Returns all supported resources and their handlers. 155 156 """ 157 # Important note: New resources should always be added under /2. During a 158 # discussion in July 2010 it was decided that having per-resource versions 159 # is more flexible and future-compatible than versioning the whole remote 160 # API. 161 return { 162 "/": R_root, 163 164 "/version": rlib2.R_version, 165 166 "/2": R_2, 167 168 "/2/nodes": rlib2.R_2_nodes, 169 re.compile(r'^/2/nodes/(%s)$' % node_name_pattern): 170 rlib2.R_2_nodes_name, 171 re.compile(r'^/2/nodes/(%s)/tags$' % node_name_pattern): 172 rlib2.R_2_nodes_name_tags, 173 re.compile(r'^/2/nodes/(%s)/role$' % node_name_pattern): 174 rlib2.R_2_nodes_name_role, 175 re.compile(r'^/2/nodes/(%s)/evacuate$' % node_name_pattern): 176 rlib2.R_2_nodes_name_evacuate, 177 re.compile(r'^/2/nodes/(%s)/migrate$' % node_name_pattern): 178 rlib2.R_2_nodes_name_migrate, 179 re.compile(r'^/2/nodes/(%s)/storage$' % node_name_pattern): 180 rlib2.R_2_nodes_name_storage, 181 re.compile(r'^/2/nodes/(%s)/storage/modify$' % node_name_pattern): 182 rlib2.R_2_nodes_name_storage_modify, 183 re.compile(r'^/2/nodes/(%s)/storage/repair$' % node_name_pattern): 184 rlib2.R_2_nodes_name_storage_repair, 185 186 "/2/instances": rlib2.R_2_instances, 187 re.compile(r'^/2/instances/(%s)$' % instance_name_pattern): 188 rlib2.R_2_instances_name, 189 re.compile(r'^/2/instances/(%s)/info$' % instance_name_pattern): 190 rlib2.R_2_instances_name_info, 191 re.compile(r'^/2/instances/(%s)/tags$' % instance_name_pattern): 192 rlib2.R_2_instances_name_tags, 193 re.compile(r'^/2/instances/(%s)/reboot$' % instance_name_pattern): 194 rlib2.R_2_instances_name_reboot, 195 re.compile(r'^/2/instances/(%s)/reinstall$' % instance_name_pattern): 196 rlib2.R_2_instances_name_reinstall, 197 re.compile(r'^/2/instances/(%s)/replace-disks$' % instance_name_pattern): 198 rlib2.R_2_instances_name_replace_disks, 199 re.compile(r'^/2/instances/(%s)/shutdown$' % instance_name_pattern): 200 rlib2.R_2_instances_name_shutdown, 201 re.compile(r'^/2/instances/(%s)/startup$' % instance_name_pattern): 202 rlib2.R_2_instances_name_startup, 203 re.compile(r'^/2/instances/(%s)/activate-disks$' % instance_name_pattern): 204 rlib2.R_2_instances_name_activate_disks, 205 re.compile(r'^/2/instances/(%s)/deactivate-disks$' % instance_name_pattern): 206 rlib2.R_2_instances_name_deactivate_disks, 207 re.compile(r'^/2/instances/(%s)/prepare-export$' % instance_name_pattern): 208 rlib2.R_2_instances_name_prepare_export, 209 re.compile(r'^/2/instances/(%s)/export$' % instance_name_pattern): 210 rlib2.R_2_instances_name_export, 211 re.compile(r'^/2/instances/(%s)/migrate$' % instance_name_pattern): 212 rlib2.R_2_instances_name_migrate, 213 re.compile(r'^/2/instances/(%s)/rename$' % instance_name_pattern): 214 rlib2.R_2_instances_name_rename, 215 re.compile(r'^/2/instances/(%s)/modify$' % instance_name_pattern): 216 rlib2.R_2_instances_name_modify, 217 re.compile(r"^/2/instances/(%s)/disk/(%s)/grow$" % 218 (instance_name_pattern, disk_pattern)): 219 rlib2.R_2_instances_name_disk_grow, 220 re.compile(r'^/2/instances/(%s)/console$' % instance_name_pattern): 221 rlib2.R_2_instances_name_console, 222 223 "/2/groups": rlib2.R_2_groups, 224 re.compile(r'^/2/groups/(%s)$' % group_name_pattern): 225 rlib2.R_2_groups_name, 226 re.compile(r'^/2/groups/(%s)/modify$' % group_name_pattern): 227 rlib2.R_2_groups_name_modify, 228 re.compile(r'^/2/groups/(%s)/rename$' % group_name_pattern): 229 rlib2.R_2_groups_name_rename, 230 re.compile(r'^/2/groups/(%s)/assign-nodes$' % group_name_pattern): 231 rlib2.R_2_groups_name_assign_nodes, 232 233 "/2/jobs": rlib2.R_2_jobs, 234 re.compile(r"^/2/jobs/(%s)$" % job_id_pattern): 235 rlib2.R_2_jobs_id, 236 re.compile(r"^/2/jobs/(%s)/wait$" % job_id_pattern): 237 rlib2.R_2_jobs_id_wait, 238 239 "/2/tags": rlib2.R_2_tags, 240 "/2/info": rlib2.R_2_info, 241 "/2/os": rlib2.R_2_os, 242 "/2/redistribute-config": rlib2.R_2_redist_config, 243 "/2/features": rlib2.R_2_features, 244 "/2/modify": rlib2.R_2_cluster_modify, 245 }
246 247 248 CONNECTOR.update(GetHandlers(_NAME_PATTERN, _NAME_PATTERN, _NAME_PATTERN, 249 constants.JOB_ID_TEMPLATE, _DISK_PATTERN)) 250