00001
00002
00003
00004 '''rtshell
00005
00006 Copyright (C) 2009-2014
00007 Geoffrey Biggs
00008 RT-Synthesis Research Group
00009 Intelligent Systems Research Institute,
00010 National Institute of Advanced Industrial Science and Technology (AIST),
00011 Japan
00012 All rights reserved.
00013 Licensed under the Eclipse Public License -v 1.0 (EPL)
00014 http://www.opensource.org/licenses/eclipse-1.0.txt
00015
00016 Function objects for actions that can be performed using rtctree.
00017
00018 '''
00019
00020
00021 import sys
00022
00023 import rtctree.exceptions
00024 import rtctree.path
00025
00026 import option_store
00027 import rts_exceptions
00028
00029
00030
00031
00032
00033 class Action(object):
00034 '''Base class for all action function objects.
00035
00036 Action objects should implement the _execute method. This will receive one
00037 argument (a reference to the RTCTree object) and should implement the
00038 action. It must return True for success or False for failure, and a very
00039 brief error message.
00040
00041 All actions must be provided with one or more result callback objects.
00042 These will be called in the order they are set after performing the action
00043 and passed the result of the action's _execute method. Its job is to take
00044 appropriate measures based on the outcome of the action. Typically, the
00045 first should perform a verification that the result meets necessary
00046 criteria, such as a required action succeeding. If no callbacks are
00047 provided, a default (@ref BaseCallback) will be inserted.
00048
00049 Action objects must implement the __str__ method. They should print out a
00050 description of what they will do. This description should include details
00051 specific to that instance of the action (for example, "Will activate
00052 component 'ConsoleIn0.rtc'").
00053
00054 '''
00055
00056 def __init__(self, callbacks=[]):
00057 super(Action, self).__init__()
00058 self._callbacks = callbacks
00059
00060 def __call__(self, rtctree=None):
00061 result, err = self._execute(rtctree)
00062 if not self._callbacks:
00063 c = BaseCallback()
00064 c(result, err)
00065 else:
00066 for c in self._callbacks:
00067 c(result, err)
00068
00069 def __str__(self):
00070 return 'Base action'
00071
00072 def add_callback(self, callback):
00073 self._callbacks.append(callback)
00074
00075 @property
00076 def optional(self):
00077 '''Is this action optional?'''
00078 for cb in self._callbacks:
00079 if cb.__class__ == RequiredActionCB:
00080 return False
00081 return True
00082
00083 def _action_string(self, action_desc):
00084 if self._callbacks:
00085 action_desc += ' ({0}'.format(self._callbacks[0])
00086 for c in self._callbacks[1:]:
00087 action_desc += ', {0}'.format(c)
00088 action_desc += ')'
00089 return action_desc
00090
00091 def _execute(self, rtctree):
00092 '''Base for action execution method.
00093
00094 Return (True, '') or (False, 'Why I failed.') when implementing this
00095 method.
00096
00097 '''
00098 raise NotImplementedError
00099
00100
00101
00102
00103
00104 class BaseCallback(object):
00105 '''Base class for callback objects.
00106
00107 Callback objects must implement the __call__ method, and receive two
00108 values:
00109 - A boolean indicating success or failure of the action.
00110 - An error message to optionally be printed on failure. None if no message.
00111
00112 '''
00113 def __init__(self, *args, **kwargs):
00114 super(BaseCallback, self).__init__()
00115
00116 def __call__(self, result, err_msg):
00117 if err_msg:
00118 if not result:
00119 print >>sys.stderr, 'Action failed: ' + err_msg
00120 else:
00121 if not result:
00122 print >>sys.stderr, 'Action failed.'
00123
00124 def __str__(self):
00125 return ''
00126
00127
00128
00129
00130
00131 class RequiredActionCB(BaseCallback):
00132 '''Callback for a required action.
00133
00134 Checks the action result and raises @ref RequiredActionFailedError if the
00135 action failed.
00136
00137 '''
00138 def __init__(self, *args, **kwargs):
00139 super(RequiredActionCB, self).__init__(*args, **kwargs)
00140
00141 def __call__(self, result, err_msg):
00142 if not result:
00143 raise rts_exceptions.RequiredActionFailedError(err_msg)
00144
00145 def __str__(self):
00146 return 'Required'
00147
00148
00149
00150
00151
00152 class CheckForRequiredCompAct(Action):
00153 '''Check for a required component in the RTC Tree.
00154
00155 This action checks the rtctree to see if a component is present at a
00156 particular path. If it finds a component at that path, it will check that
00157 the component's ID and instance name to ensure it is the desired component.
00158 If the component is not present or is the wrong component, this action will
00159 fail. Otherwise, it will succeed.
00160
00161 '''
00162 def __init__(self, path_str, id, instance_name, callbacks=[]):
00163 super(CheckForRequiredCompAct, self).__init__(callbacks=callbacks)
00164 self._path_str = path_str
00165 self._path = rtctree.path.parse_path(path_str)[0]
00166 self._id = id
00167 self._instance_name = instance_name
00168
00169 def __str__(self):
00170 return self._action_string('Check for required component \
00171 "{0}", "{1}" at path {2}'.format(self._id, self._instance_name,
00172 self._path_str))
00173
00174 def _execute(self, rtctree):
00175 if option_store.OptionStore().verbose:
00176 print >>sys.stderr, 'Checking for required component {0} with ID \
00177 "{1}" and instance name "{2}"'.format(self._path_str, self._id,
00178 self._instance_name)
00179
00180 comp = rtctree.get_node(self._path)
00181 if not comp or not comp.is_component:
00182 return False, \
00183 'Required component missing: {0}'.format(self._path_str)
00184
00185 if comp.instance_name != self._instance_name:
00186 return False, 'Component instance names mismatched: {0} != \
00187 {1}'.format(comp.instance_name, self._instance_name)
00188
00189
00190 id = 'RTC:{0}:{1}:{2}:{3}'.format(comp.vendor, comp.category,
00191 comp.type_name, comp.version)
00192 if id != self._id:
00193 return False, 'Component IDs mismatched: {0} != {1}'.format(id,
00194 self._id)
00195
00196 return True, None
00197
00198
00199
00200
00201
00202 class CheckForPortAct(Action):
00203 '''Check for a port on a component in the RTC Tree.
00204
00205 This action checks the rtctree to see if a component is present at a
00206 particular path. If it finds a component at that path, it will check that
00207 the component has the desired port. If the port is not present on the
00208 component, it will fail. Otherwise, it will succeed. No check is performed
00209 to ensure that the correct component is at that path; for that, use the
00210 @ref CheckForRequiredCompAct action.
00211
00212 This action will not fail if the specified component does not exist or is
00213 incorrect. To cause an abort in these situations, use @ref
00214 CheckForRequiredCompAct.
00215
00216 '''
00217 def __init__(self, path_str, port_name, callbacks=[]):
00218 super(CheckForPortAct, self).__init__(callbacks=callbacks)
00219 self._path_str = path_str
00220 self._path = rtctree.path.parse_path(path_str)[0]
00221 self._port_name = port_name
00222
00223 def __str__(self):
00224 return self._action_string('Check for required port "{0}" on \
00225 component at path {1}'.format(self._port_name, self._path_str))
00226
00227 def _execute(self, rtctree):
00228 if option_store.OptionStore().verbose:
00229 print >>sys.stderr, 'Checking for required port {0} on component \
00230 {1}'.format(self._port_name, self._path_str)
00231
00232 comp = rtctree.get_node(self._path)
00233 if not comp or not comp.is_component:
00234 return True, None
00235
00236 if not comp.has_port_by_name(self._port_name):
00237 return False, \
00238 'Required port not found: {0}'.format(self._port_name)
00239
00240 return True, None
00241
00242
00243
00244
00245
00246 class CheckActiveConfigSetAct(Action):
00247 '''Checks if a configuration set is active in a component.
00248
00249 This action checks if the active configuration set of a component is as
00250 expected. It will check if the set exists first; if no such set exists,
00251 the action will fail.
00252
00253 This action will not fail if the specified component does not exist or is
00254 incorrect. To cause an abort in these situations, use @ref
00255 CheckForRequiredCompAct.
00256
00257 '''
00258 def __init__(self, path_str, set, callbacks=[]):
00259 super(CheckActiveConfigSetAct, self).__init__(callbacks=callbacks)
00260 self._path_str = path_str
00261 self._path = rtctree.path.parse_path(path_str)[0]
00262 self._set = str(set)
00263
00264 def __str__(self):
00265 return self._action_string('Check configuration set "{0}" is active '\
00266 'on component {1}'.format(self._set, self._path_str))
00267
00268 def _execute(self, rtctree):
00269 if option_store.OptionStore().verbose:
00270 print >>sys.stderr, 'Checking configuration set "{0}" is active '\
00271 'on component {1}'.format(self._set, self._path_str)
00272 comp = rtctree.get_node(self._path)
00273 if not comp or not comp.is_component:
00274 return False, 'Component missing: {0}'.format(self._path_str)
00275 if comp.active_conf_set_name != self._set:
00276 return False, 'Wrong configuration set is active on {0} '\
00277 '(Active set: {1})'.format(self._path_str,
00278 comp.active_conf_set_name)
00279 return True, None
00280
00281
00282
00283
00284
00285 class SetActiveConfigSetAct(Action):
00286 '''Set the active configuration set of a component.
00287
00288 This action sets the active configuration set of a component to the
00289 specified configuration set. It will check if the set exists first; if no
00290 such set exists, the action will fail.
00291
00292 This action will not fail if the specified component does not exist or is
00293 incorrect. To cause an abort in these situations, use @ref
00294 CheckForRequiredCompAct.
00295
00296 '''
00297 def __init__(self, path_str, set, callbacks=[]):
00298 super(SetActiveConfigSetAct, self).__init__(callbacks=callbacks)
00299 self._path_str = path_str
00300 self._path = rtctree.path.parse_path(path_str)[0]
00301 self._set = str(set)
00302
00303 def __str__(self):
00304 return self._action_string('Set configuration set "{0}" active on \
00305 component at path {1}'.format(self._set, self._path_str))
00306
00307 def _execute(self, rtctree):
00308 if option_store.OptionStore().verbose:
00309 print >>sys.stderr, 'Setting configuration set "{0}" active on \
00310 component {1}'.format(self._set, self._path_str)
00311 comp = rtctree.get_node(self._path)
00312 if not comp or not comp.is_component:
00313 return False, 'Component missing: {0}'.format(self._path_str)
00314 try:
00315 comp.activate_conf_set(self._set)
00316 except rts_exceptions.NoConfSetError:
00317 return False, 'Invalid configuration set: {0}'.format(self._set)
00318 return True, None
00319
00320
00321
00322
00323
00324 class CheckConfigParamAct(Action):
00325 '''Check the value of a configuration parameter.
00326
00327 This action checks that the value of a configuration parameter is correct.
00328 It will fail if the set or the parameter does not exist.
00329
00330 This action will not fail if the specified component does not exist or is
00331 incorrect. To cause an abort in these situations, use @ref
00332 CheckForRequiredCompAct.
00333
00334 '''
00335 def __init__(self, path_str, set, param, value, callbacks=[]):
00336 super(CheckConfigParamAct, self).__init__(callbacks=callbacks)
00337 self._path_str = path_str
00338 self._path = rtctree.path.parse_path(path_str)[0]
00339 self._set = str(set)
00340 self._param = str(param)
00341 self._value = str(value)
00342
00343 def __str__(self):
00344 return self._action_string('Check parameter "{0}" in set "{1}" on '\
00345 'component at path "{2}" is "{3}"'.format(self._param,
00346 self._set, self._path_str, self._value))
00347
00348 def _execute(self, rtctree):
00349 if option_store.OptionStore().verbose:
00350 print >>sys.stderr, 'Checking parameter "{0}" in set "{1}" on '\
00351 'component "{2}" is "{3}"'.format(self._param, self._set,
00352 self._path_str, self._value)
00353 comp = rtctree.get_node(self._path)
00354 if not comp or not comp.is_component:
00355 return False, 'Component missing: {0}'.format(self._path_str)
00356 if not self._set in comp.conf_sets:
00357 return False, 'Invalid configuration set: {0}'.format(self._set)
00358 if not comp.conf_sets[self._set].has_param(self._param):
00359 return False, 'Invalid configuration parameter: '\
00360 '{0}'.format(self._param)
00361 if comp.conf_sets[self._set].data[self._param] != self._value:
00362 return False, 'Configuration parameter {0} in set {1} on '\
00363 'component {2} is incorrect (value: {3})'.format(
00364 self._param, self._set, self._path_str,
00365 comp.conf_sets[self._set].data[self._param])
00366 return True, None
00367
00368
00369
00370
00371
00372 class SetConfigParamValueAct(Action):
00373 '''Change the value of a configuration parameter in a set.
00374
00375 This action sets the value of the given configuration parameter in the
00376 given configuration set. It will fail if the set does not exist, or the
00377 parameter does not exist in that set.
00378
00379 This action will not fail if the specified component does not exist or is
00380 incorrect. To cause an abort in these situations, use @ref
00381 CheckForRequiredCompAct.
00382
00383 '''
00384 def __init__(self, path_str, set, parameter, new_value, callbacks=[]):
00385 super(SetConfigParamValueAct, self).__init__(callbacks=callbacks)
00386 self._path_str = path_str
00387 self._path = rtctree.path.parse_path(path_str)[0]
00388 self._set = str(set)
00389 self._param = str(parameter)
00390 self._new_value = str(new_value)
00391
00392 def __str__(self):
00393 return self._action_string('Set parameter "{0}" in set "{1}" on \
00394 component at path {2} to "{3}"'.format(self._param, self._set,
00395 self._path_str, self._new_value))
00396
00397 def _execute(self, rtctree):
00398 if option_store.OptionStore().verbose:
00399 print >>sys.stderr, 'Setting parameter "{0}" in set "{1}" on \
00400 component at path {2} to "{3}"'.format(self._param, self._set,
00401 self._path_str, self._new_value)
00402 comp = rtctree.get_node(self._path)
00403 if not comp or not comp.is_component:
00404 return False, 'Component missing: {0}'.format(self._path_str)
00405 try:
00406 comp.set_conf_set_value(self._set, self._param, self._new_value)
00407 except rts_exceptions.NoConfSetError:
00408 return False, 'Invalid configuration set: {0}'.format(self._set)
00409 except rts_exceptions.NoSuchConfParamError:
00410 return False, 'Invalid configuration parameter: {0}'.format(self._param)
00411 comp.reparse_conf_sets()
00412 if self._set == comp.active_conf_set_name:
00413 comp.activate_conf_set(self._set)
00414 return True, None
00415
00416
00417
00418
00419
00420 class CheckForConnAct(Action):
00421 '''Check for a correct connection between two components.
00422
00423 This action checks if there is a connection between the specified source
00424 and destination ports. If there is, it will check that any given properties
00425 are also correct.
00426
00427 No check is performed to ensure that the correct component is at that path;
00428 for that, use the @ref CheckForRequiredCompAct action.
00429
00430 This action will not fail if the specified component does not exist or is
00431 incorrect. To cause an abort in these situations, use @ref
00432 CheckForRequiredCompAct.
00433
00434 '''
00435 def __init__(self, source, dest, id, props={}, callbacks=[]):
00436 super(CheckForConnAct, self).__init__(callbacks=callbacks)
00437 self._source = source
00438 self._s_path = rtctree.path.parse_path(self._source[0])[0]
00439 self._dest = dest
00440 self._d_path = rtctree.path.parse_path(self._dest[0])[0]
00441 self._id = id
00442 self._props = props
00443
00444 def __str__(self):
00445 return self._action_string('Check for connection from {0}:{1} to ' \
00446 '{2}:{3} with properties {4}'.format(self._source[0],
00447 self._source[1], self._dest[0], self._dest[1],
00448 self._props))
00449
00450 def _execute(self, rtctree):
00451 if option_store.OptionStore().verbose:
00452 print 'Checking for connection between {0}:{1} and ' \
00453 '{2}:{3}'.format(self._source[0], self._source[1],
00454 self._dest[0], self._dest[1])
00455
00456 s_comp = rtctree.get_node(self._s_path)
00457 if not s_comp or not s_comp.is_component:
00458 return False, 'Source component missing: {0}'.format(\
00459 self._source[0])
00460 s_port = s_comp.get_port_by_name(self._source[1])
00461 if not s_port:
00462 return False, 'Source port missing: {0}:{1}'.format(\
00463 self._source[0], self._source[1])
00464
00465 d_comp = rtctree.get_node(self._d_path)
00466 if not d_comp or not d_comp.is_component:
00467 return False, 'Destination component missing: {0}'.format(\
00468 self._dest[0])
00469 d_port = d_comp.get_port_by_name(self._dest[1])
00470 if not d_port:
00471 return False, 'Destination port missing: {0}:{1}'.format(\
00472 self._dest[0], self._dest[1])
00473
00474 conn = s_port.get_connection_by_id(self._id)
00475 if not conn:
00476
00477 return False, 'No connection between {0}:{1} and {2}:{3}'.format(
00478 self._source[0], self._source[1], self._dest[0],
00479 self._dest[1])
00480 conn = d_port.get_connection_by_id(self._id)
00481 if not conn:
00482
00483 return False, 'No connection between {0}:{1} and {2}:{3}'.format(
00484 self._source[0], self._source[1], self._dest[0],
00485 self._dest[1])
00486
00487 for k in self._props:
00488 if self._props[k] != conn.properties[k]:
00489 return False, 'Property {0} of connection from {1}:{2} to '\
00490 '{3}:{4} is incorrect.'.format(k, self._source[0],
00491 self._source[1], self._dest[0], self._dest[1])
00492
00493
00494 return True, None
00495
00496
00497
00498
00499
00500 class ConnectPortsAct(Action):
00501 '''Connect two ports together.
00502
00503 This action connects two ports together using the provided connection
00504 profile. It will fail if either the components or the ports ports are not
00505 present. No check is made to ensure the components at the specified paths
00506 are the correct components.
00507
00508 '''
00509 def __init__(self, source_path, source_port, dest_path, dest_port,
00510 name, id, properties, callbacks=[]):
00511 super(ConnectPortsAct, self).__init__(callbacks=callbacks)
00512 self._source_path_str = source_path
00513 self._source_path = rtctree.path.parse_path(source_path)[0]
00514 self._source_port = source_port
00515 self._dest_path_str = dest_path
00516 self._dest_path = rtctree.path.parse_path(dest_path)[0]
00517 self._dest_port = dest_port
00518 self._name = name
00519 self._id = id
00520 self._properties = properties.copy()
00521
00522 def __str__(self):
00523 return self._action_string('Connect {0}:{1} to {2}:{3} with \
00524 ID {4} and properties {5}'.format(self._source_path_str, self._source_port,
00525 self._dest_path_str, self._dest_port, self._id,
00526 self._properties))
00527
00528 def _execute(self, rtctree):
00529 if option_store.OptionStore().verbose:
00530 print >>sys.stderr, 'Connect {0}:{1} to {2}:{3} with \
00531 ID {4} and properties {5}'.format(self._source_path_str, self._source_port,
00532 self._dest_path_str, self._dest_port, self._id,
00533 self._properties)
00534 source_comp = rtctree.get_node(self._source_path)
00535 if not source_comp or not source_comp.is_component:
00536 return False, 'Source component missing: {0}'.format(\
00537 self._source_path_str)
00538 s_port = source_comp.get_port_by_name(self._source_port)
00539 if not s_port:
00540 return False, 'Source port missing: {0}:{1}'.format(\
00541 self._source_path_str, self._source_port)
00542 dest_comp = rtctree.get_node(self._dest_path)
00543 if not dest_comp or not dest_comp.is_component:
00544 return False, 'Destination component missing: {0}'.format(\
00545 self._dest_path_str)
00546 d_port = dest_comp.get_port_by_name(self._dest_port)
00547 if not d_port:
00548 return False, 'Destination port missing: {0}:{1}'.format(\
00549 self._dest_path_str, self._dest_port)
00550
00551 conn = s_port.get_connection_by_id(self._id)
00552 if not conn:
00553 if d_port.get_connection_by_id(self._id) is None:
00554
00555 s_port.connect([d_port], name=self._name, id=self._id,
00556 props=self._properties)
00557 return True, None
00558 else:
00559
00560
00561 return False, \
00562 'Destination port has existing connection with ID {0}'.format(
00563 self._id)
00564 else:
00565 if len(conn.ports) != 2 or not conn.has_port(d_port):
00566
00567
00568 return False, \
00569 'Source port has existing connection with ID {0}'.format(
00570 self._id)
00571 else:
00572
00573 for k in self._properties:
00574 if self._properties[k] != conn.properties[k]:
00575 return False, \
00576 'Property {0} of existing connection from '\
00577 '{1}:{2} to {3}:{4} with ID {5} does not '\
00578 'match'.format(k, self._source_path_str,
00579 self._source_port, self._dest_path_str,
00580 self._dest_port, self._id)
00581 if option_store.OptionStore().verbose:
00582 print >>sys.stderr, \
00583 'Skipped existing connection with ID {0}'.format(
00584 self._id)
00585 return True, None
00586
00587
00588
00589
00590
00591 class DisconnectPortsAct(Action):
00592 '''Disconnect two ports.
00593
00594 This action disconnects two ports. It will fail if either the components or
00595 the ports ports are not present. No check is made to ensure the components
00596 at the specified paths are the correct components.
00597
00598 '''
00599 def __init__(self, source_path, source_port, dest_path, dest_port, id,
00600 callbacks=[]):
00601 super(DisconnectPortsAct, self).__init__(callbacks=callbacks)
00602 self._source_path_str = source_path
00603 self._source_path = rtctree.path.parse_path(source_path)[0]
00604 self._source_port = source_port
00605 self._dest_path_str = dest_path
00606 self._dest_path = rtctree.path.parse_path(dest_path)[0]
00607 self._dest_port = dest_port
00608 self._id = id
00609
00610 def __str__(self):
00611 return self._action_string('Disconnect {0}:{1} from {2}:{3} with ID {4}'.format(\
00612 self._source_path_str, self._source_port, self._dest_path_str,
00613 self._dest_port, self._id))
00614
00615 def _execute(self, rtctree):
00616 if option_store.OptionStore().verbose:
00617 print >>sys.stderr, \
00618 'Disconnecting {0}:{1} from {2}:{3} with ID {4}'.format(\
00619 self._source_path_str, self._source_port,
00620 self._dest_path_str, self._dest_port, self._id)
00621 source_comp = rtctree.get_node(self._source_path)
00622 if not source_comp or not source_comp.is_component:
00623 return False, 'Source component missing: {0}'.format(\
00624 self._source_path_str)
00625 source_port_obj = source_comp.get_port_by_name(self._source_port)
00626 if not source_port_obj:
00627 return False, 'Source port missing: {0}:{1}'.format(\
00628 self._source_path_str, self._source_port)
00629 dest_comp = rtctree.get_node(self._dest_path)
00630 if not dest_comp or not dest_comp.is_component:
00631 return False, 'Destination component missing: {0}'.format(\
00632 self._dest_path_str)
00633 dest_port_obj = dest_comp.get_port_by_name(self._dest_port)
00634 if not dest_port_obj:
00635 return False, 'Destination port missing: {0}:{1}'.format(\
00636 self._dest_path_str, self._dest_port)
00637
00638 s_conn = source_port_obj.get_connection_by_id(self._id)
00639 if not s_conn:
00640 return False, 'No connection from {0}:{1} with ID {2}'.format(
00641 self._source_path_str, self._source_port, self._id)
00642 d_conn = dest_port_obj.get_connection_by_id(self._id)
00643 if not d_conn:
00644 return False, 'No connection to {0}:{1} with ID {2}'.format(
00645 self._dest_path_str, self._dest_port, self._id)
00646 s_conn.disconnect()
00647 return True, None
00648
00649
00650
00651
00652
00653 class StateChangeAct(Action):
00654 '''Base action for actions that change a component's state.
00655
00656 Actions that inherit from this should provide three members:
00657 - self._action_str: A string describing the action for use in str(). e.g.
00658 "Activate".
00659 - self._verbose_str: A similar string for use in the verbose output. e.g.
00660 "Activating".
00661 - self._action_impl: A function to be called by self._execute to perform
00662 the action. It will be passed two arguments; the first is the component
00663 node from rtctree, the second is the index of the execution context
00664 involved. This should return (True, None) or False and an error string.
00665
00666 '''
00667 def __init__(self, path_str, comp_id, instance_name, ec_id, callbacks=[]):
00668 super(StateChangeAct, self).__init__(callbacks=callbacks)
00669 self._path_str = path_str
00670 self._comp_id = comp_id
00671 self._instance_name = instance_name
00672 self._path = rtctree.path.parse_path(path_str)[0]
00673 self._ec_id = ec_id
00674
00675 def __str__(self):
00676 return self._action_string('{0} {1} in execution context {2}'.format(\
00677 self._action_str, self._path_str, self._ec_id))
00678
00679 @property
00680 def comp_id(self):
00681 '''Identification string of the component.'''
00682 return self._comp_id
00683
00684 @property
00685 def ec_id(self):
00686 '''Target execution context ID.'''
00687 return self._ec_id
00688
00689 @property
00690 def instance_name(self):
00691 '''Instance name of the target component.'''
00692 return self._instance_name
00693
00694 @property
00695 def path(self):
00696 '''Full path of the target component.'''
00697 return self._path_str
00698
00699 def _execute(self, rtctree):
00700 if option_store.OptionStore().verbose:
00701 print >>sys.stderr, '{0} {1} in {2}'.format(self._verbose_str,
00702 self._path_str, self._ec_id)
00703 comp = rtctree.get_node(self._path)
00704 if not comp or not comp.is_component:
00705 return False, 'Component missing: {0}'.format(self._path_str)
00706 ec_index = comp.get_ec_index(int(self._ec_id))
00707 if ec_index < 0:
00708 return False, 'Invalid execution context: {0}'.format(self._ec_id)
00709 return self._action_impl(comp, ec_index)
00710
00711
00712
00713
00714
00715 class CheckCompStateAct(StateChangeAct):
00716 '''Check component state in an execution context.
00717
00718 This action checks that the state of an execution context is as expected.
00719
00720 '''
00721 def __init__(self, path_str, comp_id, instance_name, ec_id, expected,
00722 callbacks=[]):
00723 super(CheckCompStateAct, self).__init__(path_str, comp_id,
00724 instance_name, ec_id, callbacks=callbacks)
00725 self._expected = expected
00726 self._action_str = 'Check state is {0} for'.format(self._expected)
00727 self._verbose_str = 'Checking state is {0} for'.format(self._expected)
00728
00729 def _action_impl(self, comp, ec_index):
00730 if (self._expected.lower() == 'active' and \
00731 comp.state_in_ec(ec_index) == comp.ACTIVE) or \
00732 (self._expected.lower() == 'inactive' and \
00733 comp.state_in_ec(ec_index) == comp.INACTIVE) or \
00734 (self._expected.lower() == 'error' and \
00735 comp.state_in_ec(ec_index) == comp.ERROR) or \
00736 (self._expected.lower() == 'created' and \
00737 comp.state_in_ec(ec_index) == comp.CREATED) or \
00738 (self._expected.lower() == 'unknown' and \
00739 comp.state_in_ec(ec_index) == comp.UNKNOWN):
00740 return True, None
00741 return False, 'Component {0} is in incorrect state {1}'.format(
00742 self._path_str,
00743 comp.get_state_in_ec_string(ec_index, add_colour=False))
00744
00745
00746
00747
00748
00749 class ActivateCompAct(StateChangeAct):
00750 '''Activate a component.
00751
00752 This action changes the status of a component to active.
00753
00754 '''
00755 def __init__(self, path_str, comp_id, instance_name, ec_id, callbacks=[]):
00756 super(ActivateCompAct, self).__init__(path_str, comp_id, instance_name,
00757 ec_id, callbacks=callbacks)
00758 self._action_str = 'Activate'
00759 self._verbose_str = 'Activating'
00760
00761 def _action_impl(self, comp, ec_index):
00762 comp.activate_in_ec(ec_index)
00763 return True, None
00764
00765
00766
00767
00768
00769 class DeactivateCompAct(StateChangeAct):
00770 '''Deactivate a component.
00771
00772 This action changes the status of a component to inactive.
00773
00774 '''
00775 def __init__(self, path_str, comp_id, instance_name, ec_id, callbacks=[]):
00776 super(DeactivateCompAct, self).__init__(path_str, comp_id,
00777 instance_name, ec_id, callbacks=callbacks)
00778 self._action_str = 'Deactivate'
00779 self._verbose_str = 'Deactivating'
00780
00781 def _action_impl(self, comp, ec_index):
00782 comp.deactivate_in_ec(ec_index)
00783 return True, None
00784
00785
00786
00787
00788
00789 class ResetCompAct(StateChangeAct):
00790 '''Reset a component.
00791
00792 This action changes the status of a component to inactive from error.
00793
00794 '''
00795 def __init__(self, path_str, comp_id, instance_name, ec_id, callbacks=[]):
00796 super(ResetCompAct, self).__init__(path_str, comp_id, instance_name,
00797 ec_id, callbacks=callbacks)
00798 self._action_str = 'Reset'
00799 self._verbose_str = 'Resetting'
00800
00801 def _action_impl(self, comp, ec_index):
00802 comp.reset_in_ec(ec_index)
00803 return True, None
00804
00805
00806
00807