コード例 #1
0
ファイル: quests.py プロジェクト: japonophile/kano-profile
    def mark_completed(self):
        """
            Mark a fulfilled quest complete to claim the reward.
            This will set the state of the quest to COMPLETED in the quest
            store.
            :raises QuestError: If the quest isn't ready to be marked complete.
        """

        if self.is_completed():
            return

        if self.is_fulfilled():
            self._state = self.COMPLETED
            self._save_state()

            run_cmd('kdesk -a profile')

            for reward in self._rewards:
                n = reward.notification
                if n:
                    display_generic_notification(
                        n['title'],
                        n['byline'],
                        n['image'],
                        n['command']
                    )
        else:
            raise QuestError('Quest not ready to be completed.')
コード例 #2
0
def copy_screenshot(filename):
    '''
    Copies screenshot 'filename' into SCREENSHOT_PATH
    '''
    ensure_dir(TMP_DIR)
    if os.path.isfile(filename):
        run_cmd("cp %s %s" % (filename, SCREENSHOT_PATH))
コード例 #3
0
def reload_kernel_module(device_vendor='148f', device_product='5370', module='rt2800usb'):
    '''
    If the Kano USB deviceID is connected to the system, reload the kernel module. Returns True if reloaded.
    Works silently and ok even if the module is not currently loaded in the kernel.
    FIXME: This procedure should be called prior to connect() to circumvent current kernel module random problems.
    '''
    reloaded = False

    # Terminate wpa_supplicant daemon
    run_cmd('wpa_cli terminate')
    time.sleep(0.5)
    logger.info('wpa_cli has been terminated')

    _, _, rc = run_cmd('lsusb -d %s:%s' % (device_vendor, device_product))
    if rc == 0:
        # The device id is matched, reload the kernel driver
        rc_load = 0

        _, _, rc = run_cmd('rmmod "{}"'.format(module))
        time.sleep(0.5)
        rc_load += rc

        _, _, rc = run_cmd('modprobe "{}"'.format(module))
        time.sleep(5)
        rc_load += rc

        logger.info('Reloading wifi dongle kernel module "%s" for deviceID %s:%s rc=%d' %
                    (module, device_vendor, device_product, rc_load))
        if rc_load == 0:
            reloaded = True
    else:
        logger.info('Not reloading kernel module because device not found (%s:%s)' % (device_vendor, device_product))

    return reloaded
コード例 #4
0
def network_info():
    out, _, _ = run_cmd('ip route show')
    network_dict = dict()

    for line in out.splitlines():
        if line.startswith('default'):
            continue

        interface = line.split('dev ')[1].split()[0]

        data = dict()

        if interface.startswith('wlan'):
            command_network = "/sbin/iwconfig wlan0"
            out, _, _ = run_cmd(command_network)

            essid_match = re.match(r'.*ESSID:"(.*)"\ *$', out, re.MULTILINE)
            essid = essid_match.groups()[0] \
                if essid_match else 'Wireless Network'

            data['ESSID'] = essid
            data['nice_name'] = 'Wireless: {}'.format(essid)
        else:
            data['nice_name'] = 'Ethernet'

        data['address'] = line.split('src ')[1].split()[0]

        network_dict[interface] = data

    return network_dict
コード例 #5
0
    def __init__(self, _win):
        self.win = _win

        # Launch pipeline
        if not os.path.exists(OVERSCAN_PIPE):
            run_cmd('mknod {} c 100 0'.format(OVERSCAN_PIPE))

        # Get current overscan
        self.original_overscan = get_overscan_status()
        self.overscan_values = get_overscan_status()

        # Listen for key events
        self.win.connect("key-press-event", self.on_key_press)

        # Create UI
        self.template = Template(
            img_path=os.path.join(MEDIA_DIR, "display_test2.png"),
            title="Use UP and DOWN keys",
            description="Stretch or shrink your screen, until the white " \
                        "lines are lined up with the edges",
            button1_text="CONTINUE",
            orange_button_text="Reset"
        )
        self.template.kano_button.connect("button_release_event",
                                          self.apply_changes)
        self.template.kano_button.connect("key_release_event",
                                          self.apply_changes)
        self.template.orange_button.connect("button_release_event",
                                            self.reset)
        self.win.set_main_widget(self.template)

        self.template.kano_button.grab_focus()

        self.win.show_all()
コード例 #6
0
def is_connected(iface):
    '''
    Returns details on which wireless network we are currently associated.
    The linked variable tells us if Internet is reachable.
    '''
    essid = mode = ap = None
    linked = False

    out, err, _ = run_cmd("iwgetid %s --raw" % iface)
    essid = out.strip()

    out, err, _ = run_cmd("iwgetid %s --raw --ap" % iface)
    ap = out.strip()

    # mode 2 = Managed
    out, err, _ = run_cmd("iwgetid %s --raw --mode" % iface)
    out = out.strip()
    if out == '2':
        mode = 'Managed'
    else:
        mode = out

    # Association status can be queried via ifplugstatus,
    # but we are returning linked=True if Internet is actually up.
    linked = is_internet()

    return (essid, mode, ap, linked)
コード例 #7
0
def get_mem_stats():
    """
    Get information about memory usage
    """
    mem_stats = ''

    out, _, _ = run_cmd('free --human --lohi --total')
    mem_stats += out + '\n'
    out, _, _ = run_cmd('vcgencmd get_mem arm')
    mem_stats += out
    out, _, _ = run_cmd('vcgencmd get_mem gpu')
    mem_stats += out
    out, _, _ = run_cmd('vcgencmd get_mem reloc')
    mem_stats += out
    out, _, _ = run_cmd('vcgencmd get_mem reloc_total')
    mem_stats += out
    out, _, _ = run_cmd('vcgencmd get_mem malloc')
    mem_stats += out
    out, _, _ = run_cmd('vcgencmd get_mem malloc_total')
    mem_stats += out + '\n'
    out, _, _ = run_cmd('vcgencmd mem_reloc_stats')
    mem_stats += out + '\n'
    out, _, _ = run_cmd('cat /proc/meminfo')
    mem_stats += out + '\n'
    out, _, _ = run_cmd('ps -eo pmem,args --no-headers --sort -pmem')
    mem_stats += out

    return mem_stats
コード例 #8
0
ファイル: AppManage.py プロジェクト: carriercomm/kano-apps
def install_app(app, sudo_pwd=None, gui=True):
    pkgs = " ".join(app["packages"] + app["dependencies"])

    cmd = ""
    if gui:
        cmd = "rxvt -title 'Installing {}' -e bash -c ".format(app["title"])

    if sudo_pwd:
        cleanup_cmd = "echo {} | sudo -S dpkg --configure -a".format(sudo_pwd)
        update_cmd = "echo {} | sudo -S apt-get update".format(sudo_pwd)
        run = "echo {} | sudo -S apt-get install -y {}".format(sudo_pwd, pkgs)
    else:
        cleanup_cmd = "sudo dpkg --configure -a".format(sudo_pwd)
        update_cmd = "sudo apt-get update".format(sudo_pwd)
        run = "sudo apt-get install -y {}".format(pkgs)

    if gui:
        run = "'{}'".format(run)
    cmd += run

    # make sure there are no broken packages on the system
    run_cmd(cleanup_cmd)

    run_cmd(update_cmd)
    os.system(cmd)

    done = True
    installed_packages = get_dpkg_dict()[0]
    for pkg in app["packages"] + app["dependencies"]:
        if pkg not in installed_packages:
            done = False
            break

    return done
コード例 #9
0
def set_to_HDMI(HDMI):
    if not hdmi_supported:
        HDMI = False

    # 1 analog
    # 2 hdmi

    # These are the changes we'll apply if they have changed from what they were
    if HDMI:
        amixer_cmd = amixer_set_cmd.format(value=hdmi_value)
        set_config_value("hdmi_ignore_edid_audio", None)
        set_config_value("hdmi_drive", 2)
        config = "HDMI"
    else:
        amixer_cmd = amixer_set_cmd.format(value=analogue_value)
        set_config_value("hdmi_ignore_edid_audio", 1)
        set_config_value("hdmi_drive", None)
        config = "Analogue"

    # Set audio path in amixer
    o, e, rc = run_cmd(amixer_cmd)
    if rc:
        logger.warn("error from amixer: {} {} {}".format(o, e, rc))

    # trigger alsa-utils to store the path in /var/lib/alsa/asound.state
    o, e, rc = run_cmd(store_cmd)
    if rc:
        logger.warn("error from alsa-utils: {} {} {}".format(o, e, rc))

    set_setting('Audio', config)
コード例 #10
0
ファイル: utils.py プロジェクト: alexaverill/make-snake
def print_themes(show_default=True, terminate=True):
    # List of default themes
    default_themes = "{{3Default themes}}: "
    for l in DEFAULT_THEMES:
        default_themes += '{{2' + l + "}} | "
    default_themes = default_themes[:-2]
    # List of custom themes
    custom_themes = "{{3Custom themes}}: "
    theme_list = update_theme_list()
    for l in theme_list:
        # Remove .xml extension
        l = os.path.splitext(l)[0]
        custom_themes += '{{2' + l + "}} | "
    custom_themes = custom_themes[:-2]
    # Print info
    default_themes, _, _ = run_cmd('colour_echo "%s"' % default_themes)
    custom_themes, _, _ = run_cmd('colour_echo "%s"' % custom_themes)
    # Print default themes
    print "\n"
    if show_default:
        print "    " + default_themes.strip('\n')
    # Print custom themes
    print "    " + custom_themes.strip('\n') + '\n'
    if terminate:
        exit(2)
コード例 #11
0
ファイル: network.py プロジェクト: KanoComputing/kano-toolset
def network_info():
    out, _, _ = run_cmd("ip route show")
    network_dict = dict()

    for line in out.splitlines():
        if line.startswith("default"):
            continue

        interface = line.split("dev ")[1].split()[0]

        data = dict()

        if interface.startswith("wlan"):
            command_network = "/sbin/iwconfig wlan0"
            out, _, _ = run_cmd(command_network)

            essid_match = re.match(r'.*ESSID:"(.*)"\ .*', out, re.MULTILINE)
            essid = essid_match.groups()[0] if essid_match else "Wireless Network"

            data["ESSID"] = essid
            data["nice_name"] = "Wireless: {}".format(essid)
        else:
            data["nice_name"] = "Ethernet"

        data["address"] = line.split("src ")[1].split()[0]

        network_dict[interface] = data

    return network_dict
コード例 #12
0
def set_overscan_status(overscan_values):
    top = overscan_values['top']
    bottom = overscan_values['bottom']
    left = overscan_values['left']
    right = overscan_values['right']

    cmd = 'overscan {} {} {} {}'.format(top, bottom, left, right)
    run_cmd(cmd)
コード例 #13
0
ファイル: main.py プロジェクト: KanoComputing/kano-init-flow
 def first_scene(self):
     self._ctl.main_window.hide()
     while Gtk.events_pending():
         Gtk.main_iteration()
     run_cmd('kdesk -w')
     run_cmd('sudo kano-settings first-boot-set-wallpaper')
     self._ctl.main_window.show()
     self.next_stage()
コード例 #14
0
def kill_apps():
    # since kano-updater is run as root, need to inform
    # kanolauncher about user
    user = get_user_unsudoed()
    home = os.path.join('/home/', user)
    variables = 'HOME={} USER={}'.format(home, user)
    run_cmd('{} /usr/bin/kano-launcher /bin/true kano-kill-apps'.format(
        variables))
コード例 #15
0
ファイル: main.py プロジェクト: KanoComputing/kano-init-flow
    def __init__(self):
        # The command below initialises the overscan pipe as root
        # TODO: This would be nice to refactor.
        run_cmd('sudo kano-init-flow-system-tool init-overscan-pipe')

        self._enabled = True
        self._step = 10
        self._original = get_overscan_status()
        self._current = get_overscan_status()
コード例 #16
0
def get_edid():
    file_path = os.path.join(TMP_DIR, 'edid.dat')
    cmd = "tvservice -d {}".format(file_path)
    run_cmd(cmd)
    try:
        dat = read_file_contents(file_path)
        delete_file(file_path)
        return dat
    except:
        return "EMPTY"
コード例 #17
0
ファイル: quests.py プロジェクト: japonophile/kano-profile
    def trigger_event(self, event_name):
        refresh_kdesk = False
        if event_name in self._event_map:
            for q in self._event_map[event_name]:
                not_fulfilled_before = q.state == Quest.ACTIVE
                if not_fulfilled_before == q.is_fulfilled():
                    refresh_kdesk = True

        if refresh_kdesk:
            run_cmd('kdesk -a profile')
コード例 #18
0
ファイル: main.py プロジェクト: KanoComputing/kano-init-flow
 def save_changes(self):
     if self._original != self._current:
         cmd_template = ("sudo kano-init-flow-system-tool write-overscan " +
                         "{} {} {} {}")
         run_cmd(cmd_template.format(
             self._current['top'],
             self._current['left'],
             self._current['right'],
             self._current['bottom'],
         ))
コード例 #19
0
def get_metadata_archive():
    '''
    It creates a file (ARCHIVE_NAME) with all the information
    Returns the file
    '''
    ensure_dir(TMP_DIR)
    file_list = [
        {'name': 'kanux_version.txt', 'contents': get_version()},
        {'name': 'process.txt', 'contents': get_processes()},
        {'name': 'packages.txt', 'contents': get_packages()},
        {'name': 'dmesg.txt', 'contents': get_dmesg()},
        {'name': 'syslog.txt', 'contents': get_syslog()},
        {'name': 'cmdline.txt', 'contents': read_file_contents('/boot/cmdline.txt')},
        {'name': 'config.txt', 'contents': read_file_contents('/boot/config.txt')},
        {'name': 'wifi-info.txt', 'contents': get_wifi_info()},
        {'name': 'usbdevices.txt', 'contents': get_usb_devices()},

        # TODO: Remove raw logs when json ones become stable
        {'name': 'app-logs.txt', 'contents': get_app_logs_raw()},

        {'name': 'app-logs-json.txt', 'contents': get_app_logs_json()},
        {'name': 'hdmi-info.txt', 'contents': get_hdmi_info()},
        {'name': 'xorg-log.txt', 'contents': get_xorg_log()},
        {'name': 'cpu-info.txt', 'contents': get_cpu_info()},
        {'name': 'lsof.txt', 'contents': get_lsof()},
        {'name': 'content-objects.txt', 'contents': get_co_list()}
    ]
    # Include the screenshot if it exists
    if os.path.isfile(SCREENSHOT_PATH):
        file_list.append({
                         'name': SCREENSHOT_NAME,
                         'contents': read_file_contents(SCREENSHOT_PATH)
                         })
    # create files for each non empty metadata info
    for file in file_list:
        if file['contents']:
            write_file_contents(TMP_DIR + file['name'], file['contents'])
    # Collect all coredumps, for applications that terminated unexpectedly
    for f in os.listdir('/var/tmp/'):
        if f.startswith('core-'):
            file_list.append({
                'name': f,
                'contents': read_file_contents(os.path.join('/var/tmp', f))
            })
    # archive all the metadata files
    # need to change dir to avoid tar subdirectories
    current_directory = os.getcwd()
    os.chdir(TMP_DIR)
    run_cmd("tar -zcvf {} *".format(ARCHIVE_NAME))
    # open the file and return it
    archive = open(ARCHIVE_NAME, 'rb')
    # restore the current working directory
    os.chdir(current_directory)

    return archive
コード例 #20
0
ファイル: proxy.py プロジェクト: KanoComputing/kano-settings
def set_chromium(enable, host=None, port=None):
    if enable:
        proxy_type = 'http'

        strflags = '"--password-store=detect --proxy-server="{}:\/\/{}:{}""'.format(proxy_type, host, port)
    else:
        strflags = '"--password-store=detect"'

    cmd = "/bin/sed -i 's/CHROMIUM_FLAGS=.*/CHROMIUM_FLAGS={}/g' {}".format(strflags, chromium_cfg)
    run_cmd(cmd)
    return
コード例 #21
0
def get_dmesg():
    '''
    Returns a string with dmesg and uptime info
    '''
    cmd_dmesg = "dmesg"
    cmd_uptime = "uptime"
    d, _, _ = run_cmd(cmd_dmesg)
    t, _, _ = run_cmd(cmd_uptime)
    t = 'system uptime: %s' % t

    return '%s\n%s' % (d, t)
コード例 #22
0
def try_connect():
    '''
    Returns internet status.
    If connection fails the first time, the WiFi config will be launched
    '''
    if is_internet():
        return True

    run_cmd('sudo /usr/bin/kano-settings 12', localised=True)

    return is_internet()
コード例 #23
0
ファイル: locale.py プロジェクト: KanoComputing/kano-settings
def install_locale(locale):
    locale = ensure_utf_locale(locale)

    if not is_locale_valid(locale):
        print 'locale not valid', locale
        return False

    enforce_root(_('You need to be root to change install a locale'))

    genfile_locale = standard_locale_to_genfile_entry(locale)
    sed(r'^# ({})'.format(genfile_locale), r'\1', LOCALE_GEN_FILE)
    run_cmd('locale-gen')
コード例 #24
0
def get_hdmi_info():
    '''
    Returns a string with Display info
    '''
    # Current resolution
    cmd = "tvservice -s"
    o, _, _ = run_cmd(cmd)
    res = 'Current resolution: {}\n\n'.format(o)
    # edid file
    file_path = os.path.join(TMP_DIR, 'edid.dat')
    cmd = "tvservice -d {} && edidparser {}".format(file_path, file_path)
    edid, _, _ = run_cmd(cmd)
    delete_file(file_path)

    return res + edid
コード例 #25
0
ファイル: apps.py プロジェクト: KanoComputing/kano-profile
def launch_project(app, filename, data_dir, background=False):
    # This is necessary to support the new official names
    # TODO: once the apps have been renamed this will not be necessary
    name_translation = {
        'make-art': 'kano-draw',
        'terminal-quest': 'linux-story'
    }

    app_tr = name_translation.get(app, app)

    logger.info("launch_project: {} {} {}".format(app_tr, filename, data_dir))

    app_profiles = read_json(app_profiles_file)

    # XML file with complete pathname
    fullpath = os.path.join(data_dir, filename)

    # Prepare the command line to open the app with the new project
    try:
        cmd = (app_profiles[app_tr]['cmd']
               .format(fullpath=fullpath, filename=filename))
    except KeyError as exc:
        logger.warn(
            "Can't find app '{}' in the app profiles - [{}]"
            .format(app_tr, exc)
        )
        raise ValueError(_("App '{}' not available").format(app_tr))

    # Try to load the project if the app is already running, via a signal.
    _, _, rc = run_cmd('/usr/bin/kano-signal launch-share {}'.format(fullpath))
    if rc:
        # Likely the app is not running and the signal could not be sent, so start it now
        logger.warn("Error sending launch signal, starting the app now, rc={}".format(rc))
        if background:
            # TODO: After migrating to launching apps via systemd, shares for make-snake
            # stopped launching from KW. Created a special case here to avoid
            # fixing the make-snake cmd through systemd temporarily. FIX THIS.
            if app == 'make-snake':
                run_bg(cmd)
            else:
                run_cmd('systemd-run --user {cmd}'.format(cmd=cmd))
        else:
            _, _, rc = run_print_output_error(cmd)
            return rc
    else:
        logger.info("Sent signal to app: {} to open : {}".format(app_tr, fullpath))

    return 0
コード例 #26
0
def get_status():
    status = dict()

    status_str, _, _ = run_cmd(tvservice_path + ' -s')
    if 'DMT' in status_str:
        status['group'] = 'DMT'
    elif 'CEA' in status_str:
        status['group'] = 'CEA'
    else:
        logger.error('status parsing error')
        return

    status['mode'] = int(status_str.split('(')[1].split(')')[0].strip())
    status['full_range'] = 'RGB full' in status_str

    status['overscan'] = not (
        get_config_value('disable_overscan') == 1 and
        get_config_value('overscan_top') == 0 and
        get_config_value('overscan_bottom') == 0 and
        get_config_value('overscan_left') == 0 and
        get_config_value('overscan_right') == 0
    )

    res, hz = status_str.split(',')[1].split('@')
    status['resolution'] = res.strip()
    status['hz'] = float(hz.strip()[:-2])

    return status
コード例 #27
0
    def restore_lxpanel_configuration(self):
        userid = os.getuid()
        groupid = os.getgid()
        original_lxpanel_path = '/etc/skel/.config/lxpanel/'
        user_lxpanel_path = os.path.join('/home/' + os.getenv('SUDO_USER'), '.config/lxpanel')

        # remove the current local copy
        shutil.rmtree(user_lxpanel_path, ignore_errors=True)

        # re-create the copy from the skeleton
        shutil.copytree(original_lxpanel_path, user_lxpanel_path, symlinks=False, ignore=None)
        for root, dirs, files in os.walk(user_lxpanel_path):
            for name in files:
                os.chown(os.path.join(root, name), userid, groupid)

        run_cmd('lxpanelctl restart')
コード例 #28
0
def take_screenshot():
    '''
    Takes a screenshot and saves it into SCREENSHOT_PATH
    '''
    ensure_dir(TMP_DIR)
    cmd = "kano-screenshot -w 1024 -p " + SCREENSHOT_PATH
    _, _, rc = run_cmd(cmd)
コード例 #29
0
        def getRawData(interface, iwlist=None):
            '''
            Runs iwlist and gets WiFi data in a string
            Developped, tested with Wireless Extension v29 English translation, Nov 2007
            If iwlist points to a file, you can mimic iwlist from a response file for testing
            '''

            # Make sure the wlan interface is up, otherwise the network scan will not proceed
            run_cmd('ifconfig %s up' % interface)
            if iwlist:
                outdata = open(iwlist, 'r').read()
            else:
                # Contemplate those seldom cases where the dongle driver returns an empty list
                cstring = "iwlist " + interface + " scan"
                outdata, _, _ = run_cmd(cstring)

            return outdata
コード例 #30
0
def get_networks_info():
    '''
    Returns a string with ifconfig info
    '''
    cmd = "/sbin/ifconfig"
    o, _, _ = run_cmd(cmd)

    return o
コード例 #31
0
def do_final_stage(flow_params):
    init_status = Status.get_instance()

    clear_screen()

    reconfigure_autostart_policy()

    # Force autologin for this user until he goes through the graphic
    # init flow. At the end of it, kano-uixinit should call kano-init
    # to finalise the process and switch the kit to multiuser.
    set_ldm_autologin(init_status.username)

    init_status.stage = Status.UI_INIT_STAGE
    init_status.save()

    # Start Lightdm with a splash screen if available,
    # Or do it the classy way otherwise (soft dependency).
    if os.path.isfile('/usr/bin/kano-dashboard-lightdm'):
        run_cmd('/usr/bin/kano-dashboard-lightdm')
    else:
        start_lightdm()
コード例 #32
0
def read_edid():
    edid_dat_path = '/tmp/edid.dat'

    delete_file(edid_dat_path)
    edid_txt, _, rc = run_cmd('{0} -d {1} && edidparser {1}'.format(
        tvservice_path, edid_dat_path))
    edid_txt = edid_txt.splitlines()
    if rc != 0:
        logger.error("error getting edid dat")
        return
    delete_file(edid_dat_path)
    return edid_txt
コード例 #33
0
ファイル: audio.py プロジェクト: brandonjackson/kano-settings
def set_to_HDMI(HDMI, force=False):
    '''
    Set audio output to HDMI if supported by the display,
    otherwise set it to Analogue output.

    Returns 'HDMI' or 'Analogue', whichever was applied.
    '''

    if not is_hdmi_audio_supported() and not force:
        HDMI = False

    # 1 analog
    # 2 hdmi

    # These are the changes we'll apply if they have changed from what they were
    if HDMI:
        amixer_cmd = hdmi_cmd
        set_config_value('hdmi_ignore_edid_audio', None)
        set_config_value('hdmi_drive', 2)
        config = _("HDMI")
    else:
        amixer_cmd = analogue_cmd
        set_config_value('hdmi_ignore_edid_audio', 1)
        set_config_value('hdmi_drive', None)
        config = _("Analogue")

    end_config_transaction()

    # Set audio path in amixer
    o, e, rc = run_cmd(amixer_cmd)
    if rc:
        logger.warn("error from amixer: {} {} {}".format(o, e, rc))

    # trigger alsa-store to store the path in /var/lib/alsa/asound.state
    o, e, rc = run_cmd(store_cmd)
    if rc:
        logger.warn("error from alsa-store: {} {} {}".format(o, e, rc))

    set_setting('Audio', config)
    return config
コード例 #34
0
ファイル: youtube.py プロジェクト: isabella232/kano-video
def get_video_file_url(video_url):
    try:
        logger.info('Starting youtube-dl with url: %s ' % video_url)

        cmd_youtube = 'youtube-dl -g "{}" {}'.format(video_url, proxy_arg)

        output, error, rc = run_cmd(cmd_youtube)
        logger.info('youtube-dl returns with rc=%d' % rc)
        output = output.strip('\n')
        assert (rc == 0)
        return True, output
    except:
        return False, error