Example #1
0
 def __init__(self):
     self._quit = False
     if len(sys.argv) >= 2:
         config = parse_conf(sys.argv[1])
     else:
         config = parse_conf('ivt.yml')
     config = config_schema.validate(config)
     self.config = config
     if len(sys.argv) >= 3:
         channel_config = parse_conf(sys.argv[2])
     else:
         channel_config = parse_conf('ivt_channels.yml')
     self.ivt = IVT(
         config['project'],
         config['login_code'],
         config['login_passwd'],
         config['keepalive_interval'],
         channel_config
     )
     WSClientTransport.APP_FACTORY = self.ivt.ivt_session_factory
     self.ws_url = config['ivc']+'?'+urllib.urlencode(
         {
             'login_code': config['login_code'],
             'login_passwd': config['login_passwd'],
             'project': config['project'],
             'hardware_model': config['hardware_model'],
             'firmware_model': IVT_VERSION
         }
     )
     self._retry_evt = Event()
     self._done_upgrade_evt = Event()
     self._done_upgrade_evt.set()
     gevent.signal(signal.SIGINT, self.close)
     gevent.signal(signal.SIGTERM, self.close)
     self._greenlet_chk_ivt_package = gevent.spawn(self._chk_new_ivt_firmware)
Example #2
0
def main():
    default_log_config(debug=True)
    import logging
    log = logging.getLogger(__name__)

    try:
        if len(sys.argv) == 2:
            config = parse_conf(sys.argv[1])
        else:
            config = parse_conf('ivt.yml')
        config = config_schema.validate(config)

        ivt = IVT(config['project'],
                  config['login_code'],
                  config['login_passwd'],
                  config['keepalive_interval'],
                  config['cameras'],
                  preview_upload_server=config.get('preview_upload_server'))

        # start port
        port = SubProcessPort(
            port_name=config['login_code'],
            port_type=RTSP_PORT_PROGRAM_NAME,
            log_file=RTSP_PORT_PROGRAM_NAME + '.log',
        )
        port.start()

        # connect to IVC
        WSClientTransport.APP_FACTORY = ivt.ivt_session_factory
        url = config['ivc'] + '?' + urllib.urlencode(
            {
                'login_code': config['login_code'],
                'login_passwd': config['login_passwd'],
                'project': config['project']
            })
        while True:
            try:
                client = WSClientTransport(url)
                client.connect()
                client.wait_close()
                time.sleep(10)
            except:
                log.exception("Client session closed")
                time.sleep(10)

    except Exception:
        log.exception('Failed to start IVT')
Example #3
0
class App(object):

    ivt_package_schema = Schema({
        'firmware_model': Use(STRING),
        'url': Use(STRING),
    })

    def __init__(self):
        self._quit = False
        if len(sys.argv) >= 2:
            config = parse_conf(sys.argv[1])
        else:
            config = parse_conf('ivt.yml')
        config = config_schema.validate(config)
        self.config = config
        if len(sys.argv) >= 3:
            channel_config = parse_conf(sys.argv[2])
        else:
            channel_config = parse_conf('ivt_channels.yml')
        self.ivt = IVT(
            config['project'],
            config['login_code'],
            config['login_passwd'],
            config['keepalive_interval'],
            channel_config
        )
        WSClientTransport.APP_FACTORY = self.ivt.ivt_session_factory
        self.ws_url = config['ivc']+'?'+urllib.urlencode(
            {
                'login_code': config['login_code'],
                'login_passwd': config['login_passwd'],
                'project': config['project'],
                'hardware_model': config['hardware_model'],
                'firmware_model': IVT_VERSION
            }
        )
        self._retry_evt = Event()
        self._done_upgrade_evt = Event()
        self._done_upgrade_evt.set()
        gevent.signal(signal.SIGINT, self.close)
        gevent.signal(signal.SIGTERM, self.close)
        self._greenlet_chk_ivt_package = gevent.spawn(self._chk_new_ivt_firmware)

    def run(self):
        while not self._quit:
            try:
                client = WSClientTransport(self.ws_url)
                client.connect()
                client.wait_close()
            except:
                log.exception("Client session closed")
            finally:
                if not self._quit:
                    self._retry_evt.wait(timeout=30)
                    self._retry_evt.clear()
        self._done_upgrade_evt.wait()
        log.info('Quit')
        sys.exit(0)

    def close(self):
        log.info('Closing')
        self._quit = True
        self.ivt.close()
        self._retry_evt.set()

    def _chk_new_ivt_firmware(self):
        gevent.sleep(5)
        while True:
            try:
                ivt_package = self.ivt.chk_new_ivt_firmware()
                if not ivt_package:
                    continue
                ivt_package = self.ivt_package_schema.validate(ivt_package)
                target_ivt_version = ivt_package['firmware_model']
                if target_ivt_version.strip() == IVT_VERSION.strip():
                    continue
                log.info('New version of IVT package {0} found'.format(ivt_package))
                if self.config['debug']:
                    # do not automatically upgrade in debug mode
                    log.info('Will not upgrade IVT in debug mode')
                    continue
                if self.ivt.is_broadcasting():
                    log.info('Is broadcasting, delay IVT upgrade')
                    continue
                log.info('Try to upgrade IVT to version {0}'.format(target_ivt_version))
                self._done_upgrade_evt.clear()
                self.close()
                self._upgrade(ivt_package['url'])
                log.info('Successfully upgrade IVT to version {0}'.format(target_ivt_version))
                self._start_new_ivt()
                return
            except Exception:
                log.exception('Failed to check IVT package version or upgrade IVT')
            finally:
                self._done_upgrade_evt.set()
                gevent.sleep(600)

    def _upgrade(self, url):
        # to make sure subprocess's stdout will be in utf-8 encoding
        environ = dict(os.environ)
        environ['LANG'] = 'en_US.UTF-8'
        # download upgrade script
        sub = Popen(['curl', '-O', url], cwd='/root', stdout=PIPE, stderr=PIPE, env=environ)
        stdout, stderr = sub.communicate()
        if sub.returncode != 0:
            raise Exception(u'Failed to download upgrade script, return code {0}, {1}'.format(sub.returncode, stderr.decode('utf8')))
        script = os.path.basename(urlparse(url).path)
        cmd = ['bash',
               script,
               self.config['ivc'],
               self.config['project'],
               self.config['login_code'],
               self.config['login_passwd'],
               self.config['hardware_model']]
        sub = Popen(cmd, stdout=PIPE, stderr=PIPE, cwd='/root', env=environ)
        try:
            while True:
                with gevent.Timeout(600):
                    line = sub.stdout.readline()
                    if not line:
                        sub.wait()
                        break
                    else:
                        log.info('Upgrade output: '+line.decode('utf8').strip())
        except gevent.Timeout:
            sub.kill()
            raise Exception(u'Failed to upgrade, timeout')
        if sub.returncode != 0:
            raise Exception(u'Failed to upgrade, return code {0}, {1}'.format(sub.returncode, sub.stderr.read()))

    def _start_new_ivt(self):
        Popen('./ivt', close_fds=True, shell=True)
        log.info('New IVT started')