00001
00002
00003
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
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
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
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
00117
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
00150 to_remove = []
00151 for rtc in rtcs:
00152 if rtcs[rtc][1]:
00153
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
00169 add_paths = parse_member_paths(options.add)
00170 rem_paths = parse_member_paths(options.remove)
00171
00172
00173 tgt_path, tgt_suffix = rtctree.path.parse_path(tgt_full_path)
00174
00175
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
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
00190
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
00199 if not tgt_suffix:
00200 tgt_suffix = 'CompositeRTC'
00201 tgt_raw_path += ':' + tgt_suffix
00202
00203 comp = tgt_obj.get_node([tgt_obj.name, tgt_suffix + '.rtc'])
00204 if not comp:
00205
00206 if options.remove:
00207 raise rts_exceptions.CannotRemoveFromNewCompositionError()
00208
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
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
00288