예제 #1
0
class FysomStateTests(unittest.TestCase):
    def setUp(self):
        self.fsm = Fysom({
            'initial': 'green',
            'events': [
                {'name': 'warn', 'src': 'green', 'dst': 'yellow'},
                {'name': 'panic', 'src': 'yellow', 'dst': 'red'},
                {'name': 'calm', 'src': 'red', 'dst': 'yellow'},
                {'name': 'clear', 'src': 'yellow', 'dst': 'green'}
            ]
        })

    def test_is_state_should_succeed_for_initial_state(self):
        self.assertTrue(self.fsm.isstate('green'))

    def test_identity_transition_should_not_be_allowed_by_default(self):
        self.assertFalse(self.fsm.can('clear'))
        self.assertTrue(self.fsm.cannot('clear'))

    def test_configured_transition_should_work(self):
        self.assertTrue(self.fsm.can('warn'))

    def test_transition_should_change_state(self):
        self.fsm.warn()
        self.assertTrue(self.fsm.isstate('yellow'))

    def test_should_raise_exception_when_state_transition_is_not_allowed(self):
        self.assertRaises(FysomError, self.fsm.panic)
        self.assertRaises(FysomError, self.fsm.calm)
        self.assertRaises(FysomError, self.fsm.clear)
예제 #2
0
    def do_stem(self, word):
        fsm = Fysom(initial='start', events=self.events)

        i = len(word) - 1
        j = len(word)

        while (True):
            if i <= 0:
                break
            v = word[i:j]
            # print v
            res = fsm.can(v)
            if (res):
                if v == 'i' and fsm.can(word[i - 1:j]):
                    i = i - 1
                    continue
                fsm.trigger(v)
                if fsm.current == 'h':
                    if word[i - 1:i] == 'i':
                        i = i - 1  # skip i
                        if word[i - 1:i] == 'n':
                            # ning qushimchasi
                            fsm.current = 'start'
                            continue
                elif fsm.current == 'b':
                    fsm.current = 'start'
                j = i

            i = i - 1

        return word[:j]
예제 #3
0
파일: devon.py 프로젝트: anvarulugov/devon
    def do_stem(self, word):
        fsm = Fysom(initial='start', events=self.events)
        # FIXME: uncomment below and make sanitize functions support
        # both Python 2 and 3 versions
        # word = WordProcessor.sanitize(word)
        i = len(word) - 1
        j = len(word)

        while (True):
            if i <= 0:
                break
            v = word[i:j]
            # print v
            res = fsm.can(v)
            if (res):
                if v == 'i' and fsm.can(word[i - 1:j]):
                    i = i - 1
                    continue
                fsm.trigger(v)
                if fsm.current == 'h':
                    if word[i - 1:i] == 'i':
                        i = i - 1  # skip i
                        if word[i - 1:i] == 'n':
                            # ning qushimchasi
                            fsm.current = 'start'
                            continue
                elif fsm.current == 'b':
                    fsm.current = 'start'
                j = i

            i = i - 1

        return word[:j]
예제 #4
0
파일: devon.py 프로젝트: MrBrownWins/devon
    def do_stem(self, word):
        fsm = Fysom(initial='start', events=self.events)
        # FIXME: uncomment below and make sanitize functions support
        # both Python 2 and 3 versions
        # word = WordProcessor.sanitize(word)
        i = len(word) - 1
        j = len(word)

        while(True):
            if i <= 0:
                break
            v = word[i:j]
            # print v
            res = fsm.can(v)
            if (res):
                if v == 'i' and fsm.can(word[i-1:j]):
                    i = i - 1
                    continue
                fsm.trigger(v)
                if fsm.current == 'h':
                    if word[i-1:i] == 'i':
                        i = i - 1  # skip i
                        if word[i-1:i] == 'n':
                            # ning qushimchasi
                            fsm.current = 'start'
                            continue
                elif fsm.current == 'b':
                    fsm.current = 'start'
                j = i

            i = i - 1

        return word[:j]
예제 #5
0
class FysomStateTests(unittest.TestCase):
    def setUp(self):
        self.fsm = Fysom({
            'initial': 'green',
            'events': [
                {'name': 'warn', 'src': 'green', 'dst': 'yellow'},
                {'name': 'panic', 'src': 'yellow', 'dst': 'red'},
                {'name': 'calm', 'src': 'red', 'dst': 'yellow'},
                {'name': 'clear', 'src': 'yellow', 'dst': 'green'},
                {'name': 'warm', 'src': 'green', 'dst': 'blue'}
            ]
        })

    def test_is_state_should_succeed_for_initial_state(self):
        self.assertTrue(self.fsm.isstate('green'))

    def test_identity_transition_should_not_be_allowed_by_default(self):
        self.assertFalse(self.fsm.can('clear'))
        self.assertTrue(self.fsm.cannot('clear'))

    def test_configured_transition_should_work(self):
        self.assertTrue(self.fsm.can('warn'))

    def test_transition_should_change_state(self):
        self.fsm.warn()
        self.assertTrue(self.fsm.isstate('yellow'))

    def test_should_raise_exception_when_state_transition_is_not_allowed(self):
        self.assertRaises(FysomError, self.fsm.panic)
        self.assertRaises(FysomError, self.fsm.calm)
        self.assertRaises(FysomError, self.fsm.clear)

    def test_event_handler_has_name_and_docstring(self):
        self.assertEqual(self.fsm.warm.__name__, "warm", "Event handlers do not have appropriate name.")
        self.assertNotEqual(self.fsm.warm.__name__, None, "Docstring for event handler is None!")

    def test_trigger_should_trigger_the_event_handler(self):
        self.assertEqual(self.fsm.current, "green", "The initial state isn't the expected state.")
        self.fsm.trigger("warm")
        make_callable = lambda: self.fsm.trigger("unknowevent")
        self.assertRaises(FysomError, make_callable)
        self.assertEqual(self.fsm.current, "blue", "The initial state isn't the expected state.")
예제 #6
0
class FysomStateTests(unittest.TestCase):
    def setUp(self):
        self.fsm = Fysom({
            'initial':
            'green',
            'events': [{
                'name': 'warn',
                'src': 'green',
                'dst': 'yellow'
            }, {
                'name': 'panic',
                'src': 'yellow',
                'dst': 'red'
            }, {
                'name': 'calm',
                'src': 'red',
                'dst': 'yellow'
            }, {
                'name': 'clear',
                'src': 'yellow',
                'dst': 'green'
            }]
        })

    def test_is_state_should_succeed_for_initial_state(self):
        self.assertTrue(self.fsm.isstate('green'))

    def test_identity_transition_should_not_be_allowed_by_default(self):
        self.assertFalse(self.fsm.can('clear'))
        self.assertTrue(self.fsm.cannot('clear'))

    def test_configured_transition_should_work(self):
        self.assertTrue(self.fsm.can('warn'))

    def test_transition_should_change_state(self):
        self.fsm.warn()
        self.assertTrue(self.fsm.isstate('yellow'))

    def test_should_raise_exception_when_state_transition_is_not_allowed(self):
        self.assertRaises(FysomError, self.fsm.panic)
        self.assertRaises(FysomError, self.fsm.calm)
        self.assertRaises(FysomError, self.fsm.clear)
예제 #7
0
class StatesTestCase(unittest.TestCase):
    def setUp(self):
        self.fsm = Fysom({
            'initial': 'green',
            'events': [
                {'name': 'warn', 'src': 'green', 'dst': 'yellow'},
                {'name': 'panic', 'src': 'yellow', 'dst': 'red'},
                {'name': 'calm', 'src': 'red', 'dst': 'yellow'},
                {'name': 'clear', 'src': 'yellow', 'dst': 'green'}
            ]
        })

    def test_invalid_state(self):
        self.assertRaises(AttributeError, getattr, self.fsm, 'wtfbbq')

    def test_state_conditions(self):
        """
        This will check for example, if state is in clear, will be able to emit
        warn and will not be able to emit panic, calm or clear again.
        """
        self.assertTrue(self.fsm.isstate('green'))
        self.assertTrue(self.fsm.can('warn'))
        self.assertFalse(self.fsm.can('panic'))
        self.assertTrue(self.fsm.cannot('panic'))
        self.assertFalse(self.fsm.can('clam'))
        self.assertFalse(self.fsm.can('clear'))

    def test_state_changing(self):
        self.assertTrue(self.fsm.isstate('green'))
        self.fsm.warn()
        self.assertTrue(self.fsm.isstate('yellow'))

    def test_state_cannot_be_called_twice(self):
        self.fsm.warn()
        self.assertTrue(self.fsm.isstate('yellow'))
        self.assertRaises(FysomError, self.fsm.warn)

    def test_auto_next_state(self):
        self.assertEqual('green', self.fsm.current)

        self.assertEqual('yellow', self.fsm.next())
        self.assertEqual('yellow', self.fsm.current)

    def test_multiple_possibilities_for_next(self):
        fsm = Fysom({
            'initial': 'green',
            'events': [
                {'name': 'warn', 'src': 'green', 'dst': 'yellow'},
                {'name': 'panic', 'src': 'yellow', 'dst': 'red'},
                {'name': 'panic', 'src': 'green', 'dst': 'red'},
                {'name': 'calm', 'src': 'red', 'dst': 'yellow'},
                {'name': 'clear', 'src': 'yellow', 'dst': 'green'}
            ]
        })

        self.assertRaises(MultiplePossibilitesFound, fsm.next)

    def test_no_possibility_for_next(self):
        fsm = Fysom({
            'initial': 'green',
            'events': [
                {'name': 'panic', 'src': 'yellow', 'dst': 'red'},
                {'name': 'calm', 'src': 'red', 'dst': 'yellow'},
                {'name': 'clear', 'src': 'yellow', 'dst': 'green'}
            ]
        })

        self.assertRaises(NoPossibilityFound, fsm.next)

    def test_goto(self):
        fsm = Fysom({
            'initial': 'green',
            'events': [
                {'name': 'warn', 'src': 'green', 'dst': 'yellow'},
                {'name': 'panic', 'src': 'yellow', 'dst': 'red'},
                {'name': 'panic', 'src': 'green', 'dst': 'red'},
                {'name': 'calm', 'src': 'red', 'dst': 'yellow'},
                {'name': 'clear', 'src': 'yellow', 'dst': 'green'}
            ]
        })
        self.assertRaises(MultiplePossibilitesFound, fsm.next)
        self.assertEqual('red', fsm.goto('panic'))

    def test_no_possibility_for_goto(self):
        fsm = Fysom({
            'initial': 'green',
            'events': [
                {'name': 'warn', 'src': 'green', 'dst': 'yellow'},
                {'name': 'panic', 'src': 'yellow', 'dst': 'red'},
                {'name': 'panic', 'src': 'green', 'dst': 'red'},
                # when call panic from green, we go to red, from red we
                # should go to yellow, but it is commented and we should
                # have a exception
                # {'name': 'calm', 'src': 'red', 'dst': 'yellow'},
                {'name': 'clear', 'src': 'yellow', 'dst': 'green'}
            ]
        })

        self.assertRaises(MultiplePossibilitesFound, fsm.next)
        self.assertEqual('red', fsm.goto('panic'))
        self.assertRaises(NoPossibilityFound, fsm.goto, 'calm')
예제 #8
0
class FysomStateTests(unittest.TestCase):
    def setUp(self):
        self.fsm = Fysom({
            'initial':
            'green',
            'events': [{
                'name': 'warn',
                'src': 'green',
                'dst': 'yellow'
            }, {
                'name': 'panic',
                'src': 'yellow',
                'dst': 'red'
            }, {
                'name': 'calm',
                'src': 'red',
                'dst': 'yellow'
            }, {
                'name': 'clear',
                'src': 'yellow',
                'dst': 'green'
            }, {
                'name': 'warm',
                'src': 'green',
                'dst': 'blue'
            }]
        })

    def test_is_state_should_succeed_for_initial_state(self):
        self.assertTrue(self.fsm.isstate('green'))

    def test_identity_transition_should_not_be_allowed_by_default(self):
        self.assertFalse(self.fsm.can('clear'))
        self.assertTrue(self.fsm.cannot('clear'))

    def test_configured_transition_should_work(self):
        self.assertTrue(self.fsm.can('warn'))

    def test_transition_should_change_state(self):
        self.fsm.warn()
        self.assertTrue(self.fsm.isstate('yellow'))

    def test_should_raise_exception_when_state_transition_is_not_allowed(self):
        self.assertRaises(FysomError, self.fsm.panic)
        self.assertRaises(FysomError, self.fsm.calm)
        self.assertRaises(FysomError, self.fsm.clear)

    def test_event_handler_has_name_and_docstring(self):
        self.assertEqual(self.fsm.warm.__name__, "warm",
                         "Event handlers do not have appropriate name.")
        self.assertNotEqual(self.fsm.warm.__name__, None,
                            "Docstring for event handler is None!")

    def test_trigger_should_trigger_the_event_handler(self):
        self.assertEqual(self.fsm.current, "green",
                         "The initial state isn't the expected state.")
        self.fsm.trigger("warm")
        self.assertRaises(FysomError, self.fsm.trigger, "unknown_event")
        self.assertEqual(self.fsm.current, "blue",
                         "The initial state isn't the expected state.")

    def test_trigger_should_trigger_the_event_handler_with_args(self):
        self.assertEqual(self.fsm.current, "green",
                         "The initial state isn't the expected state.")

        def onblue(event):
            self.assertEqual(event.args, ("any-positional-argument", ))

        self.fsm.onblue = onblue

        self.fsm.trigger("warm", "any-positional-argument")
        self.assertEqual(self.fsm.current, "blue",
                         "The initial state isn't the expected state.")

    def test_trigger_should_trigger_the_event_handler_with_kwargs(self):
        self.assertEqual(self.fsm.current, "green",
                         "The initial state isn't the expected state.")

        def onblue(event):
            self.assertEqual(event.keyword_argument, "any-value")

        self.fsm.onblue = onblue

        self.fsm.trigger("warm", keyword_argument="any-value")
        self.assertEqual(self.fsm.current, "blue",
                         "The initial state isn't the expected state.")
#!/usr/bin/python
from fysom import Fysom

print "Experimenting finite state machine package."
fsm = Fysom({'initial': 'green',
	         'events': [
                 { 'name': 'warn', 'src': 'green', 'dst': 'yellow' },
                 { 'name': 'panic', 'src': 'yellow', 'dst': 'red' },
                 { 'name': 'calm', 'src': 'red', 'dst': 'yellow' },
                 { 'name': 'clear', 'src': 'yellow', 'dst': 'green' }
	         ]})


print "Current state = " + fsm.current
print "Is in state 'red? = %r" % fsm.isstate('red')
print "Is in state 'green? = %r" % fsm.isstate('green')
print "Can fire event %s from state %s? = %r" % ('warn', fsm.current, fsm.can('warn'))
print "Can fire event %s from state %s? = %r" % ('panic', fsm.current, fsm.can('panic'))
print "Can fire event %s from state %s? = %r" % ('clear', fsm.current, fsm.can('clear'))

print ""
print "Firing event warn"
fsm.warn()
print "Current state = " + fsm.current
print "Is in state 'red? = %r" % fsm.isstate('red')
print "Is in state 'green? = %r" % fsm.isstate('green')
print "Can fire event %s from state %s? = %r" % ('warn', fsm.current, fsm.can('warn'))
print "Can fire event %s from state %s? = %r" % ('panic', fsm.current, fsm.can('panic'))
print "Can fire event %s from state %s? = %r" % ('clear', fsm.current, fsm.can('clear'))
예제 #10
0
class Manager(object):
    INTF = "cmc_eth0"
    DHCP_SOCK_ADDRESS = 'ipc:///tmp/zmq-dhcp.ipc'
    TPC_SOCK_ADDRESS = 'ipc:///tmp/zmq-tpc.ipc'
    RCP_SOCK_ADDRESS = 'ipc:///tmp/zmq-rcp.ipc'
    HAL_SOCK_ADDRESS = 'ipc:///tmp/zmq-hal.ipc'
    EXAMPLE_PROC_SOCK_ADDRESS = 'ipc:///tmp/zmq-example.ipc'
    IF_UP_TIMEOUT = 60
    # If process should respond in exponential backoff timer, this is safety
    # catch for cases, when something goes wrong
    BACKOFF_TIMEOUT = 600

    dhcp_data_path = ['oper', 'DhcpData']
    hw_version_path = ['oper', 'HwVersion']
    hw_version = "OPENWRT v1"

    __metaclass__ = AddLoggerToClass

    def __init__(self):
        self.dhcpv4_process = None
        self.dhcpv6_process = None
        self.sfd_stream = None
        self.db = RPD_DB()
        self.db_adapter = CfgDbAdapter(self.db)
        self.dhcp_data = t_DhcpData()
        self.disp = Dispatcher()
        self.signal_mask = self.create_signal_mask()
        self.dhcp_sock = None
        self.dhcp_timer = None
        self.processes = {}

        ProcessInfo.dispatcher = self.disp
        self.processes['dhcpv6'] = ProcessInfo(
            [
                "odhcp6c",  # Args - start
                "-s",
                "/lib/netifd/dhcpv6.script",
                "-P",
                "0",
                # Request IPv6 Prefix = auto
                "-t",
                "256",
                # Random backoff <1, 256>
                "-v",  # Verbose
                "-I",
                self.DHCP_SOCK_ADDRESS
            ],  # Args - end
            self.DHCP_SOCK_ADDRESS,  # IPC address
            self.BACKOFF_TIMEOUT,  # Timeout in seconds
            self._dhcp_no_lease  # Timeout callback
        )
        self.processes['dhcpv4'] = ProcessInfo(
            [
                "udhcpc",  # Args - start
                "-p",  # Create PID file
                "/var/run/udhcpc-" + self.INTF + ".pid",
                "-f",
                "-t",
                "8",  # Random backoff <1, 256>
                "-i",
                self.INTF,
                "-C",  # Don't send MAC address as client-id
                "-B",  # Enable broadcast
                "-S",  # Enable logging to syslog
                "-n",  # Exit if lease is not obtained
                "-I",
                self.DHCP_SOCK_ADDRESS
            ],  # Args - end
            self.DHCP_SOCK_ADDRESS,  # IPC address
            self.BACKOFF_TIMEOUT,  # Timeout in seconds
            self._dhcp_no_lease  # Timeout callback
        )
        self.processes['rcp'] = ProcessInfo(
            [
                "python",  # Args - start
                "-m",
                "rpd.rcp.rcp_process",
                "--ipc-address",
                self.RCP_SOCK_ADDRESS
            ],  # Args - end
            self.RCP_SOCK_ADDRESS  # IPC address
        )

        confFile = '/etc/config/hal.conf'
        self.processes['hal'] = ProcessInfo(
            ("python -m rpd.hal.src.HalMain --conf=" + confFile).split(" "),
            "")
        self.processes['tpc'] = ProcessInfo(
            [
                "python",  # Args - start
                "-m",
                "rpd.tpc",
                "--ipc-address",
                self.TPC_SOCK_ADDRESS
            ],  # Args - end
            self.TPC_SOCK_ADDRESS,  # IPC address
            self.BACKOFF_TIMEOUT,  # Timeout in seconds
            self.reboot  # Timeout callback
        )
        self.processes['example'] = ProcessInfo(
            [
                "python",  # Args - start
                "-m",
                "rpd.example",
                "--ipc-address",
                self.EXAMPLE_PROC_SOCK_ADDRESS
            ],  # Args - end
            self.EXAMPLE_PROC_SOCK_ADDRESS,  # IPC address
            60,  # Timeout in seconds
            self.reboot  # Timeout callback
        )
        self.processes['example'].start(self.example_msg_cb)
        # Source of subTLV codes - section 6.4.1 of
        # http://www.cablelabs.com/wp-content/uploads/specdocs/CM-SP-R-PHY-I01_150615.pdf
        rpd_ident = ['cfg', 'RpdCapabilities', 'RpdIdentification']

        self.dhcp_args_mapping = {
            '0x02': rpd_ident + ['DeviceDescription'],
            '0x04': rpd_ident + ['SerialNumber'],
            '0x05': Manager.hw_version_path,
            '0x06': rpd_ident + ['CurrentSwVersion'],
            '0x07': rpd_ident + ['BootRomVersion'],
            '0x08':
            "".join(SysTools.get_mac_address(
                self.INTF).split(':')[0:3]),  # vendor ID
            '0x09': rpd_ident + ['ModelNumber'],
            '0x0A': rpd_ident + ['VendorName']
        }

        # Fill device information to DB, if not loaded
        mac_addr_str = rpd_ident + ['DeviceMacAddress']
        if self.db_adapter.get_leaf(mac_addr_str) is None:
            # TODO negative case handling
            self.db_adapter.set_leaf(mac_addr_str,
                                     SysTools.get_mac_address(self.INTF), True)

        hostname_str = rpd_ident + ['DeviceAlias']
        if self.db_adapter.get_leaf(hostname_str) is None:
            # TODO negative case handling
            self.db_adapter.set_leaf(hostname_str, SysTools.get_host_name(),
                                     True)

        # TODO get from HW
        if self.db_adapter.get_leaf(Manager.hw_version_path) is None:
            # TODO negative case handling
            self.db_adapter.set_leaf(Manager.hw_version_path,
                                     Manager.hw_version, True)

        self.fsm = Fysom({
            'initial': {
                'state': 'init'
            },
            'events': [{
                'name': 'init_done',
                'src': 'init',
                'dst': 'if_up_waiting'
            }, {
                'name': 'if_is_up',
                'src': 'if_up_waiting',
                'dst': 'dhcpv6_waiting'
            }, {
                'name': 'dhcpv6_failed',
                'src': 'dhcpv6_waiting',
                'dst': 'dhcpv4_waiting'
            }, {
                'name':
                'dhcp_ack',
                'src': [
                    'dhcpv6_waiting', 'dhcpv4_waiting', 'time_waiting',
                    'log_waiting', 'gcp_started'
                ],
                'dst':
                'time_waiting'
            }, {
                'name': 'time_cfged',
                'src': 'time_waiting',
                'dst': 'log_waiting'
            }, {
                'name': 'log_done',
                'src': 'log_waiting',
                'dst': 'gcp_started'
            }, {
                'name':
                'fatal_failure',
                'src': [
                    'if_up_waiting', 'dhcpv6_waiting', 'dhcpv4_waiting',
                    'time_waiting', 'gcp_started'
                ],
                'dst':
                'reboot'
            }],
            'callbacks': {
                'onchangestate': self._onchangestate,
                'onif_is_up': self._on_iface_is_up,
                'ondhcp_ack': self._ondhcp_ack,
                'ontime_cfged': self._ontime_cfged,
                'onlog_done': self._onlog_done,
                'onfatal_failure': self.reboot,
            }
        })

    def delete_dhcp_data(self):
        """Delete DHCP data structure from DB and also clear cached copy of it.

        :return:

        """
        # TODO negative case handling
        self.db_adapter.del_leaf(Manager.dhcp_data_path)

    def store_dhcp_data(self):
        """Save updated cached copy of DHCP data to DB. This must be called
        after each set operation to this cached structure (to keep it
        synchronized).

        :return:

        """
        # TODO negative case handling - clear self.DhcpData
        self.db_adapter.set_leaf(Manager.dhcp_data_path, self.dhcp_data, True)

    def _dhcp_timeout_cb(self, _):
        """DHCP process haven't responded in limited time (backoff timer +
        extra time), so probably something wrong happened (DHCP process
        crashed, was killed, stuck in a loop, ...)

        :return:

        """
        self.logger.warn("DHCP timer expired")
        self._dhcp_no_lease()

    def _dhcp_data_ready(self):
        """Received new DHCP data, do necessary cleanup if needed
        (start/update) (old GCP sessions must be closed). Keep remote logging
        enabled, so we don't loose syslog messages in case of DHCP update.

        :return:

        """
        if not self.fsm.can('dhcp_ack'):
            raise ValueError("Wrong state '%s' for dhcp_ack event",
                             self.fsm.current)

        self.fsm.dhcp_ack()

    def _dhcp_no_lease(self):
        """DHCP client failed to get required information (backoff timer
        increased to maximum value without success)

        - If DHCPv6 failed -> try DHCPv4
        - If DHCPv4 failed -> reboot

        :return:

        """
        dhcpv6_proc = self.processes['dhcpv6']
        dhcpv4_proc = self.processes['dhcpv4']

        if dhcpv6_proc.process is not None:
            # Kill DHCPv6 process if it still running, cleanup all related
            # stuff, but keep ipc_sock - it will be reused for dhcpv4
            dhcpv6_proc.cleanup(close_ipc_sock=False)
            dhcpv6_proc.process = None

            if not self.fsm.can('dhcpv6_failed'):
                raise ValueError("Wrong state '%s' for dhcpv6_failed event",
                                 self.fsm.current)
            self.fsm.dhcpv6_failed()
            # Prepare "runtime" args
            args = []
            for code, attr in self.dhcp_args_mapping.iteritems():
                if isinstance(attr, basestring):
                    attr_val = attr
                else:
                    attr_val = self.db_adapter.get_leaf(attr)
                if attr_val is None or not isinstance(attr_val, basestring):
                    self.logger.warning(
                        "Attribute: %s not set in DB, ignoring ", attr)
                    continue
                # append args in format: -x 0x0A:value
                args.extend(['-c', '{}:{}'.format(code, attr_val)])
            self.logger.info("Starting DHCPv4 client ...")
            dhcpv4_proc.start(self.dhcp_msg_cb, args, dhcpv6_proc.ipc_sock)
        elif dhcpv4_proc.process is not None:
            dhcpv4_proc.cleanup()
            dhcpv4_proc.process = None
            self.logger.error("Both DHCPv6 & DHCPv4 failed - exiting ...")
            self.fsm.fatal_failure()
        else:
            raise ValueError("Received unexpected DHCP failed message")

    def _cleanup(self):
        """Cleanup method, this should be used only in scenario, when Manager
        is killed directly.

        :return:

        """
        for process in self.processes.values():
            process.cleanup()

        if self.sfd_stream is not None:
            self.sfd_stream.close()

        self.configure_remote_logging(None)
        exit(0)

    def testing_cleanup(self):
        """Cleanup method for testing purposes."""
        for process in self.processes.values():
            process.cleanup()

        if self.sfd_stream is not None:
            self.sfd_stream.close()
        # let the cleanup finish
        time.sleep(2)

    def fd_event_handler(self, signal_fd, eventmask):
        """Callback called by dispatcher when any signal is received on
        signalfd Reads signal info from fd and calls applicable signal handler.

        :return:

        """
        del eventmask
        siginfo = signalfd_siginfo()
        if self.sfd_stream is None:
            try:
                self.sfd_stream = os.fdopen(signal_fd, 'rb', 0)
            except IOError, ex:
                self.logger.error("Failed to open signal fd - %s",
                                  os.strerror(ex.errno))
                self._cleanup()
                return
        self.sfd_stream.readinto(siginfo)
        self._signal_handler(siginfo.ssi_signo, None)
예제 #11
0
파일: states.py 프로젝트: bytearchive/fysom
class StatesTestCase(unittest.TestCase):
    def setUp(self):
        self.fsm = Fysom({
            'initial': 'green',
            'events': [
                {'name': 'warn', 'src': 'green', 'dst': 'yellow'},
                {'name': 'panic', 'src': 'yellow', 'dst': 'red'},
                {'name': 'calm', 'src': 'red', 'dst': 'yellow'},
                {'name': 'clear', 'src': 'yellow', 'dst': 'green'}
            ]
        })

    def test_invalid_state(self):
        self.assertRaises(AttributeError, getattr, self.fsm, 'wtfbbq')

    def test_state_conditions(self):
        """
        This will check for example, if state is in clear, will be able to emit
        warn and will not be able to emit panic, calm or clear again.
        """
        self.assertTrue(self.fsm.isstate('green'))
        self.assertTrue(self.fsm.can('warn'))
        self.assertFalse(self.fsm.can('panic'))
        self.assertTrue(self.fsm.cannot('panic'))
        self.assertFalse(self.fsm.can('clam'))
        self.assertFalse(self.fsm.can('clear'))

    def test_state_changing(self):
        self.assertTrue(self.fsm.isstate('green'))
        self.fsm.warn()
        self.assertTrue(self.fsm.isstate('yellow'))

    def test_state_cannot_be_called_twice(self):
        self.fsm.warn()
        self.assertTrue(self.fsm.isstate('yellow'))
        self.assertRaises(FysomError, self.fsm.warn)

    def test_auto_next_state(self):
        self.assertEqual('green', self.fsm.current)

        self.assertEqual('yellow', self.fsm.next())
        self.assertEqual('yellow', self.fsm.current)

    def test_multiple_possibilities_for_next(self):
        fsm = Fysom({
            'initial': 'green',
            'events': [
                {'name': 'warn', 'src': 'green', 'dst': 'yellow'},
                {'name': 'panic', 'src': 'yellow', 'dst': 'red'},
                {'name': 'panic', 'src': 'green', 'dst': 'red'},
                {'name': 'calm', 'src': 'red', 'dst': 'yellow'},
                {'name': 'clear', 'src': 'yellow', 'dst': 'green'}
            ]
        })

        self.assertRaises(MultiplePossibilitesFound, fsm.next)

    def test_no_possibility_for_next(self):
        fsm = Fysom({
            'initial': 'green',
            'events': [
                {'name': 'panic', 'src': 'yellow', 'dst': 'red'},
                {'name': 'calm', 'src': 'red', 'dst': 'yellow'},
                {'name': 'clear', 'src': 'yellow', 'dst': 'green'}
            ]
        })

        self.assertRaises(NoPossibilityFound, fsm.next)