Guest User

Untitled

a guest
Feb 13th, 2018
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 28.23 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. # Example Usage:
  4. # ./shell.py "ls /" quit
  5. # ./shell.py "ls /project" quit
  6. # ./shell.py "ls /project/default-domain:default-project" quit
  7. # ./shell.py "ls /project/default-domain:default-project/virtual_networks" quit
  8. # ./shell.py "cat /project/default-domain:default-project" quit
  9. # ./shell.py "cat -p /project/default-domain:default-project" quit
  10. # ./shell.py "cat /project/default-domain:admin/virtual_networks/default-domain:default-project:default-virtual-network" quit
  11.  
  12. test_cmds = [
  13. "ls /",
  14. "ls /project",
  15. "ls /project/default-domain:default-project",
  16. "ls /project/default-domain:default-project/virtual_networks",
  17. "cat /project/default-domain:default-project",
  18. "cat -p /project/default-domain:default-project",
  19. "cat /project/default-domain:admin/virtual_networks/default-domain:default-project:default-virtual-network",
  20. ]
  21.  
  22. import sys
  23. import logging
  24. import os
  25. import argparse
  26. import ConfigParser
  27. import cgitb
  28. from pprint import pprint
  29. from cmd2 import Cmd, options, make_option
  30. import functools
  31. from uuid import UUID
  32. import json
  33. import tempfile
  34. import cStringIO
  35. import inspect
  36.  
  37. from vnc_api import vnc_api
  38. from vnc_api.gen.generatedssuper import GeneratedsSuper
  39.  
  40. logger = logging.getLogger(__name__)
  41.  
  42. class NoSuchDirectory(Exception):
  43. pass
  44.  
  45. class IsADirectory(Exception):
  46. pass
  47.  
  48. class NoSuchFile(Exception):
  49. pass
  50.  
  51. class NoSuchCommand(Exception):
  52. pass
  53.  
  54. def is_uuid_like(string):
  55. try:
  56. UUID(string)
  57. return True
  58. except ValueError:
  59. return False
  60. # end is_uuid_like
  61.  
  62. def read_config(cfg_parser, section, option, default=None):
  63. try:
  64. val = cfg_parser.get(section, option)
  65. except (AttributeError,
  66. ConfigParser.NoOptionError,
  67. ConfigParser.NoSectionError):
  68. val = default
  69.  
  70. return val
  71. # end read_config
  72.  
  73. class RestFileSystems(object):
  74. _path_prefix_to_driver = {}
  75. cwd = None
  76. def add_driver(self, prefix, driver):
  77. self._path_prefix_to_driver[prefix] = driver
  78. # end add_driver
  79.  
  80. def _get_fs(self, path_pfx):
  81. # if path_pfx can match any registered fs pfx,
  82. # return None, else match default fs(contrail)
  83. logger.debug('Getting filesystem for %s', path_pfx)
  84. if any(x for x in self._path_prefix_to_driver
  85. if x.startswith(path_pfx)):
  86. return self._path_prefix_to_driver.get(path_pfx)
  87. return self._path_prefix_to_driver.get('/')
  88.  
  89. def _match_fs(self, path_pfx):
  90. logger.debug('Matching %s in %s', path_pfx,
  91. [pfx for pfx in self._path_prefix_to_driver])
  92. return [pfx for pfx,drv in self._path_prefix_to_driver.items()
  93. if pfx.startswith(path_pfx)]
  94.  
  95. def get_completions(self, partial_path):
  96. # process last part in path
  97. if self.cwd is None:
  98. if partial_path[0] != '/':
  99. logger.debug('No leading / and CWD None')
  100. return []
  101.  
  102. logger.debug('No CWD')
  103. fs = self._get_fs(partial_path)
  104. if not fs:
  105. fs_matches = self._match_fs(partial_path)
  106. logger.debug('Matched file systems %s', fs_matches)
  107. return fs_matches
  108.  
  109. dirname = os.path.dirname(partial_path)
  110. partial_filename = os.path.basename(partial_path)
  111. logger.debug('File system found: %s dirname %s basename %s',
  112. fs, dirname, partial_filename)
  113. files = fs.list_dir(dirname)
  114. matching_files = [f for f in files or [] if f.startswith(partial_filename)]
  115. logger.debug('Matching files: %s', matching_files)
  116. return matching_files
  117. # end get_completions
  118.  
  119. def ls(self, path, opts):
  120. if self.cwd is None:
  121. fs = self._get_fs(path)
  122. if not fs:
  123. logger.error('ls: No matching file-system for %s', path)
  124. return []
  125. files = fs.list_dir(path, opts)
  126. logger.debug("ls command found files %s", files)
  127. return files
  128. # end ls
  129.  
  130. def cat(self, path, opts):
  131. if self.cwd is None:
  132. fs = self._get_fs(path)
  133. if not fs:
  134. logger.error('cat: No matching file-system for %s', path)
  135. return []
  136. content = fs.print_file(path, opts)
  137. logger.debug("cat command found content %s", content)
  138. return content
  139. # end cat
  140.  
  141. def inspect(self, path, opts=None):
  142. pass
  143. # end inspect
  144. # end class RestFileSystems
  145.  
  146. class ContrailDriver(object):
  147. @classmethod
  148. def get_config_api_connection(cls, api_conf_files):
  149. config_parser = ConfigParser.SafeConfigParser()
  150. if api_conf_files is None:
  151. config_parser.read(
  152. ['/etc/contrail/contrail-api.conf',
  153. '/etc/contrail/contrail-keystone-auth.conf'])
  154. else:
  155. config_parser.read(api_conf_files)
  156. username = read_config(config_parser, 'KEYSTONE', 'admin_user')
  157. password = read_config(config_parser, 'KEYSTONE', 'admin_password')
  158. tenant_name = read_config(
  159. config_parser, 'KEYSTONE', 'admin_tenant_name')
  160.  
  161. connection = vnc_api.VncApi(
  162. username=username, password=password, tenant_name=tenant_name)
  163.  
  164. try:
  165. cls.obj_types = [x.replace('-', '_')
  166. for x in vnc_api.all_resource_types]
  167. cls.obj_classes = dict((x.replace('-', '_'),
  168. vnc_api.get_object_class(x))
  169. for x in vnc_api.all_resource_types)
  170. except AttributeError:
  171. cls.obj_types = connnection._type_to_class.keys()
  172. cls.obj_classes = connection._type_to_class
  173.  
  174. return connection
  175. # end get_config_api_connection
  176.  
  177. @classmethod
  178. def all_field_names(cls, obj_type):
  179. obj_class = cls.obj_classes[obj_type]
  180. return list(obj_class.prop_fields |
  181. obj_class.children_fields |
  182. obj_class.backref_fields)
  183. # end all_field_names
  184.  
  185. #@classmethod
  186. #def serialize_to_json(cls, obj, field_names=None):
  187. # import pdb; pdb.set_trace()
  188. # obj_class = cls.obj_classes[obj._type.replace('-', '_')]
  189. # serialized = {}
  190. # serialized.update(obj._serialize_to_json())
  191. # for backref_name in obj_class.backref_fields:
  192. # if hasattr(self, backref_name):
  193. # obj._serialize_field_to_json(serialized, None, backref_name)
  194. # for child_name in obj_class.children_fields:
  195. # if hasattr(self, child_name):
  196. # obj._serialize_field_to_json(serialized, None, child_name)
  197. # return serialized
  198. #end serialize_to_json
  199.  
  200. def __init__(self, args):
  201. self.args = args
  202. self.conn = self.get_config_api_connection(args.api_conf)
  203.  
  204. try:
  205. self.obj_types = [x.replace('-', '_')
  206. for x in vnc_api.all_resource_types]
  207. self.obj_classes = dict((x.replace('-', '_'),
  208. vnc_api.get_object_class(x))
  209. for x in vnc_api.all_resource_types)
  210. except AttributeError:
  211. self.obj_types = self.conn._type_to_class.keys()
  212. self.obj_classes = self.conn._type_to_class
  213.  
  214. def _root_lister():
  215. return self.obj_types
  216. self.listers = {'/': _root_lister}
  217. for obj_type in self.obj_types:
  218. lister = functools.partial(self.collection_list, obj_type)
  219. functools.update_wrapper(lister, self.collection_list)
  220. self.listers['/%s' %(obj_type)] = lister
  221.  
  222. logger.debug('Initializing, all object types: %s', self.obj_types)
  223. # end __init__
  224.  
  225. def _object_path_to_parts(self, obj_path):
  226. # obj_path is full path of object/attr. returns obj_key and attr_path
  227. try:
  228. obj_key = obj_path.split('/')[2]
  229. except IndexError:
  230. raise NoSuchFile('Not an object path: %s' %(obj_path))
  231.  
  232. if len(obj_path.split('/')) > 2:
  233. attr_path = '/'.join(obj_path.split('/')[3:])
  234. else:
  235. attr_path = None
  236. return obj_key, attr_path
  237. # end _object_path_to_parts
  238.  
  239. def _object_read(self, obj_type, obj_key,
  240. include_children=False, include_backrefs=False):
  241.  
  242. obj_class = self.obj_classes[obj_type]
  243. fields = set([])
  244. if include_children:
  245. fields = fields | obj_class.children_fields
  246. if include_backrefs:
  247. fields = fields | obj_class.backref_fields
  248.  
  249. method = getattr(self.conn, '%s_read' %(obj_type))
  250. if ':' in obj_key or not is_uuid_like(obj_key):
  251. obj = method(fq_name=obj_key.split(':'), fields=list(fields))
  252. logger.debug('Read object %s', obj)
  253. else:
  254. obj = method(id=obj_key, fields=list(fields))
  255. logger.debug('Read object %s', obj)
  256.  
  257. return obj
  258. # end _object_read
  259.  
  260. def list_dir(self, dirpath, opts=None):
  261. # dir path is oneof /, /<type>, /<type>/<obj-fqn>
  262. # or /<type>/<obj-fqn>/<attr-hierarchy>
  263. norm_dirpath = os.path.normpath(dirpath)
  264. logger.debug('Listing directory for %s', norm_dirpath)
  265. if norm_dirpath in self.listers:
  266. # direct match list types/collection
  267. logger.debug('Found lister %s', self.listers[norm_dirpath])
  268. return self.listers[norm_dirpath]()
  269.  
  270. for obj_type in self.obj_types:
  271. if not norm_dirpath.startswith('/%s/' %(obj_type)):
  272. continue
  273.  
  274. #include_children = opts.list_children if opts else True
  275. #include_backrefs = opts.list_back_references if opts else True
  276. include_children = True
  277. include_backrefs = True
  278. return self.object_list(obj_type, norm_dirpath,
  279. include_children, include_backrefs)
  280.  
  281. raise NoSuchDirectory('No such directory %s' %(norm_dirpath))
  282. # end list_dir
  283.  
  284. def collection_list(self, obj_type):
  285. logger.debug('Listing objects %s', obj_type)
  286. method = getattr(self.conn, '%ss_list' %(obj_type))
  287. resources = method()
  288. uuids_fqns = []
  289. for res in resources['%ss' %(obj_type.replace('_', '-'))]:
  290. uuids_fqns.append(res['uuid'])
  291. uuids_fqns.append(':'.join(res['fq_name']))
  292.  
  293. return uuids_fqns
  294. # end collection_list
  295.  
  296. def object_list(self, obj_type, obj_path,
  297. include_children=False, include_backrefs=False):
  298. # obj_path is always the full path of object/property
  299. obj_key, attr_path = self._object_path_to_parts(obj_path)
  300. logger.debug('Listing object %s %s', obj_type, obj_key)
  301.  
  302. obj = self._object_read(obj_type, obj_key,
  303. include_children, include_backrefs)
  304. if not attr_path:
  305. # all top-level attrs of objects
  306. ret_attrs = []
  307. for attr in obj.__dict__.keys():
  308. if attr == '_id_perms':
  309. ret_attrs.append('id_perms')
  310. continue
  311. if attr.startswith('_'):
  312. continue
  313. ret_attrs.append(attr)
  314. return ret_attrs
  315. # if full object
  316.  
  317. attr_path_parts = attr_path.split('/')
  318. # handle refs/backrefs
  319. if (attr_path_parts[0] in obj.ref_fields or
  320. attr_path_parts[0] in obj.backref_fields):
  321. if len(attr_path_parts) == 1:
  322. # list of refs/back_refs
  323. refs = getattr(obj, attr_path_parts[0])
  324. uuids = [ref['uuid'] for ref in refs]
  325. fqns = [':'.join(ref['to']) for ref in refs]
  326. return uuids + fqns
  327.  
  328. # listing a specific ref/backref
  329. ref_type = attr_path_parts[0].replace(
  330. '_back_refs', '').replace('_refs', '')
  331. # generate abspath for ref and recurse
  332. ref_path = '/%s/%s' %(ref_type, '/'.join(attr_path_parts[1:]))
  333. return self.object_list(ref_type, ref_path,
  334. include_children, include_backrefs)
  335. # end ref handling
  336.  
  337. # handle children
  338. if attr_path_parts[0] in obj.children_fields:
  339. if len(attr_path_parts) == 1:
  340. # list of children
  341. children = getattr(obj, attr_path_parts[0])
  342. uuids = [child['uuid'] for child in children]
  343. fqns = [':'.join(child['to']) for child in children]
  344. return uuids + fqns
  345.  
  346. # listing a child
  347. child_type = attr_path_parts[0][:-1] # strip plural
  348. # generate abspath for child and recurse
  349. child_path = '/%s/%s' %(child_type, '/'.join(attr_path_parts[1:]))
  350. return self.object_list(child_type, child_path,
  351. include_children, include_backrefs)
  352. # end children handling
  353.  
  354. try:
  355. attr = getattr(obj, '.'.join(attr_path_parts))
  356. except AttributeError:
  357. return None
  358.  
  359. logger.debug('Reading attr_path %s value %s', attr_path, attr)
  360. if isinstance(attr, GeneratedsSuper):
  361. return attr.__dict__.keys()
  362.  
  363. # attr is a leaf
  364. return []
  365. # end object_list
  366.  
  367. def print_file(self, file_path, opts):
  368. # file_path is /<type>/<fqn>[/<attr-hierarchy]
  369. norm_file_path = os.path.normpath(file_path)
  370. logger.debug('Printing file for %s', norm_file_path)
  371. for obj_type in self.obj_types:
  372. if not norm_file_path.startswith('/%s/' %(obj_type)):
  373. continue
  374. #include_children = opts.read_children if opts else True
  375. #include_backrefs = opts.read_back_references if opts else True
  376. include_children = True
  377. include_backrefs = True
  378. return self.object_read(obj_type, norm_file_path,
  379. include_children, include_backrefs)
  380. raise NoSuchFile('No such file: %s' %(norm_file_path))
  381. # end print_file
  382.  
  383. def object_read(self, obj_type, obj_path,
  384. include_children=True, include_backrefs=True):
  385. # obj_path is always the full path of object/property
  386. # returns json representation of object
  387. obj_key, attr_path = self._object_path_to_parts(obj_path)
  388. logger.debug('Reading object %s %s', obj_type, obj_key)
  389.  
  390. obj = self._object_read(obj_type, obj_key,
  391. include_children, include_backrefs)
  392. if not attr_path:
  393. #obj_json = self.serialize_to_json(obj)
  394. return json.dumps(obj.serialize_to_json(),
  395. default=lambda o: dict((k,v) for k,v in o.__dict__.iteritems()),
  396. sort_keys=True, indent=4)
  397.  
  398. attr_path_parts = attr_path.split('/')
  399. # handle refs/backrefs
  400. if (attr_path_parts[0] in obj.ref_fields or
  401. attr_path_parts[0] in obj.backref_fields):
  402. try:
  403. refs = getattr(obj, attr_path_parts[0])
  404. except AttributeError:
  405. raise NoSuchFile('No such object reference %s' %(obj_path))
  406.  
  407. ref_type = attr_path_parts[0].replace(
  408. '_back_refs', '').replace('_refs', '')
  409. if len(attr_path_parts) == 1:
  410. # printing all ref/backref
  411. refs_content = []
  412. # find abspath of all refs and recurse
  413. for ref in refs:
  414. ref_path = '/%s/%s' %(ref_type, ref['uuid'])
  415. refs_content.append(self.object_read(
  416. ref_type, ref_path,
  417. include_children, include_backrefs))
  418. return ','.join(refs_content)
  419. # end all refs of a type
  420.  
  421. # attr hierarchy within ref
  422. # generate abspath for ref and recurse
  423. ref_path = '/%s/%s' %(ref_type, '/'.join(attr_path_parts[1:]))
  424. return self.object_read(ref_type, ref_path,
  425. include_children, include_backrefs)
  426. # end handling refs/backrefs
  427.  
  428. # handle children
  429. if attr_path_parts[0] in obj.children_fields:
  430. try:
  431. children = getattr(obj, attr_path_parts[0])
  432. except AttributeError:
  433. raise NoSuchFile('No such object child %s' %(obj_path))
  434.  
  435. child_type = attr_path_parts[0][:-1] # strip plural
  436. if len(attr_path_parts) == 1:
  437. # printing all children
  438. children_content = []
  439. # find abspath of all children and recurse
  440. for child in children:
  441. child_path = '/%s/%s' %(child_type, child['uuid'])
  442. children_content.append(self.object_read(
  443. child_type, child_path,
  444. include_children, include_backrefs))
  445. return ','.join(children_content)
  446. # end all children of a type
  447.  
  448. # listing a specific child
  449. # generate abspath for child and recurse
  450. child_path = '/%s/%s' %(child_type, '/'.join(attr_path_parts[1:]))
  451. return self.object_read(child_type, child_path,
  452. include_children, include_backrefs)
  453. # end handling children
  454.  
  455. try:
  456. attr = getattr(obj, '.'.join(attr_path_parts))
  457. except AttributeError:
  458. return None
  459.  
  460. logger.debug('Reading attr_path %s value %s', attr_path, attr)
  461. if isinstance(attr, GeneratedsSuper):
  462. attr_json = json.dumps(attr,
  463. default=lambda o: dict((k,v) for k,v in o.__dict__.iteritems()))
  464. return attr_json
  465. else:
  466. return json.dumps(attr)
  467.  
  468. raise NoSuchFile('No such object file %s' %(obj_path))
  469. # end object_read
  470. # end class ContrailDriver
  471.  
  472. class NeutronDriver(object):
  473. def __init__(self, args=None):
  474. self.args = args
  475. # end class NeutronDriver
  476.  
  477. class Diagnostics(object):
  478. def __init__(self, args, filesystems):
  479. self.args = args
  480. self.fs = filesystems
  481. self.diag_cmds = [m[0].replace('diag_','')
  482. for m in inspect.getmembers(
  483. self, predicate=inspect.ismethod)
  484. if m[0].startswith('diag_')]
  485. self.contrail_config_api = ContrailDriver.get_config_api_connection(
  486. args.api_conf)
  487. # end __init__
  488.  
  489. def all_field_names(self, obj_type):
  490. return ContrailDriver.all_field_names(obj_type)
  491. # end all_field_names
  492.  
  493. def get_completions(self, text, line, begidx, endidx):
  494. # process last part in line
  495. line_parts = line.split()
  496. if len(line_parts) == 1:
  497. # trying to find all possible diag commands
  498. #diag_cmds = [m[0].replace('diag_','')
  499. # for m in inspect.getmembers(
  500. # self, predicate=inspect.ismethod)
  501. # if m[0].startswith('diag_')]
  502. return self.diag_cmds
  503.  
  504. partial_input = line.split()[-1]
  505. if (len(line_parts) == 2) and line[-1] != ' ':
  506. # trying to match specific diag command
  507. diag_cmd_pfx = partial_input
  508. return [c for c in self.diag_cmds if c.startswith(partial_input)]
  509.  
  510. # diag command known, complete custom or as a file
  511. diag_cmd = line_parts[1]
  512. if diag_cmd not in self.diag_cmds:
  513. return []
  514.  
  515. custom_completion = 'completion_%s' %(diag_cmd)
  516. if hasattr(self, custom_completion):
  517. return getattr(self, custom_completion)(text, line, begidx, endidx)
  518.  
  519. # default to complete as a file
  520. matches = self.fs.get_completions(partial_input)
  521. partial_base = os.path.basename(partial_input)
  522. return [text + x.replace(partial_base, '', 1) for x in matches]
  523. # end get_completions
  524.  
  525. def diag_vm_has_no_ip(self, arg_list):
  526. vm_uuid = arg_list[0].split('/')[-1]
  527. summary_report = []
  528. detailed_report = []
  529.  
  530. detailed_report.append('Inspected VM: %s' %(
  531. self.fs.inspect('/virtual-machine/%s' %(vm_uuid))))
  532. try:
  533. vm_obj = self.contrail_config_api.virtual_machine_read(
  534. id=vm_uuid,
  535. fields=self.all_field_names('virtual_machine'))
  536. except vnc_api.NoIdError as e:
  537. raise DiagException(summary_report, detailed_report, str(e))
  538.  
  539. vmi_uuids = [vmi['uuid'] for vmi in vm_obj.get_virtual_machine_interface_back_refs()]
  540. vmi_infos = []
  541. for vmi_uuid in vmi_uuids:
  542. detailed_report.append('Inspected VMI: %s' %(
  543. self.fs.inspect('/virtual-machine-interface/%s' %(vmi_uuid))))
  544. vmi_obj = self.contrail_config_api.virtual_machine_interface_read(id=vmi_uuid)
  545. vmi_info = {'vmi_name': vmi_obj.name,
  546. 'has_ri_ref': False,
  547. 'instance-ips': [],
  548. 'floating-ips': []}
  549.  
  550. # TODO: add check to see if right ri is ref'd
  551. if vmi_obj.get_routing_instance_refs():
  552. vmi_info['has_ri_ref'] = True
  553. for ri_ref in vmi_obj.get_routing_instance_refs():
  554. detailed_report.append('Inspected RI: %s' %(
  555. self.fs.inspect('/routing-instance/%s' %(ri_ref['uuid']))))
  556. else:
  557. summary_report.append(
  558. 'ERROR: VMI %s has no routing instance reference' %(vmi_uuid))
  559. for iip_back_ref in vmi_obj.get_instance_ip_back_refs() or []:
  560. iip_uuid = iip_back_ref['uuid']
  561. detailed_report.append('Inspected IIP: %s' %(
  562. self.fs.inspect('/instance-ip/%s' %(iip_uuid))))
  563. iip_obj = self.contrail_config_api.instance_ip_read(
  564. id=iip_uuid)
  565. vmi_info['instance-ips'].append(iip_obj.instance_ip_address)
  566. for fip_back_ref in vmi_obj.get_floating_ip_back_refs() or []:
  567. fip_uuid = fip_back_ref['uuid']
  568. detailed_report.append('Inspected FIP: %s' %(
  569. self.fs.inspect('/floating-ip/%s' %(fip_uuid))))
  570. fip_obj = self.contrail_config_api.floating_ip_read(
  571. id=fip_uuid)
  572. vmi_info['floating-ips'].append(fip_obj.floating_ip_address)
  573.  
  574. vmi_infos.append(vmi_info)
  575. # end for all vmi_uuids
  576.  
  577. vmis_present = "VM has %s interfaces: %s" %(
  578. len(vmi_infos), pprint(vmi_infos))
  579. summary_report.append(vmis_present)
  580.  
  581. def data_model_assertions():
  582. return "Data Model Checks: PASS"
  583.  
  584. def data_presence_assertions():
  585. return "Data Presence Checks: PASS"
  586.  
  587. summary_report.append(data_model_assertions())
  588. summary_report.append(data_presence_assertions())
  589.  
  590. return summary_report + detailed_report
  591. # end diag_vm_has_no_ip
  592.  
  593. def execute(self, diag_cmd, arg_list):
  594. try:
  595. return pprint(getattr(self, 'diag_%s' %(diag_cmd))(arg_list))
  596. except DiagException as e:
  597. return 'Diagnostic Exception: %s' %(str(e))
  598. # end execute
  599.  
  600. # end class Diagnostics
  601.  
  602. class DiagException(Exception):
  603. def __init__(self, summary, detailed, error):
  604. self.summary = summary
  605. self.detailed = detailed
  606. self.error = error
  607. # end __init__
  608.  
  609. def __str__(self):
  610. return 'Error: %s\nSummary-Report: %s\nDetailed-Report: %s\n' %(
  611. self.error, self.summary, self.detailed)
  612. # end __str__
  613. # end class DiagException
  614.  
  615.  
  616. class Shell(Cmd):
  617. def initialize(self, args, filesystems, diagnostics):
  618. self.filesystems = filesystems
  619. self.diagnostics = diagnostics
  620. # end initialize
  621.  
  622. def do_EOF(self, line):
  623. return True
  624. # end do_EOF
  625.  
  626. def default(self, line):
  627. print line
  628. # end default
  629.  
  630. def completedefault(self, text, line, begidx, endidx):
  631. # process last path in line
  632. logger.debug('text: %s', text)
  633. logger.debug('line: %s', line)
  634. logger.debug('last: %s', line.split()[-1])
  635. logger.debug('begidx: %s', begidx)
  636. logger.debug('endidx: %s', endidx)
  637.  
  638. partial_path = line.split()[-1]
  639. partial_base = os.path.basename(partial_path)
  640. matches = self.filesystems.get_completions(partial_path)
  641. logger.debug('\nmatches: %s, text: %s, pb: %s, begidx: %s, endidx: %s',
  642. matches, text, partial_base, begidx, endidx)
  643. # for each match found strip partial_base and prepend entered text
  644. return [text + x.replace(partial_base, '', 1) for x in matches]
  645.  
  646. #cmd = line.split()[0].strip().lower()
  647. #if cmd in set(['ls', 'cat']):
  648. # partial_path = line.split()[-1]
  649. # partial_base = os.path.basename(partial_path)
  650. # matches = self.filesystems.get_completions(partial_path)
  651. # logger.debug('\nmatches: %s, text: %s, pb: %s, begidx: %s, endidx: %s',
  652. # matches, text, partial_base, begidx, endidx)
  653. # # for each match found strip partial_base and prepend entered text
  654. # return [text + x.replace(partial_base, '', 1) for x in matches]
  655. #elif cmd == 'diagnose':
  656. # partial_input = line.split()[-1]
  657. # matches = self.diagnostics.get_completions(line, partial_input)
  658. # return matches
  659. # end completedefault
  660.  
  661. def complete_diagnose(self, text, line, begidx, endidx):
  662. matches = self.diagnostics.get_completions(text, line, begidx, endidx)
  663. return matches
  664.  
  665. #@options([
  666. # make_option('-b', '--list-back-references', action="store_true"),
  667. # make_option('-c', '--list-children', action="store_true"),
  668. # ])
  669. def do_ls(self, line, opts=None):
  670. entries = self.filesystems.ls(line, opts)
  671. if entries is None:
  672. return
  673. for e in entries:
  674. print e
  675. # end do_ls
  676.  
  677. @options([
  678. make_option('-b', '--read-back-references', action="store_true"),
  679. make_option('-c', '--read-children', action="store_true"),
  680. make_option('-p', '--output-python-dict', action="store_true"),
  681. ])
  682. def do_cat(self, line, opts=None):
  683. content = self.filesystems.cat(line, opts)
  684. if not content:
  685. return
  686.  
  687. if opts.output_python_dict:
  688. try:
  689. pprint(json.loads(content))
  690. except Exception as e:
  691. logger.error('Exception: %s for content: %s',
  692. str(e), content)
  693. else:
  694. print content
  695. # end do_cat
  696.  
  697. def do_inspect(self, line, opts=None):
  698. pass
  699. # end do_inspect
  700.  
  701. def do_diagnose(self, line, opts=None):
  702. line_parts = line.split()
  703. if not line_parts:
  704. print 'Choose one of %s' %(self.diagnostics.diag_cmds)
  705. return
  706.  
  707. diag_cmd = line_parts[0]
  708. if diag_cmd not in self.diagnostics.diag_cmds:
  709. print '%s: Invalid diagnostic command' %(diag_cmd)
  710. return
  711.  
  712. if len(line_parts) > 1:
  713. cmd_opts = line_parts[1:]
  714. else:
  715. cmd_opts = None
  716. diag_resp = self.diagnostics.execute(
  717. diag_cmd, cmd_opts)
  718. print diag_resp
  719. # end do_diagnose
  720. # end class Shell
  721.  
  722. def self_test(shell):
  723. with tempfile.NamedTemporaryFile() as test_f:
  724. def test_cmds_to_file():
  725. for cmd in test_cmds:
  726. test_f.write('%s\n' %(cmd))
  727. test_f.flush()
  728. return test_f
  729. # end test_cmds_to_file
  730. test_cmds_to_file()
  731. shell.do_load(test_f.name)
  732. test_f.close()
  733. return
  734. # end self_test
  735.  
  736. def main(args_str=None):
  737. cgitb.enable(format='text')
  738. logger.setLevel('ERROR')
  739. logformat = logging.Formatter("%(levelname)s: %(message)s")
  740. stdout = logging.StreamHandler()
  741. stdout.setLevel('ERROR')
  742. stdout.setFormatter(logformat)
  743. logger.addHandler(stdout)
  744.  
  745. parser = argparse.ArgumentParser()
  746.  
  747. help="Path to contrail-api conf files," \
  748. " default /etc/contrail-api.conf /etc/contrail/contrail-keystone-auth.conf"
  749. parser.add_argument(
  750. "--api-conf", action='append', help=help, metavar="FILE")
  751. parser.add_argument(
  752. "--self-test", action='store_true', help="Test shell commands")
  753. args, remaining_argv = parser.parse_known_args(
  754. args_str.split() if args_str else [])
  755.  
  756. shell = Shell()
  757. shell.debug = True
  758. shell.prompt = 'contrail> '
  759. fs = RestFileSystems()
  760. c_drv = ContrailDriver(args)
  761. fs.add_driver('/', c_drv)
  762. fs.add_driver('/neutron', NeutronDriver(args))
  763. diags = Diagnostics(args, fs)
  764. shell.initialize(args, fs, diags)
  765. if args.self_test:
  766. return self_test(shell)
  767.  
  768. shell.cmdloop()
  769. # end main
  770.  
  771. if __name__ == '__main__':
  772. main(' '.join(sys.argv[1:]))
Add Comment
Please, Sign In to add comment