rtcomp.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 # -*- Python -*-
00003 # -*- coding: utf-8 -*-
00004 
00005 '''rtshell
00006 
00007 Copyright (C) 2009-2014
00008     Geoffrey Biggs
00009     RT-Synthesis Research Group
00010     Intelligent Systems Research Institute,
00011     National Institute of Advanced Industrial Science and Technology (AIST),
00012     Japan
00013     All rights reserved.
00014 Licensed under the Eclipse Public License -v 1.0 (EPL)
00015 http://www.opensource.org/licenses/eclipse-1.0.txt
00016 
00017 Implementation of the compose-components command.
00018 
00019 '''
00020 
00021 
00022 import optparse
00023 import os
00024 import rtctree.exceptions
00025 import rtctree.path
00026 import rtctree.tree
00027 import rtctree.utils
00028 import SDOPackage
00029 import SDOPackage__POA
00030 import sys
00031 import traceback
00032 
00033 import path
00034 import rtmgr
00035 import rts_exceptions
00036 import rtshell
00037 
00038 
00039 def parse_member_paths(source_paths):
00040     paths = []
00041     for p in source_paths:
00042         ports = []
00043         split = p.split(':')
00044         if len(split) == 2:
00045             p = split[0]
00046             ports = split[1].split(',')
00047         elif len(split) > 2:
00048             raise rtctree.exceptions.BadPathError(p)
00049         fp = path.cmd_path_to_full_path(p)
00050         c_path, ignored = rtctree.path.parse_path(fp)
00051         paths.append((p, c_path, ports))
00052     return paths
00053 
00054 
00055 def get_comp_objs(paths, tree):
00056     objs = {}
00057     for fp, cp, ports in paths:
00058         obj = tree.get_node(cp)
00059         if not obj:
00060             raise rts_exceptions.NoSuchObjectError(fp)
00061         if not obj.is_component:
00062             raise rts_exceptions.NotAComponentError(fp)
00063         objs[fp] = (obj, ports)
00064     return objs
00065 
00066 
00067 def get_potential_comp_objs(paths, tree):
00068     objs = {}
00069     zombies = {}
00070     for fp, cp, ports in paths:
00071         obj = tree.get_node(cp)
00072         if not obj:
00073             zombies[fp] = (cp[0], ports)
00074         else:
00075             objs[fp] = (obj, ports)
00076     return objs, zombies
00077 
00078 
00079 def create_composition(mgr, name, options, comp_type):
00080     if not options.startswith('&'):
00081         options = '&' + options
00082     mgr.create_component('{0}?&instance_name={1}{2}'.format(comp_type, name,
00083         options))
00084     return mgr.get_node([mgr.name, name + '.rtc'])
00085 
00086 
00087 def add_to_composition(comp, rtcs, tree, verbose):
00088     # Set the exported ports
00089     current_ports = comp.conf_sets['default'].data['exported_ports'].split(',')
00090     current_ports = [x for x in current_ports if x]
00091     new_ports = current_ports
00092     for rtc in rtcs:
00093         c = rtcs[rtc][0]
00094         for p in rtcs[rtc][1]:
00095             # Port existence check has already been done
00096             p_name = rtcs[rtc][0].instance_name + '.' + p
00097             if p_name not in new_ports:
00098                 if verbose:
00099                     print >>sys.stderr, \
00100                             'Exporting port {0} from composition'.format(p_name)
00101                 new_ports.append(p_name)
00102     if new_ports:
00103         new_ports = reduce(lambda x, y: x + ',' + y, new_ports)
00104         comp.set_conf_set_value('default', 'exported_ports', new_ports)
00105         comp.activate_conf_set('default')
00106     # Add the new RTCs to the composition
00107     to_add = []
00108     for rtc in rtcs:
00109         c = rtcs[rtc][0]
00110         if not comp.is_member(c):
00111             if verbose:
00112                 print >>sys.stderr, \
00113                         'Adding component {0} to composition'.format(rtc)
00114             to_add.append(c)
00115         elif verbose and not rtcs[rtc][1]:
00116             # Only print this message if the component didn't have any ports to
00117             # add
00118             print >>sys.stderr, \
00119                     'Component {0} is already in composition'.format(rtc)
00120     comp.add_members(to_add)
00121 
00122 
00123 def rem_from_composition(comp, rtcs, tree, verbose):
00124     current_ports = comp.conf_sets['default'].data['exported_ports'].split(',')
00125     current_ports = [x for x in current_ports if x]
00126     new_ports = current_ports
00127     for rtc in rtcs:
00128         if type(rtcs[rtc][0]) is str:
00129             inst_name = rtcs[rtc][0]
00130         else:
00131             inst_name = rtcs[rtc][0].instance_name
00132         for p in rtcs[rtc][1]:
00133             p_name = inst_name + '.' + p
00134             if p_name in new_ports:
00135                 if verbose:
00136                     print >>sys.stderr, \
00137                             'Hiding port {0} in composition'.format(p_name)
00138                 new_ports.remove(p_name)
00139             elif verbose:
00140                 print >>sys.stderr, \
00141                         'Port {0} is already hidden in composition'.format(
00142                                 p_name)
00143     if new_ports:
00144         new_ports = reduce(lambda x, y: x + ',' + y, new_ports)
00145     else:
00146         new_ports = ''
00147     comp.set_conf_set_value('default', 'exported_ports', new_ports)
00148     comp.activate_conf_set('default')
00149     # Remove RTCs that have no ports specified from the composition
00150     to_remove = []
00151     for rtc in rtcs:
00152         if rtcs[rtc][1]:
00153             # Ignore components that had ports specified
00154             continue
00155         c = rtcs[rtc][0]
00156         if comp.is_member(c):
00157             if verbose:
00158                 print >>sys.stderr, \
00159                         'Removing component {0} from composition'.format(rtc)
00160             to_remove.append(c)
00161         elif verbose:
00162             print >>sys.stderr, \
00163                     'Component {0} is not in composition'.format(rtc)
00164     comp.remove_members(to_remove)
00165 
00166 
00167 def manage_composition(tgt_raw_path, tgt_full_path, options, tree=None):
00168     # Parse paths of components to add/remove
00169     add_paths = parse_member_paths(options.add)
00170     rem_paths = parse_member_paths(options.remove)
00171 
00172     # The target, either a manager or a component
00173     tgt_path, tgt_suffix = rtctree.path.parse_path(tgt_full_path)
00174 
00175     # Make a tree
00176     if not tree:
00177         paths = [tgt_path] + [y for x, y, z in add_paths + rem_paths]
00178         tree = rtctree.tree.RTCTree(paths=paths, filter=paths)
00179     tgt_obj = tree.get_node(tgt_path)
00180     if not tgt_obj:
00181         raise rts_exceptions.NoSuchObjectError(tgt_raw_path)
00182 
00183     # Input sanity check: ensure all components and ports to be added exist
00184     add_rtcs = get_comp_objs(add_paths, tree)
00185     for rtc in add_rtcs:
00186         for p in add_rtcs[rtc][1]:
00187             if not add_rtcs[rtc][0].get_port_by_name(p):
00188                 raise rts_exceptions.PortNotFoundError(rtc, p)
00189     # Ensure all ports to be removed that are on components that are alive
00190     # exist
00191     rem_rtcs, rem_zombies = get_potential_comp_objs(rem_paths, tree)
00192     for rtc in rem_rtcs:
00193         for p in rem_rtcs[rtc][1]:
00194             if not rem_rtcs[rtc][0].get_port_by_name(p):
00195                 raise rts_exceptions.PortNotFoundError(rtc, p)
00196 
00197     if tgt_obj.is_manager:
00198         # Create composition
00199         if not tgt_suffix:
00200             tgt_suffix = 'CompositeRTC'
00201             tgt_raw_path += ':' + tgt_suffix
00202         # Check if this composition already exists
00203         comp = tgt_obj.get_node([tgt_obj.name, tgt_suffix + '.rtc'])
00204         if not comp:
00205             # Cannot remove components when creating a new composition
00206             if options.remove:
00207                 raise rts_exceptions.CannotRemoveFromNewCompositionError()
00208             # No composition exists in this manager; make a new one
00209             if options.verbose:
00210                 print >>sys.stderr, 'Creating new composition {0}'.format(
00211                         tgt_raw_path)
00212             comp = create_composition(tgt_obj, tgt_suffix, options.options,
00213                     options.type)
00214         elif options.verbose:
00215             print >>sys.stderr, 'Editing existing composition {0}'.format(
00216                     tgt_raw_path)
00217     elif tgt_obj.is_component:
00218         # Edit composition - there should be no suffix
00219         if tgt_suffix:
00220             raise rts_exceptions.NotAComponentError(tgt_raw_path)
00221         comp = tgt_obj
00222         if options.verbose:
00223             print >>sys.stderr, 'Editing existing composition {0}'.format(
00224                     tgt_raw_path)
00225     else:
00226         raise rts_exceptions.NotAComponentOrManagerError(tgt_raw_path)
00227     if not comp.is_composite:
00228         raise rts_exceptions.NotACompositeComponentError(tgt_raw_path)
00229 
00230     if add_paths:
00231         add_to_composition(comp, add_rtcs, tree, options.verbose)
00232     if rem_paths:
00233         rem_rtcs.update(rem_zombies)
00234         rem_from_composition(comp, rem_rtcs, tree, options.verbose)
00235     if not comp.members[comp.organisations[0].org_id]:
00236         if options.verbose:
00237             print >>sys.stderr, 'Composition {0} has no members'.format(
00238                     tgt_raw_path)
00239 
00240 
00241 def main(argv=None, tree=None):
00242     usage = '''Usage: %prog [options] <manager:name|composite component path>
00243 Manage composite components.'''
00244     version = rtshell.RTSH_VERSION
00245     parser = optparse.OptionParser(usage=usage, version=version)
00246     parser.add_option('-a', '--add', dest='add', action='append',
00247             type='string', default=[], help='A component to include in the '
00248             'composition. Specify a comma-separated list of ports to export '
00249             'after the component name, separated by a colon.')
00250     parser.add_option('-o', '--options', dest='options', action='store',
00251             type='string', default='', help='Extra options to pass to the '\
00252             'component on creation.')
00253     parser.add_option('-r', '--remove', dest='remove', action='append',
00254             type='string', default=[], help='A component or ports to remove '
00255             'from the composition.')
00256     parser.add_option('-t', '--type', dest='type', action='store',
00257             type='string', default='PeriodicECSharedComposite',
00258             help='Type of composite component to create. [Default: %default]')
00259     parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
00260             default=False,
00261             help='Output verbose information. [Default: %default]')
00262 
00263     if argv:
00264         sys.argv = [sys.argv[0]] + argv
00265     try:
00266         options, args = parser.parse_args()
00267     except optparse.OptionError, e:
00268         print >>sys.stderr, 'OptionError:', e
00269         return 1
00270 
00271     if len(args) != 1:
00272         print >>sys.stderr, '{0}: No manager or existing composite component '\
00273             'specified.'.format(sys.argv[0])
00274         return 1
00275     full_path = path.cmd_path_to_full_path(args[0])
00276 
00277     try:
00278         manage_composition(args[0], full_path, options, tree=tree)
00279     except Exception, e:
00280         if options.verbose:
00281             traceback.print_exc()
00282         print >>sys.stderr, '{0}: {1}'.format(sys.argv[0], e)
00283         return 1
00284     return 0
00285 
00286 
00287 # vim: tw=79
00288 


rtshell
Author(s): Geoffrey Biggs
autogenerated on Fri Aug 28 2015 12:55:12