Package cm_api :: Package endpoints :: Module types
[hide private]
[frames] | no frames]

Source Code for Module cm_api.endpoints.types

   1  # Licensed to Cloudera, Inc. under one 
   2  # or more contributor license agreements.  See the NOTICE file 
   3  # distributed with this work for additional information 
   4  # regarding copyright ownership.  Cloudera, Inc. licenses this file 
   5  # to you under the Apache License, Version 2.0 (the 
   6  # "License"); you may not use this file except in compliance 
   7  # with the License.  You may obtain a copy of the License at 
   8  # 
   9  #     http://www.apache.org/licenses/LICENSE-2.0 
  10  # 
  11  # Unless required by applicable law or agreed to in writing, software 
  12  # distributed under the License is distributed on an "AS IS" BASIS, 
  13  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  14  # See the License for the specific language governing permissions and 
  15  # limitations under the License. 
  16   
  17  try: 
  18    import json 
  19  except ImportError: 
  20    import simplejson as json 
  21   
  22  import copy 
  23  import datetime 
  24  import time 
  25   
  26  __docformat__ = "epytext" 
27 28 -class Attr(object):
29 """ 30 Encapsulates information about an attribute in the JSON encoding of the 31 object. It identifies properties of the attribute such as whether it's 32 read-only, its type, etc. 33 """ 34 DATE_FMT = "%Y-%m-%dT%H:%M:%S.%fZ" 35
36 - def __init__(self, atype=None, rw=True, is_api_list=False):
37 self._atype = atype 38 self._is_api_list = is_api_list 39 self.rw = rw
40
41 - def to_json(self, value, preserve_ro):
42 """ 43 Returns the JSON encoding of the given attribute value. 44 45 If the value has a 'to_json_dict' object, that method is called. Otherwise, 46 the following values are returned for each input type: 47 - datetime.datetime: string with the API representation of a date. 48 - dictionary: if 'atype' is ApiConfig, a list of ApiConfig objects. 49 - python list: python list (or ApiList) with JSON encoding of items 50 - the raw value otherwise 51 """ 52 if hasattr(value, 'to_json_dict'): 53 return value.to_json_dict(preserve_ro) 54 elif isinstance(value, dict) and self._atype == ApiConfig: 55 return config_to_api_list(value) 56 elif isinstance(value, datetime.datetime): 57 return value.strftime(self.DATE_FMT) 58 elif isinstance(value, list) or isinstance(value, tuple): 59 if self._is_api_list: 60 return ApiList(value).to_json_dict() 61 else: 62 return [ self.to_json(x, preserve_ro) for x in value ] 63 else: 64 return value
65
66 - def from_json(self, resource_root, data):
67 """ 68 Parses the given JSON value into an appropriate python object. 69 70 This means: 71 - a datetime.datetime if 'atype' is datetime.datetime 72 - a converted config dictionary or config list if 'atype' is ApiConfig 73 - if the attr is an API list, an ApiList with instances of 'atype' 74 - an instance of 'atype' if it has a 'from_json_dict' method 75 - a python list with decoded versions of the member objects if the input 76 is a python list. 77 - the raw value otherwise 78 """ 79 if data is None: 80 return None 81 82 if self._atype == datetime.datetime: 83 return datetime.datetime.strptime(data, self.DATE_FMT) 84 elif self._atype == ApiConfig: 85 # ApiConfig is special. We want a python dictionary for summary views, 86 # but an ApiList for full views. Try to detect each case from the JSON 87 # data. 88 if not data['items']: 89 return { } 90 first = data['items'][0] 91 return json_to_config(data, len(first) == 2) 92 elif self._is_api_list: 93 return ApiList.from_json_dict(data, resource_root, self._atype) 94 elif isinstance(data, list): 95 return [ self.from_json(resource_root, x) for x in data ] 96 elif hasattr(self._atype, 'from_json_dict'): 97 return self._atype.from_json_dict(data, resource_root) 98 else: 99 return data
100
101 -class ROAttr(Attr):
102 """ 103 Subclass that just defines the attribute as read-only. 104 """
105 - def __init__(self, atype=None, is_api_list=False):
106 Attr.__init__(self, atype=atype, rw=False, is_api_list=is_api_list)
107
108 109 -def check_api_version(resource_root, min_version):
110 """ 111 Checks if the resource_root's API version it at least the given minimum 112 version. 113 """ 114 if resource_root.version < min_version: 115 raise Exception("API version %s is required but %s is in use." 116 % (min_version, resource_root.version))
117
118 119 -def call(method, path, ret_type, 120 ret_is_list=False, data=None, params=None, api_version=1):
121 """ 122 Generic function for calling a resource method and automatically dealing with 123 serialization of parameters and deserialization of return values. 124 125 @param method: method to call (must be bound to a resource; 126 e.g., "resource_root.get"). 127 @param path: the full path of the API method to call. 128 @param ret_type: return type of the call. 129 @param ret_is_list: whether the return type is an ApiList. 130 @param data: Optional data to send as payload to the call. 131 @param params: Optional query parameters for the call. 132 @param api_version: minimum API version for the call. 133 """ 134 check_api_version(method.im_self, api_version) 135 if data: 136 data = json.dumps(Attr(is_api_list=True).to_json(data, False)) 137 ret = method(path, data=data, params=params) 138 else: 139 ret = method(path, params=params) 140 if ret_type is None: 141 return 142 elif ret_is_list: 143 return ApiList.from_json_dict(ret, method.im_self, ret_type) 144 elif isinstance(ret, list): 145 return [ ret_type.from_json_dict(x, method.im_self) for x in ret ] 146 else: 147 return ret_type.from_json_dict(ret, method.im_self)
148
149 -class BaseApiObject(object):
150 """ 151 The BaseApiObject helps with (de)serialization from/to JSON. 152 153 The derived class has two ways of defining custom attributes: 154 - Overwriting the '_ATTRIBUTES' field with the attribute dictionary 155 - Override the _get_attributes() method, in case static initialization of 156 the above field is not possible. 157 158 It's recommended that the _get_attributes() implementation do caching to 159 avoid computing the dictionary on every invocation. 160 161 The derived class's constructor must call the base class's init() static 162 method. All constructor arguments (aside from self and resource_root) must 163 be keywords arguments with default values (typically None), or 164 from_json_dict() will not work. 165 """ 166 167 _ATTRIBUTES = { } 168 _WHITELIST = ( '_resource_root', '_attributes' ) 169 170 @classmethod
171 - def _get_attributes(cls):
172 """ 173 Returns a map of property names to attr instances (or None for default 174 attribute behavior) describing the properties of the object. 175 176 By default, this method will return the class's _ATTRIBUTES field. 177 Classes can override this method to do custom initialization of the 178 attributes when needed. 179 """ 180 return cls._ATTRIBUTES
181 182 @staticmethod
183 - def init(obj, resource_root, attrs=None):
184 """ 185 Wraper around the real constructor to avoid issues with the 'self' 186 argument. Call like this, from a subclass's constructor: 187 188 - BaseApiObject.init(self, locals()) 189 """ 190 # This works around http://bugs.python.org/issue2646 191 # We use unicode strings as keys in kwargs. 192 str_attrs = { } 193 if attrs: 194 for k, v in attrs.iteritems(): 195 if k not in ('self', 'resource_root'): 196 str_attrs[k] = v 197 BaseApiObject.__init__(obj, resource_root, **str_attrs)
198
199 - def __init__(self, resource_root, **attrs):
200 """ 201 Initializes internal state and sets all known writable properties of the 202 object to None. Then initializes the properties given in the provided 203 attributes dictionary. 204 205 @param resource_root: API resource object. 206 @param attrs: optional dictionary of attributes to set. This should only 207 contain r/w attributes. 208 """ 209 self._resource_root = resource_root 210 211 for name, attr in self._get_attributes().iteritems(): 212 object.__setattr__(self, name, None) 213 if attrs: 214 self._set_attrs(attrs, from_json=False)
215
216 - def _set_attrs(self, attrs, allow_ro=False, from_json=True):
217 """ 218 Sets all the attributes in the dictionary. Optionally, allows setting 219 read-only attributes (e.g. when deserializing from JSON) and skipping 220 JSON deserialization of values. 221 """ 222 for k, v in attrs.iteritems(): 223 attr = self._check_attr(k, allow_ro) 224 if attr and from_json: 225 v = attr.from_json(self._get_resource_root(), v) 226 object.__setattr__(self, k, v)
227
228 - def __setattr__(self, name, val):
229 if name not in BaseApiObject._WHITELIST: 230 self._check_attr(name, False) 231 object.__setattr__(self, name, val)
232
233 - def _check_attr(self, name, allow_ro):
234 if name not in self._get_attributes(): 235 raise AttributeError('Invalid property %s for class %s.' % 236 (name, self.__class__.__name__)) 237 attr = self._get_attributes()[name] 238 if not allow_ro and attr and not attr.rw: 239 raise AttributeError('Attribute %s of class %s is read only.' % 240 (name, self.__class__.__name__)) 241 return attr
242
243 - def _get_resource_root(self):
244 return self._resource_root
245
246 - def _update(self, api_obj):
247 """Copy state from api_obj to this object.""" 248 if not isinstance(self, api_obj.__class__): 249 raise ValueError( 250 "Class %s does not derive from %s; cannot update attributes." % 251 (self.__class__, api_obj.__class__)) 252 253 for name in self._get_attributes().keys(): 254 try: 255 val = getattr(api_obj, name) 256 setattr(self, name, val) 257 except AttributeError, ignored: 258 pass
259
260 - def to_json_dict(self, preserve_ro=False):
261 dic = { } 262 for name, attr in self._get_attributes().iteritems(): 263 if not preserve_ro and attr and not attr.rw: 264 continue 265 try: 266 value = getattr(self, name) 267 if value is not None: 268 if attr: 269 dic[name] = attr.to_json(value, preserve_ro) 270 else: 271 dic[name] = value 272 except AttributeError: 273 pass 274 return dic
275
276 - def __str__(self):
277 """ 278 Default implementation of __str__. Uses the type name and the first 279 attribute retrieved from the attribute map to create the string. 280 """ 281 name = self._get_attributes().keys()[0] 282 value = getattr(self, name, None) 283 return "<%s>: %s = %s" % (self.__class__.__name__, name, value)
284 285 @classmethod
286 - def from_json_dict(cls, dic, resource_root):
287 obj = cls(resource_root) 288 obj._set_attrs(dic, allow_ro=True) 289 return obj
290
291 -class BaseApiResource(BaseApiObject):
292 """ 293 A specialization of BaseApiObject that provides some utility methods for 294 resources. This class allows easier serialization / deserialization of 295 parameters and return values. 296 """ 297
298 - def _api_version(self):
299 """ 300 Returns the minimum API version for this resource. Defaults to 1. 301 """ 302 return 1
303
304 - def _path(self):
305 """ 306 Returns the path to the resource. 307 308 e.g., for a service 'foo' in cluster 'bar', this should return 309 '/clusters/bar/services/foo'. 310 """ 311 raise NotImplementedError
312
313 - def _require_min_api_version(self, version):
314 """ 315 Raise an exception if the version of the api is less than the given version. 316 317 @param version: The minimum required version. 318 """ 319 actual_version = self._get_resource_root().version 320 version = max(version, self._api_version()) 321 if actual_version < version: 322 raise Exception("API version %s is required but %s is in use." 323 % (version, actual_version))
324
325 - def _cmd(self, command, data=None, params=None, api_version=1):
326 """ 327 Invokes a command on the resource. Commands are expected to be under the 328 "commands/" sub-resource. 329 """ 330 return self._post("commands/" + command, ApiCommand, 331 data=data, params=params, api_version=api_version)
332
333 - def _get_config(self, rel_path, view, api_version=1):
334 """ 335 Retrieves an ApiConfig list from the given relative path. 336 """ 337 self._require_min_api_version(api_version) 338 params = view and dict(view=view) or None 339 resp = self._get_resource_root().get(self._path() + '/' + rel_path, 340 params=params) 341 return json_to_config(resp, view == 'full')
342
343 - def _update_config(self, rel_path, config, api_version=1):
344 self._require_min_api_version(api_version) 345 resp = self._get_resource_root().put(self._path() + '/' + rel_path, 346 data=config_to_json(config)) 347 return json_to_config(resp, False)
348
349 - def _delete(self, rel_path, ret_type, ret_is_list=False, params=None, 350 api_version=1):
351 return self._call('delete', rel_path, ret_type, ret_is_list, None, params, 352 api_version)
353
354 - def _get(self, rel_path, ret_type, ret_is_list=False, params=None, 355 api_version=1):
356 return self._call('get', rel_path, ret_type, ret_is_list, None, params, 357 api_version)
358
359 - def _post(self, rel_path, ret_type, ret_is_list=False, data=None, params=None, 360 api_version=1):
361 return self._call('post', rel_path, ret_type, ret_is_list, data, params, 362 api_version)
363
364 - def _put(self, rel_path, ret_type, ret_is_list=False, data=None, params=None, 365 api_version=1):
366 return self._call('put', rel_path, ret_type, ret_is_list, data, params, 367 api_version)
368
369 - def _call(self, method, rel_path, ret_type, ret_is_list=False, data=None, 370 params=None, api_version=1):
371 path = self._path() 372 if rel_path: 373 path += '/' + rel_path 374 return call(getattr(self._get_resource_root(), method), 375 path, 376 ret_type, 377 ret_is_list, 378 data, 379 params, 380 api_version)
381
382 -class ApiList(BaseApiObject):
383 """A list of some api object""" 384 LIST_KEY = "items" 385
386 - def __init__(self, objects, resource_root=None, **attrs):
387 BaseApiObject.__init__(self, resource_root, **attrs) 388 # Bypass checks in BaseApiObject.__setattr__ 389 object.__setattr__(self, 'objects', objects)
390
391 - def __str__(self):
392 return "<ApiList>(%d): [%s]" % ( 393 len(self.objects), 394 ", ".join([str(item) for item in self.objects]))
395
396 - def to_json_dict(self, preserve_ro=False):
397 ret = BaseApiObject.to_json_dict(self, preserve_ro) 398 attr = Attr() 399 ret[ApiList.LIST_KEY] = [ attr.to_json(x, preserve_ro) for x in self.objects ] 400 return ret
401
402 - def __len__(self):
403 return self.objects.__len__()
404
405 - def __iter__(self):
406 return self.objects.__iter__()
407
408 - def __getitem__(self, i):
409 return self.objects.__getitem__(i)
410
411 - def __getslice(self, i, j):
412 return self.objects.__getslice__(i, j)
413 414 @classmethod
415 - def from_json_dict(cls, dic, resource_root, member_cls=None):
416 if not member_cls: 417 member_cls = cls._MEMBER_CLASS 418 attr = Attr(atype=member_cls) 419 items = [] 420 if ApiList.LIST_KEY in dic: 421 items = [ attr.from_json(resource_root, x) for x in dic[ApiList.LIST_KEY] ] 422 ret = cls(items) 423 # If the class declares custom attributes, populate them based on the input 424 # dict. The check avoids extra overhead for the common case, where we just 425 # have a plain list. _set_attrs() also does not understand the "items" 426 # attribute, so it can't be in the input data. 427 if cls._ATTRIBUTES: 428 if ApiList.LIST_KEY in dic: 429 dic = copy.copy(dic) 430 del dic[ApiList.LIST_KEY] 431 ret._set_attrs(dic, allow_ro=True) 432 return ret
433
434 -class ApiHostRef(BaseApiObject):
435 _ATTRIBUTES = { 436 'hostId' : None, 437 } 438
439 - def __init__(self, resource_root, hostId=None):
440 BaseApiObject.init(self, resource_root, locals())
441
442 - def __str__(self):
443 return "<ApiHostRef>: %s" % (self.hostId)
444
445 -class ApiServiceRef(BaseApiObject):
446 _ATTRIBUTES = { 447 'clusterName' : None, 448 'serviceName' : None, 449 'peerName' : None, 450 } 451
452 - def __init__(self, resource_root, serviceName=None, clusterName=None, 453 peerName=None):
454 BaseApiObject.init(self, resource_root, locals())
455
456 -class ApiClusterRef(BaseApiObject):
457 _ATTRIBUTES = { 458 'clusterName' : None, 459 } 460
461 - def __init__(self, resource_root, clusterName = None):
462 BaseApiObject.init(self, resource_root, locals())
463
464 -class ApiRoleRef(BaseApiObject):
465 _ATTRIBUTES = { 466 'clusterName' : None, 467 'serviceName' : None, 468 'roleName' : None, 469 } 470
471 - def __init__(self, resource_root, serviceName=None, roleName=None, 472 clusterName=None):
473 BaseApiObject.init(self, resource_root, locals())
474
475 -class ApiRoleConfigGroupRef(BaseApiObject):
476 _ATTRIBUTES = { 477 'roleConfigGroupName' : None, 478 } 479
480 - def __init__(self, resource_root, roleConfigGroupName=None):
481 BaseApiObject.init(self, resource_root, locals())
482
483 -class ApiCommand(BaseApiObject):
484 SYNCHRONOUS_COMMAND_ID = -1 485 486 @classmethod
487 - def _get_attributes(cls):
488 if not cls.__dict__.has_key('_ATTRIBUTES'): 489 cls._ATTRIBUTES = { 490 'id' : ROAttr(), 491 'name' : ROAttr(), 492 'startTime' : ROAttr(datetime.datetime), 493 'endTime' : ROAttr(datetime.datetime), 494 'active' : ROAttr(), 495 'success' : ROAttr(), 496 'resultMessage' : ROAttr(), 497 'clusterRef' : ROAttr(ApiClusterRef), 498 'serviceRef' : ROAttr(ApiServiceRef), 499 'roleRef' : ROAttr(ApiRoleRef), 500 'hostRef' : ROAttr(ApiHostRef), 501 'children' : ROAttr(ApiCommand, is_api_list=True), 502 'parent' : ROAttr(ApiCommand), 503 'resultDataUrl' : ROAttr(), 504 } 505 return cls._ATTRIBUTES
506
507 - def __str__(self):
508 return "<ApiCommand>: '%s' (id: %s; active: %s; success: %s)" % ( 509 self.name, self.id, self.active, self.success)
510
511 - def _path(self):
512 return '/commands/%d' % self.id
513
514 - def fetch(self):
515 """ 516 Retrieve updated data about the command from the server. 517 518 @return: A new ApiCommand object. 519 """ 520 if self.id == ApiCommand.SYNCHRONOUS_COMMAND_ID: 521 return self 522 523 resp = self._get_resource_root().get(self._path()) 524 return ApiCommand.from_json_dict(resp, self._get_resource_root())
525
526 - def wait(self, timeout=None):
527 """ 528 Wait for command to finish. 529 530 @param timeout: (Optional) Max amount of time (in seconds) to wait. Wait 531 forever by default. 532 @return: The final ApiCommand object, containing the last known state. 533 The command may still be running in case of timeout. 534 """ 535 if self.id == ApiCommand.SYNCHRONOUS_COMMAND_ID: 536 return self 537 538 SLEEP_SEC = 5 539 540 if timeout is None: 541 deadline = None 542 else: 543 deadline = time.time() + timeout 544 545 while True: 546 cmd = self.fetch() 547 if not cmd.active: 548 return cmd 549 550 if deadline is not None: 551 now = time.time() 552 if deadline < now: 553 return cmd 554 else: 555 time.sleep(min(SLEEP_SEC, deadline - now)) 556 else: 557 time.sleep(SLEEP_SEC)
558 559
560 - def abort(self):
561 """ 562 Abort a running command. 563 564 @return: A new ApiCommand object with the updated information. 565 """ 566 if self.id == ApiCommand.SYNCHRONOUS_COMMAND_ID: 567 return self 568 569 path = self._path() + '/abort' 570 resp = self._get_resource_root().post(path) 571 return ApiCommand.from_json_dict(resp, self._get_resource_root())
572
573 -class ApiBulkCommandList(ApiList):
574 _ATTRIBUTES = { 575 'errors' : ROAttr(), 576 } 577 _MEMBER_CLASS = ApiCommand
578
579 -class ApiCommandMetadata(BaseApiObject):
580 _ATTRIBUTES = { 581 'name' : ROAttr(), 582 'argSchema' : ROAttr(), 583 } 584
585 - def __init__(self, resource_root):
586 BaseApiObject.init(self, resource_root)
587
588 - def __str__(self):
589 return "<ApiCommandMetadata>: %s (%s)" % (self.name, self.argSchema)
590
591 # 592 # Metrics. 593 # 594 595 -class ApiMetricData(BaseApiObject):
596 """Metric reading data.""" 597 598 _ATTRIBUTES = { 599 'timestamp' : ROAttr(datetime.datetime), 600 'value' : ROAttr(), 601 } 602
603 - def __init__(self, resource_root):
604 BaseApiObject.init(self, resource_root)
605
606 607 -class ApiMetric(BaseApiObject):
608 """Metric information.""" 609 610 _ATTRIBUTES = { 611 'name' : ROAttr(), 612 'context' : ROAttr(), 613 'unit' : ROAttr(), 614 'data' : ROAttr(ApiMetricData), 615 'displayName' : ROAttr(), 616 'description' : ROAttr(), 617 } 618
619 - def __init__(self, resource_root):
620 BaseApiObject.init(self, resource_root)
621
622 # 623 # Activities. 624 # 625 626 -class ApiActivity(BaseApiObject):
627 _ATTRIBUTES = { 628 'name' : ROAttr(), 629 'type' : ROAttr(), 630 'parent' : ROAttr(), 631 'startTime' : ROAttr(), 632 'finishTime' : ROAttr(), 633 'id' : ROAttr(), 634 'status' : ROAttr(), 635 'user' : ROAttr(), 636 'group' : ROAttr(), 637 'inputDir' : ROAttr(), 638 'outputDir' : ROAttr(), 639 'mapper' : ROAttr(), 640 'combiner' : ROAttr(), 641 'reducer' : ROAttr(), 642 'queueName' : ROAttr(), 643 'schedulerPriority' : ROAttr(), 644 } 645
646 - def __init__(self, resource_root):
647 BaseApiObject.init(self, resource_root)
648
649 - def __str__(self):
650 return "<ApiActivity>: %s (%s)" % (self.name, self.status)
651
652 # 653 # Replication 654 # 655 656 -class ApiCmPeer(BaseApiObject):
657 _ATTRIBUTES = { 658 'name' : None, 659 'url' : None, 660 'username' : None, 661 'password' : None, 662 } 663
664 - def __str__(self):
665 return "<ApiPeer>: %s (%s)" % (self.name, self.url)
666
667 -class ApiHdfsReplicationArguments(BaseApiObject):
668 _ATTRIBUTES = { 669 'sourceService' : Attr(ApiServiceRef), 670 'sourcePath' : None, 671 'destinationPath' : None, 672 'mapreduceServiceName' : None, 673 'userName' : None, 674 'numMaps' : None, 675 'dryRun' : None, 676 'schedulerPoolName' : None, 677 'abortOnError' : None, 678 'preservePermissions' : None, 679 'preserveBlockSize' : None, 680 'preserveReplicationCount' : None, 681 'removeMissingFiles' : None, 682 'skipChecksumChecks' : None, 683 }
684
685 -class ApiHdfsReplicationResult(BaseApiObject):
686 _ATTRIBUTES = { 687 'progress' : ROAttr(), 688 'counters' : ROAttr(), 689 'numBytesDryRun' : ROAttr(), 690 'numFilesDryRun' : ROAttr(), 691 'numFilesExpected' : ROAttr(), 692 'numBytesExpected' : ROAttr(), 693 'numFilesCopied' : ROAttr(), 694 'numBytesCopied' : ROAttr(), 695 'numFilesSkipped' : ROAttr(), 696 'numBytesSkipped' : ROAttr(), 697 'numFilesDeleted' : ROAttr(), 698 'numFilesCopyFailed' : ROAttr(), 699 'numBytesCopyFailed' : ROAttr(), 700 'setupError' : ROAttr(), 701 'jobId' : ROAttr(), 702 'jobDetailsUri' : ROAttr(), 703 'dryRun' : ROAttr(), 704 'snapshottedDirs' : ROAttr(), 705 }
706
707 -class ApiHiveTable(BaseApiObject):
708 _ATTRIBUTES = { 709 'database' : None, 710 'tableName' : None, 711 } 712
713 - def __str__(self):
714 return "<ApiHiveTable>: %s, %s" % (self.database, self.tableName)
715
716 -class ApiImpalaUDF(BaseApiObject):
717 _ATTRIBUTES = { 718 'database' : ROAttr(), 719 'signature' : ROAttr(), 720 } 721
722 - def __str__(self):
723 return "<ApiImpalaUDF>: %s, %s" % (self.database, self.signature)
724
725 -class ApiHiveReplicationArguments(BaseApiObject):
726 _ATTRIBUTES = { 727 'sourceService' : Attr(ApiServiceRef), 728 'tableFilters' : Attr(ApiHiveTable), 729 'exportDir' : None, 730 'force' : None, 731 'replicateData' : None, 732 'hdfsArguments' : Attr(ApiHdfsReplicationArguments), 733 'dryRun' : None, 734 }
735
736 -class ApiHiveReplicationResult(BaseApiObject):
737 _ATTRIBUTES = { 738 'tableCount' : ROAttr(), 739 'tables' : ROAttr(ApiHiveTable), 740 'impalaUDFCount' : ROAttr(), 741 'impalaUDFs' : ROAttr(ApiImpalaUDF), 742 'errorCount' : ROAttr(), 743 'errors' : ROAttr(), 744 'dataReplicationResult' : ROAttr(ApiHdfsReplicationResult), 745 'dryRun' : ROAttr(), 746 'phase' : ROAttr(), 747 }
748
749 -class ApiReplicationCommand(ApiCommand):
750 @classmethod
751 - def _get_attributes(cls):
752 if not cls.__dict__.has_key('_ATTRIBUTES'): 753 attrs = { 754 'hdfsResult' : ROAttr(ApiHdfsReplicationResult), 755 'hiveResult' : ROAttr(ApiHiveReplicationResult), 756 } 757 attrs.update(ApiCommand._get_attributes()) 758 cls._ATTRIBUTES = attrs 759 return cls._ATTRIBUTES
760
761 -class ApiReplicationSchedule(BaseApiObject):
762 _ATTRIBUTES = { 763 'startTime' : Attr(datetime.datetime), 764 'endTime' : Attr(datetime.datetime), 765 'interval' : None, 766 'intervalUnit' : None, 767 'paused' : None, 768 'hdfsArguments' : Attr(ApiHdfsReplicationArguments), 769 'hiveArguments' : Attr(ApiHiveReplicationArguments), 770 'alertOnStart' : None, 771 'alertOnSuccess' : None, 772 'alertOnFail' : None, 773 'alertOnAbort' : None, 774 'id' : ROAttr(), 775 'nextRun' : ROAttr(datetime.datetime), 776 'history' : ROAttr(ApiReplicationCommand), 777 }
778
779 -class ApiHBaseSnapshotPolicyArguments(BaseApiObject):
780 _ATTRIBUTES = { 781 'tableRegExps' : None, 782 }
783
784 -class ApiHdfsSnapshotPolicyArguments(BaseApiObject):
785 _ATTRIBUTES = { 786 'pathPatterns' : None, 787 }
788
789 -class ApiHBaseSnapshot(BaseApiObject):
790 _ATTRIBUTES = { 791 'snapshotName' : None, 792 'tableName' : None, 793 'creationTime' : ROAttr(datetime.datetime), 794 }
795
796 -class ApiHBaseSnapshotError(BaseApiObject):
797 _ATTRIBUTES = { 798 'tableName' : ROAttr(), 799 'snapshotName' : ROAttr(), 800 'error' : ROAttr(), 801 }
802
803 -class ApiHdfsSnapshot(BaseApiObject):
804 _ATTRIBUTES = { 805 'path' : None, 806 'snapshotName' : None, 807 'snapshotPath' : None, 808 'creationTime' : ROAttr(datetime.datetime), 809 }
810
811 -class ApiHdfsSnapshotError(BaseApiObject):
812 _ATTRIBUTES = { 813 'path' : ROAttr(), 814 'snapshotName' : ROAttr(), 815 'snapshotPath' : ROAttr(), 816 'error' : ROAttr(), 817 }
818
819 -class ApiHBaseSnapshotResult(BaseApiObject):
820 _ATTRIBUTES = { 821 'processedTableCount' : ROAttr(), 822 'processedTables' : ROAttr(), 823 'unprocessedTableCount' : ROAttr(), 824 'unprocessedTables' : ROAttr(), 825 'createdSnapshotCount' : ROAttr(), 826 'createdSnapshots' : ROAttr(ApiHBaseSnapshot), 827 'deletedSnapshotCount' : ROAttr(), 828 'deletedSnapshots' : ROAttr(ApiHBaseSnapshot), 829 'creationErrorCount' : ROAttr(), 830 'creationErrors' : ROAttr(ApiHBaseSnapshotError), 831 'deletionErrorCount' : ROAttr(), 832 'deletionErrors' : ROAttr(ApiHBaseSnapshotError), 833 }
834
835 -class ApiHdfsSnapshotResult(BaseApiObject):
836 _ATTRIBUTES = { 837 'processedPathCount' : ROAttr(), 838 'processedPaths' : ROAttr(), 839 'unprocessedPathCount' : ROAttr(), 840 'unprocessedPaths' : ROAttr(), 841 'createdSnapshotCount' : ROAttr(), 842 'createdSnapshots' : ROAttr(ApiHdfsSnapshot), 843 'deletedSnapshotCount' : ROAttr(), 844 'deletedSnapshots' : ROAttr(ApiHdfsSnapshot), 845 'creationErrorCount' : ROAttr(), 846 'creationErrors' : ROAttr(ApiHdfsSnapshotError), 847 'deletionErrorCount' : ROAttr(), 848 'deletionErrors' : ROAttr(ApiHdfsSnapshotError), 849 }
850
851 -class ApiSnapshotCommand(BaseApiObject):
852 @classmethod
853 - def _get_attributes(cls):
854 if not cls.__dict__.has_key('_ATTRIBUTES'): 855 attrs = { 856 'hdfsResult' : ROAttr(ApiHdfsSnapshotResult), 857 'hbaseResult' : ROAttr(ApiHBaseSnapshotResult), 858 } 859 attrs.update(ApiCommand._get_attributes()) 860 cls._ATTRIBUTES = attrs 861 return cls._ATTRIBUTES
862
863 -class ApiSnapshotPolicy(BaseApiObject):
864 """ 865 @type name: str 866 @ivar name: Name of the snapshot policy. 867 @type description: str 868 @ivar description: Description of the snapshot policy. 869 @type hourly_snapshots: int 870 @ivar hourly_snapshots: Number of hourly snapshots to be retained (default: 0). 871 @type daily_snapshots: int 872 @ivar daily_snapshots: Number of daily snapshots to be retained (default: 0). 873 @type weekly_snapshots: int 874 @ivar weekly_snapshots: Number of weekly snapshots to be retained (default: 0). 875 @type monthly_snapshots: int 876 @ivar monthly_snapshots: Number of monthly snapshots to be retained (default: 0). 877 @type yearly_snapshots: int 878 @ivar yearly_snapshots: Number of yearly snapshots to be retained (default: 0). 879 @type hours_for_hourly_snapshots: list of int 880 @ivar hours_for_hourly_snapshots: Hours of the day that hourly snapshots should be created. 881 Valid values are 0 to 23. If this list is empty, then hourly snapshots are 882 created for every hour. 883 @type minute_of_hour: int 884 @ivar minute_of_hour: Minute in the hour that hourly, daily, weekly, monthly and yearly 885 snapshots should be created. Valid values are 0 to 59 (default: 0). 886 @type hour_of_day: int 887 @ivar hour_of_day: Hour in the day that daily, weekly, monthly and yearly snapshots should be created. 888 Valid values are 0 to 23 (default: 0). 889 @type day_of_week: int 890 @ivar day_of_week: Day of the week that weekly snapshots should be created. 891 Valid values are 1 to 7, 1 representing Sunday (default: 1). 892 @type day_of_month: int 893 @ivar day_of_month: Day of the month that monthly and yearly snapshots should be created. 894 Values from 1 to 31 are allowed. Additionally 0 to -30 can be used to 895 specify offsets from the last day of the month (default: 1). 896 @type month_of_year: int 897 @ivar month_of_year: Month of the year that yearly snapshots should be created. 898 Valid values are 1 to 12, 1 representing January (default: 1). 899 @ivar alert_on_start: whether to generate alerts on start of snapshot creation/deletion activity. 900 @ivar alert_on_success: whether to generate alerts on successful completion of snapshot creation/deletion activity. 901 @ivar alert_on_fail: whether to generate alerts on failure of snapshot creation/deletion activity. 902 @ivar alert_on_abort: whether to generate alerts on abort of snapshot creation/deletion activity. 903 @type hbaseArguments: ApiHBaseSnapshotPolicyArguments 904 @ivar hbaseArguments: HBase specific arguments for the replication job. 905 @type hdfsArguments: ApiHdfsSnapshotPolicyArguments 906 @ivar hdfsArguments: HDFS specific arguments for the replication job. 907 """ 908 _ATTRIBUTES = { 909 'name' : None, 910 'description' : None, 911 'hourlySnapshots' : None, 912 'dailySnapshots' : None, 913 'weeklySnapshots' : None, 914 'monthlySnapshots' : None, 915 'yearlySnapshots' : None, 916 'minuteOfHour' : None, 917 'hourOfDay' : None, 918 'dayOfWeek' : None, 919 'dayOfMonth' : None, 920 'monthOfYear' : None, 921 'hoursForHourlySnapshots' : None, 922 'alertOnStart' : None, 923 'alertOnSuccess' : None, 924 'alertOnFail' : None, 925 'alertOnAbort' : None, 926 'hbaseArguments' : Attr(ApiHBaseSnapshotPolicyArguments), 927 'hdfsArguments' : Attr(ApiHdfsSnapshotPolicyArguments), 928 'lastCommand' : ROAttr(ApiSnapshotCommand), 929 'lastSuccessfulCommand' : ROAttr(ApiSnapshotCommand), 930 }
931
932 # 933 # Batch. 934 # 935 936 -class ApiBatchRequestElement(BaseApiObject):
937 """One element in a batch request.""" 938 _ATTRIBUTES = { 939 'method' : None, 940 'url' : None, 941 'body' : None, 942 'contentType' : None, 943 'acceptType' : None, 944 }
945
946 -class ApiBatchResponseElement(BaseApiObject):
947 """One element in a batch response.""" 948 _ATTRIBUTES = { 949 'statusCode' : ROAttr(), 950 'response' : ROAttr(), 951 }
952
953 -class ApiBatchResponseList(ApiList):
954 """A list of batch response objects.""" 955 _ATTRIBUTES = { 956 'success' : ROAttr(), 957 } 958 _MEMBER_CLASS = ApiBatchResponseElement
959
960 # 961 # Configuration helpers. 962 # 963 964 -class ApiConfig(BaseApiObject):
965 _ATTRIBUTES = { 966 'name' : None, 967 'value' : None, 968 'required' : ROAttr(), 969 'default' : ROAttr(), 970 'displayName' : ROAttr(), 971 'description' : ROAttr(), 972 'relatedName' : ROAttr(), 973 'validationState' : ROAttr(), 974 'validationMessage' : ROAttr(), 975 } 976
977 - def __init__(self, resource_root, name=None, value=None):
978 BaseApiObject.init(self, resource_root, locals())
979
980 - def __str__(self):
981 return "<ApiConfig>: %s = %s" % (self.name, self.value)
982
983 -class ApiImpalaQuery(BaseApiObject):
984 _ATTRIBUTES = { 985 'queryId' : ROAttr(), 986 'queryState' : ROAttr(), 987 'queryType' : ROAttr(), 988 'statement' : ROAttr(), 989 'database' : ROAttr(), 990 'rowsProduced' : ROAttr(), 991 'coordinator' : ROAttr(ApiHostRef), 992 'user' : ROAttr(), 993 'startTime' : ROAttr(datetime.datetime), 994 'endTime' : ROAttr(datetime.datetime), 995 'detailsAvailable' : ROAttr(), 996 'attributes' : ROAttr(), 997 'durationMillis' : ROAttr() 998 } 999
1000 - def __str__(self):
1001 return "<ApiImpalaQuery>: %s" % (self.queryId)
1002
1003 1004 -class ApiImpalaQueryResponse(BaseApiObject):
1005 1006 _ATTRIBUTES = { 1007 'queries' : ROAttr(ApiImpalaQuery), 1008 'warnings' : ROAttr() 1009 }
1010
1011 -class ApiImpalaQueryDetailsResponse(BaseApiObject):
1012 _ATTRIBUTES = { 1013 'details' : ROAttr() 1014 } 1015
1016 - def __str__(self):
1017 return "<AipImpalaQueryDetailsResponse> %s" % self.details
1018
1019 -class ApiImpalaCancelResponse(BaseApiObject):
1020 _ATTRIBUTES = { 1021 'warning' : ROAttr() 1022 } 1023
1024 - def __str__(self):
1025 return "<ApiImpalaCancelResponse> %s" % self.warning
1026
1027 -class ApiImpalaQueryAttribute(BaseApiObject):
1028 1029 _ATTRIBUTES = { 1030 'name' : ROAttr(), 1031 'type' : ROAttr(), 1032 'displayName' : ROAttr(), 1033 'supportsHistograms' : ROAttr(), 1034 'description' : ROAttr() 1035 } 1036
1037 - def __str__(self):
1038 return "<ApiImpalaQueryAttribute> %s" % name
1039
1040 -class ApiMr2AppInformation(BaseApiObject):
1041 _ATTRIBUTES = { 1042 'jobState' : ROAttr() 1043 } 1044
1045 - def __str__(self):
1046 return "<ApiMr2AppInformation>: %s" % (self.jobState)
1047
1048 -class ApiYarnApplication(BaseApiObject):
1049 _ATTRIBUTES = { 1050 'applicationId' : ROAttr(), 1051 'name' : ROAttr(), 1052 'user' : ROAttr(), 1053 'startTime' : ROAttr(datetime.datetime), 1054 'endTime' : ROAttr(datetime.datetime), 1055 'pool' : ROAttr(), 1056 'state' : ROAttr(), 1057 'progress' : ROAttr(), 1058 'mr2AppInformation' : ROAttr(ApiMr2AppInformation), 1059 'attributes' : ROAttr(), 1060 } 1061
1062 - def __str__(self):
1063 return "<ApiYarnApplication>: %s" % (self.applicationId)
1064
1065 -class ApiYarnApplicationResponse(BaseApiObject):
1066 1067 _ATTRIBUTES = { 1068 'applications' : ROAttr(ApiYarnApplication), 1069 'warnings' : ROAttr() 1070 }
1071
1072 -class ApiYarnKillResponse(BaseApiObject):
1073 _ATTRIBUTES = { 1074 'warning' : ROAttr() 1075 } 1076
1077 - def __str__(self):
1078 return "<ApiYarnKillResponse> %s" % self.warning
1079
1080 -class ApiYarnApplicationAttribute(BaseApiObject):
1081 1082 _ATTRIBUTES = { 1083 'name' : ROAttr(), 1084 'type' : ROAttr(), 1085 'displayName' : ROAttr(), 1086 'supportsHistograms' : ROAttr(), 1087 'description' : ROAttr() 1088 } 1089
1090 - def __str__(self):
1091 return "<ApiYarnApplicationAttribute> %s" % name
1092
1093 -def config_to_api_list(dic):
1094 """ 1095 Converts a python dictionary into a list containing the proper 1096 ApiConfig encoding for configuration data. 1097 1098 @param dic: Key-value pairs to convert. 1099 @return: JSON dictionary of an ApiConfig list (*not* an ApiList). 1100 """ 1101 config = [ ] 1102 for k, v in dic.iteritems(): 1103 config.append({ 'name' : k, 'value': v }) 1104 return { ApiList.LIST_KEY : config }
1105
1106 -def config_to_json(dic):
1107 """ 1108 Converts a python dictionary into a JSON payload. 1109 1110 The payload matches the expected "apiConfig list" type used to update 1111 configuration parameters using the API. 1112 1113 @param dic: Key-value pairs to convert. 1114 @return: String with the JSON-encoded data. 1115 """ 1116 return json.dumps(config_to_api_list(dic))
1117
1118 -def json_to_config(dic, full = False):
1119 """ 1120 Converts a JSON-decoded config dictionary to a python dictionary. 1121 1122 When materializing the full view, the values in the dictionary will be 1123 instances of ApiConfig, instead of strings. 1124 1125 @param dic: JSON-decoded config dictionary. 1126 @param full: Whether to materialize the full view of the config data. 1127 @return: Python dictionary with config data. 1128 """ 1129 config = { } 1130 for entry in dic['items']: 1131 k = entry['name'] 1132 if full: 1133 config[k] = ApiConfig.from_json_dict(entry, None) 1134 else: 1135 config[k] = entry.get('value') 1136 return config
1137