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 rtcheck library.
00018
00019 '''
00020
00021
00022 import optparse
00023 import os
00024 import rtctree.path
00025 import rtctree.tree
00026 import rtsprofile.rts_profile
00027 import sys
00028 import traceback
00029
00030 import actions
00031 import option_store
00032 import rts_exceptions
00033 import rtshell
00034
00035
00036 class SystemNotOKCB(rtshell.actions.BaseCallback):
00037 '''Callback for a required action.
00038
00039 Checks the action result and raises @ref RequiredActionFailedError if the
00040 action failed.
00041
00042 '''
00043 def __init__(self, *args, **kwargs):
00044 super(SystemNotOKCB, self).__init__(*args, **kwargs)
00045 self._failed = False
00046
00047 def __call__(self, result, err_msg):
00048 if err_msg:
00049 print >>sys.stderr, err_msg
00050 if not result:
00051 self._failed = True
00052
00053 def __str__(self):
00054 return 'Required'
00055
00056 @property
00057 def failed(self):
00058 '''Did any calls to this callback indicate failure?'''
00059 return self._failed
00060
00061
00062 def get_data_conn_props(conn):
00063 return {'dataport.dataflow_type': str(conn.data_flow_type),
00064 'dataport.interface_type': str(conn.interface_type),
00065 'dataport.subscription_type': str(conn.subscription_type),
00066 'dataport.data_type': str(conn.data_type)}
00067
00068
00069 def check_comps(rtsprofile, req_cb):
00070 checks = []
00071 for comp in [c for c in rtsprofile.components if c.is_required]:
00072 checks.append(rtshell.actions.CheckForRequiredCompAct('/' +
00073 comp.path_uri, comp.id, comp.instance_name, callbacks=[req_cb]))
00074 for comp in [c for c in rtsprofile.components if not c.is_required]:
00075 checks.append(rtshell.actions.CheckForRequiredCompAct('/' +
00076 comp.path_uri, comp.id, comp.instance_name))
00077 return checks
00078
00079
00080 def check_connection(c, rtsprofile, props, cbs):
00081 s_comp = rtsprofile.find_comp_by_target(c.source_data_port)
00082 s_path = '/' + s_comp.path_uri
00083 s_port = c.source_data_port.port_name
00084 prefix = s_comp.instance_name + '.'
00085 if s_port.startswith(prefix):
00086 s_port = s_port[len(prefix):]
00087 d_comp = rtsprofile.find_comp_by_target(c.target_data_port)
00088 d_path = '/' + d_comp.path_uri
00089 d_port = c.target_data_port.port_name
00090 prefix = d_comp.instance_name + '.'
00091 if d_port.startswith(prefix):
00092 d_port = d_port[len(prefix):]
00093 return rtshell.actions.CheckForConnAct((s_path, s_port), (d_path, d_port),
00094 str(c.connector_id), props, callbacks=cbs)
00095
00096
00097 def check_connections(rtsprofile, req_cb):
00098 checks = []
00099 for c in rtsprofile.required_data_connections():
00100 props = get_data_conn_props(c)
00101 checks.append(check_connection(c, rtsprofile, props, [req_cb]))
00102
00103 for c in rtsprofile.optional_data_connections():
00104 props = get_data_conn_props(c)
00105 checks.append(check_connection(c, rtsprofile, props, []))
00106
00107 for c in rtsprofile.required_service_connections():
00108 checks.append(check_connection(c, rtsprofile, {} [req_cb]))
00109
00110 for c in rtsprofile.optional_service_connections():
00111 checks.append(check_connection(c, rtsprofile, {}, []))
00112
00113 return checks
00114
00115
00116 def check_configs(rtsprofile, req_cb):
00117 checks = []
00118
00119 for c in rtsprofile.components:
00120 if c.active_configuration_set:
00121 checks.append(rtshell.actions.CheckActiveConfigSetAct('/' +
00122 c.path_uri, c.active_configuration_set, callbacks=[req_cb]))
00123 for cs in c.configuration_sets:
00124 for p in cs.configuration_data:
00125 checks.append(rtshell.actions.CheckConfigParamAct('/' +
00126 c.path_uri, cs.id, p.name, p.data, callbacks=[req_cb]))
00127 return checks
00128
00129
00130 def check_states(rtsprofile, expected, req_cb):
00131 checks = []
00132 for comp in [c for c in rtsprofile.components if c.is_required]:
00133 for ec in comp.execution_contexts:
00134 checks.append(rtshell.actions.CheckCompStateAct('/' +
00135 comp.path_uri, comp.id, comp.instance_name, ec.id, expected,
00136 callbacks=[req_cb]))
00137 for comp in [c for c in rtsprofile.components if not c.is_required]:
00138 for ec in comp.execution_contexts:
00139 checks.append(rtshell.actions.CheckCompStateAct('/' +
00140 comp.path_uri, comp.id, comp.instance_name, ec.id, expected))
00141 return checks
00142
00143
00144 def check(profile=None, xml=True, state='Active', dry_run=False, tree=None):
00145
00146 if profile:
00147
00148 with open(profile) as f:
00149 if xml:
00150 rtsp = rtsprofile.rts_profile.RtsProfile(xml_spec=f)
00151 else:
00152 rtsp = rtsprofile.rts_profile.RtsProfile(yaml_spec=f)
00153 else:
00154
00155 lines = sys.stdin.read()
00156 if xml:
00157 rtsp = rtsprofile.rts_profile.RtsProfile(xml_spec=lines)
00158 else:
00159 rtsp = rtsprofile.rts_profile.RtsProfile(yaml_spec=lines)
00160
00161
00162 cb = SystemNotOKCB()
00163 actions = (check_comps(rtsp, cb) + check_connections(rtsp, cb) +
00164 check_configs(rtsp, cb) + check_states(rtsp, state, cb))
00165 if dry_run:
00166 for a in actions:
00167 print a
00168 else:
00169 if not tree:
00170
00171 tree = rtctree.tree.RTCTree(paths=[rtctree.path.parse_path(
00172 '/' + c.path_uri)[0] for c in rtsp.components])
00173 for a in actions:
00174 a(tree)
00175 if cb.failed:
00176 return False
00177 return True
00178
00179
00180 def main(argv=None, tree=None):
00181 usage = '''Usage: %prog [options] <RTSProfile specification file>
00182 Check that the running RT System conforms to an RTSProfile.'''
00183 parser = optparse.OptionParser(usage=usage, version=rtshell.RTSH_VERSION)
00184 parser.add_option('--dry-run', dest='dry_run', action='store_true',
00185 default=False, help="Print what will be done but don't actually '\
00186 'do anything. [Default: %default]")
00187 parser.add_option('-s', '--state', dest='state', action='store',
00188 type='string', default='Active',
00189 help='The expected state of the RT Components in the system. ' \
00190 '[Default: %default]')
00191 parser.add_option('-v', '--verbose', dest='verbose', action='store_true',
00192 default=False,
00193 help='Output verbose information. [Default: %default]')
00194 parser.add_option('-x', '--xml', dest='xml', action='store_true',
00195 default=True, help='Use XML input format. [Default: True]')
00196 parser.add_option('-y', '--yaml', dest='xml', action='store_false',
00197 help='Use YAML input format. [Default: False]')
00198
00199 if argv:
00200 sys.argv = [sys.argv[0]] + argv
00201 try:
00202 options, args = parser.parse_args()
00203 except optparse.OptionError, e:
00204 print >>sys.stderr, 'OptionError: ', e
00205 return 1
00206 rtshell.option_store.OptionStore().verbose = options.verbose
00207
00208 if not args:
00209 profile = None
00210 elif len(args) == 1:
00211 profile = args[0]
00212 else:
00213 print >>sys.stderr, usage
00214 return 1
00215
00216 try:
00217 if not check(profile=profile, xml=options.xml, state=options.state,
00218 dry_run=options.dry_run, tree=tree):
00219 return 1
00220 except Exception, e:
00221 if options.verbose:
00222 traceback.print_exc()
00223 print >>sys.stderr, '{0}: {1}'.format(sys.argv[0], e)
00224 return 1
00225 return 0
00226
00227
00228
00229