Esempio n. 1
0
File: model.py Progetto: mayasd/WAPT
def update_installed_packages(uuid, installed_packages):
    """Stores packages json data into separate HostPackagesStatus

    Args:
        uuid (str) : unique ID of host
        installed_packages (list): data from host
    Returns:

    """
    # TODO : be smarter : insert / update / delete instead of delete all / insert all ?
    # is it faster ?
    key = ['package','version','version','architecture','locale','maturity']
    def get_key(rec):
        return {k:rec[k] for k in rec}
    #old_installed = HostPackagesStatus.select().where(HostPackagesStatus.host == uuid).dicts()

    def encode_value(value):
        if isinstance(value,unicode):
            value = value.replace(u'\x00', ' ')
        return value

    HostPackagesStatus.delete().where(HostPackagesStatus.host == uuid).execute()
    packages = []
    for package in installed_packages:
        package['host'] = uuid
        # csv str on the client, Array on the server
        package['depends'] = ensure_list(package['depends'])
        package['conflicts'] = ensure_list(package['conflicts'])

        # filter out all unknown fields from json data for the SQL insert
        packages.append(dict([(k, encode_value(v)) for k, v in package.iteritems() if k in HostPackagesStatus._meta.fields]))
    if packages:
        return HostPackagesStatus.insert_many(packages).execute() # pylint: disable=no-value-for-parameter
    else:
        return True
Esempio n. 2
0
def remove_from_csv_list(csv_list,new_items):
    """Remove items from csv_list"""
    items = ensure_list(csv_list)
    for item in new_items:
        if item in items:
            items.remove(item)
    return ','.join(items)
Esempio n. 3
0
def add_to_csv_list(csv_list,new_items):
    """Add items to csv_list"""
    items = ensure_list(csv_list)
    for item in new_items:
        if not item in items:
            items.append(item)
    return ','.join(items)
Esempio n. 4
0
def add_to_csv_list(csv_list, new_items):
    """Add items to csv_list"""
    items = ensure_list(csv_list)
    for item in new_items:
        if not item in items:
            items.append(item)
    return ','.join(items)
Esempio n. 5
0
def remove_from_csv_list(csv_list, new_items):
    """Remove items from csv_list"""
    items = ensure_list(csv_list)
    for item in new_items:
        if item in items:
            items.remove(item)
    return ','.join(items)
Esempio n. 6
0
def build_waptupgrade_package(waptconfigfile,
                              target_directory=None,
                              wapt_server_user=None,
                              wapt_server_passwd=None,
                              key_password=None,
                              sign_digests=None):
    if target_directory is None:
        target_directory = tempfile.gettempdir()

    if not wapt_server_user:
        wapt_server_user = raw_input('WAPT Server user :'******'WAPT Server password :'******'ascii')

    wapt = common.Wapt(config_filename=waptconfigfile,
                       disable_update_server_status=True)
    wapt.dbpath = r':memory:'
    wapt.use_hostpackages = False

    if sign_digests is None:
        sign_digests = wapt.sign_digests

    if not wapt.personal_certificate_path or not os.path.isfile(
            wapt.personal_certificate_path):
        raise Exception(
            u'No personal certificate provided or not found (%s) for signing waptupgrade package'
            % wapt.personal_certificate_path)

    waptget = get_file_properties('wapt-get.exe')
    entry = PackageEntry(waptfile=makepath(wapt.wapt_base_dir, 'waptupgrade'))
    patchs_dir = makepath(entry.sourcespath, 'patchs')
    mkdirs(patchs_dir)
    filecopyto(makepath(wapt.wapt_base_dir, 'waptdeploy.exe'),
               makepath(patchs_dir, 'waptdeploy.exe'))

    entry.package = '%s-waptupgrade' % wapt.config.get(
        'global', 'default_package_prefix')
    rev = entry.version.split('-')[1]
    entry.version = '%s-%s' % (waptget['FileVersion'], rev)
    entry.inc_build()
    entry.save_control_to_wapt()
    entry.build_package(target_directory=target_directory)
    certs = wapt.personal_certificate()
    key = wapt.private_key(private_key_password=key_password)
    if not certs[0].is_code_signing:
        raise Exception(u'%s is not a code signing certificate' %
                        wapt.personal_certificate_path)
    entry.sign_package(private_key=key,
                       certificate=certs,
                       private_key_password=key_password,
                       mds=ensure_list(sign_digests))

    wapt.http_upload_package(entry.localpath,
                             wapt_server_user=wapt_server_user,
                             wapt_server_passwd=wapt_server_passwd)
    return entry.as_dict()
Esempio n. 7
0
def get_packages_filenames(packages,
                           with_depends=True,
                           waptconfigfile=None,
                           repo_name='wapt-templates',
                           remoterepo=None):
    """Returns list of package filenames (latest version) and md5 matching comma separated list of packages names and their dependencies
    helps to batch download a list of selected packages using tools like curl or wget

    Args:
        packages (list): list of package entries as dicts or PackageEntry
        with_depends (bool): get recursively the all depends filenames
        waptconfigfile (str): path to wapt ini file
        repo_name : section name in wapt ini file for repo parameters (repo_url, http_proxy, timeout, verify_cert)
        remoterepo (WaptRemoteRepo) : remote repo to query.
                                      Mutually exclusive with waptconfigfile and repo_name
    Returns:
        list: list of (wapt file basename,md5)

    >>> get_packages_filenames(r"c:\users\htouvet\AppData\Local\waptconsole\waptconsole.ini","tis-firefox-esr,tis-flash,tis-wapttest")
    [u'tis-firefox-esr_24.4.0-0_all.wapt', u'tis-flash_12.0.0.77-3_all.wapt', u'tis-wapttest.wapt', u'tis-wapttestsub_0.1.0-1_all.wapt', u'tis-7zip_9.2.0-15_all.wapt']
    """
    result = []
    defaults = {
        'repo_url': 'https://store.wapt.fr/wapt',
        'http_proxy': '',
        'verify_cert': '0',
    }

    if remoterepo is None:
        config = RawConfigParser(defaults=defaults)
        config.read(waptconfigfile)

        remoterepo = WaptRemoteRepo(name=repo_name, config=config)
        remoterepo.update()

    for pe in packages:
        if not isinstance(pe, PackageEntry):
            pe = PackageEntry(**pe)

        result.append((
            pe.filename,
            pe.md5sum,
        ))
        if with_depends and pe.depends:
            depends_list = []
            for depname in ensure_list(pe.depends):
                pe_dep = remoterepo.packages_matching(depname)
                if pe_dep:
                    depends_list.append(pe_dep[-1])
            for (fn, md5) in get_packages_filenames(depends_list,
                                                    remoterepo=remoterepo):
                if not fn in result:
                    result.append((
                        fn,
                        md5,
                    ))
    return result
Esempio n. 8
0
def proxy_host_request(request, action):
    """Proxy a waptconsole action to wapt clients using websockets

    Args:
        uuid: can be a list or a single uuid
        notify_user: 0/1
        notify_server: 0/1

    Returns:
        dict:
            'result':
                'success' (list)
                'errors' (list)
            'msg' (str)
            'success'(bool)
            'request_time' (float)
            'error_code'
    """
    try:
        start_time = time.time()
        all_args = {k: v for k, v in request.args.iteritems()}
        if request.json:
            all_args.update(request.json)

        uuids = ensure_list(all_args['uuid'])
        del(all_args['uuid'])
        timeout = float(request.args.get('timeout', app.conf.get('clients_read_timeout', 5)))

        result = dict(success=[], errors=[])
        tasks = []
        for uuid in uuids:
            try:
                host_data = Hosts\
                    .select(Hosts.uuid, Hosts.computer_fqdn,
                            Hosts.server_uuid,
                            Hosts.listening_address,
                            Hosts.listening_port,
                            Hosts.listening_protocol,
                            Hosts.listening_timestamp,
                            )\
                    .where((Hosts.server_uuid == get_server_uuid()) & (Hosts.uuid == uuid) & (~Hosts.listening_address.is_null()) & (Hosts.listening_protocol == 'websockets'))\
                    .dicts()\
                    .first(1)

                if host_data and host_data.get('listening_address', None):
                    msg = u''
                    logger.info(
                        'Launching %s with args %s for %s at address %s...' %
                        (action, all_args, uuid, host_data['listening_address']))

                    args = dict(all_args)
                    sid = host_data['listening_address']
                    computer_fqdn = host_data['computer_fqdn']

                    def emit_action(sid, uuid, action, action_args, computer_fqdn, timeout=5):
                        try:
                            got_result = []

                            def result_callback(data):
                                got_result.append(data)

                            logger.debug(u'Emit %s to %s (%s)' % (action, uuid, computer_fqdn))
                            socketio.emit(action, action_args, room=sid, callback=result_callback)
                            # wait for asynchronous answer...
                            wait_loop = timeout * 20
                            while not got_result:
                                wait_loop -= 1
                                if wait_loop < 0:
                                    raise EWaptTimeoutWaitingForResult(u'Timeout, client did not send result within %s s' % timeout)
                                socketio.sleep(0.05)

                            # action succedded
                            result['success'].append(
                                dict(
                                    uuid=uuid,
                                    msg=msg,
                                    computer_fqdn=computer_fqdn,
                                    result=got_result[0],
                                ))
                        except Exception as e:
                            result['errors'].append(
                                dict(
                                    uuid=uuid,
                                    msg='%s' % repr(e),
                                    computer_fqdn='',
                                ))
                    if sid:
                        tasks.append(socketio.start_background_task(
                            emit_action, sid=sid, uuid=uuid, action=action, action_args=args, computer_fqdn=computer_fqdn))

                else:
                    result['errors'].append(
                        dict(
                            uuid=uuid,
                            msg=u'Host %s is not registered or not connected wia websockets' % uuid,
                            computer_fqdn='',
                        ))
            except Exception as e:
                result['errors'].append(
                    dict(
                        uuid=uuid,
                        msg=u'Host %s error %s' % (uuid, repr(e)),
                        computer_fqdn='',
                    ))

        # wait for all background tasks to terminate or timeout...
        # assume the timeout should be longer if more hosts to perform
        wait_loop = timeout * len(tasks)
        while True:
            running = [t for t in tasks if t.is_alive()]
            if not running:
                break
            wait_loop -= 1
            if wait_loop < 0:
                break
            socketio.sleep(0.05)

        msg = ['Success : %s, Errors: %s' % (len(result['success']), len(result['errors']))]
        if result['errors']:
            msg.extend(['%s: %s' % (e['computer_fqdn'], e['msg'])
                        for e in result['errors']])

        return make_response(result,
                             msg='\n- '.join(msg),
                             success=len(result['success']) > 0,
                             request_time=time.time() - start_time)
    except Exception as e:
        return make_response_from_exception(e)
Esempio n. 9
0
def get_packages_filenames(packages,with_depends=True,waptconfigfile=None,repo_name='wapt-templates',remoterepo=None,package_request=None):
    """Returns list of package filenames (latest version) and md5 matching comma separated list of packages names and their dependencies
    helps to batch download a list of selected packages using tools like curl or wget

    Args:
        packages (list): list of package entries as dicts or PackageEntry
        with_depends (bool): get recursively the all depends filenames
        waptconfigfile (str): path to wapt ini file
        repo_name : section name in wapt ini file for repo parameters (repo_url, http_proxy, timeout, verify_cert)
        remoterepo (WaptRemoteRepo) : remote repo to query.
                                      Mutually exclusive with waptconfigfile and repo_name
    Returns:
        list: list of (wapt file basename,md5)

    >>> get_packages_filenames(r"c:\users\htouvet\AppData\Local\waptconsole\waptconsole.ini","tis-firefox-esr,tis-flash,tis-wapttest")
    [u'tis-firefox-esr_24.4.0-0_all.wapt', u'tis-flash_12.0.0.77-3_all.wapt', u'tis-wapttest.wapt', u'tis-wapttestsub_0.1.0-1_all.wapt', u'tis-7zip_9.2.0-15_all.wapt']
    """
    result = []
    defaults = {
        'repo_url':'https://store.wapt.fr/wapt',
        'http_proxy':'',
        'verify_cert':'0',
        }

    if remoterepo is None:
        config = RawConfigParser(defaults=defaults)
        config.read(waptconfigfile)

        remoterepo = WaptRemoteRepo(name=repo_name,config=config)
        remoterepo.update()

    if package_request is not None and isinstance(package_request,dict):
        package_request = PackageRequest(**package_request)

    for pe in packages:
        if not isinstance(pe,PackageEntry):
            pe = PackageEntry(**pe)

        # propagate capa to parent package
        if package_request is None:
            request_filter = PackageRequest()
            if pe.locale != 'all' and pe.locale:
                request_filter.locales = [pe.locale]
            if pe.architecture != 'all' and pe.architecture:
                request_filter.architectures = [pe.architecture]
            if pe.min_os_version:
                request_filter.min_os_version = pe.min_os_version
            if pe.max_os_version:
                request_filter.max_os_version = pe.max_os_version
        else:
            request_filter = package_request

        result.append((pe.filename,pe.md5sum,))
        if with_depends and pe.depends:
            depends_list = []
            for depname in ensure_list(pe.depends):
                request_filter.request = depname
                pe_dep = remoterepo.packages_matching(request_filter)
                if pe_dep:
                    depends_list.append(pe_dep[-1])
            for (fn,md5) in get_packages_filenames(depends_list,remoterepo = remoterepo):
                if not fn in result:
                    result.append((fn,md5,))
    return result
Esempio n. 10
0
def build_waptupgrade_package(wapt,
                              mainrepo,
                              sources_directory=None,
                              target_directory=None,
                              wapt_server_user=None,
                              wapt_server_passwd=None,
                              key_password=None,
                              sign_digests=None,
                              priority='critical'):
    if target_directory is None:
        target_directory = tempfile.gettempdir()

    if not wapt_server_user:
        wapt_server_user = raw_input('WAPT Server user :'******'WAPT Server password :'******'ascii')

    if sign_digests is None:
        sign_digests = wapt.sign_digests

    if not wapt.personal_certificate_path or not os.path.isfile(
            wapt.personal_certificate_path):
        raise Exception(
            u'No personal certificate provided or not found (%s) for signing waptupgrade package'
            % wapt.personal_certificate_path)

    waptget = get_file_properties('wapt-get.exe')
    if sources_directory is None:
        sources_directory = makepath(wapt.wapt_base_dir, 'waptupgrade')
    entry = PackageEntry(waptfile=sources_directory)
    patchs_dir = makepath(entry.sourcespath, 'patchs')
    mkdirs(patchs_dir)
    filecopyto(makepath(wapt.wapt_base_dir, 'waptdeploy.exe'),
               makepath(patchs_dir, 'waptdeploy.exe'))
    mainrepo.update()
    entry.package = '%s-waptupgrade' % wapt.config.get(
        'global', 'default_package_prefix')
    existing = mainrepo.packages_matching(PackageRequest(entry.package))
    if existing:
        rev = sorted(existing)[-1].version.split('-')[1]
    else:
        rev = entry.version.split('-')[1]
    entry.version = '%s-%s' % (waptget['FileVersion'], rev)
    entry.inc_build()
    entry.priority = priority
    entry.save_control_to_wapt()
    entry.build_package(target_directory=target_directory)
    certs = wapt.personal_certificate()
    key = wapt.private_key(private_key_password=key_password)
    if not certs[0].is_code_signing:
        raise Exception(u'%s is not a code signing certificate' %
                        wapt.personal_certificate_path)
    entry.sign_package(private_key=key,
                       certificate=certs,
                       private_key_password=key_password,
                       mds=ensure_list(sign_digests))

    wapt.http_upload_package(entry.localpath,
                             wapt_server_user=wapt_server_user,
                             wapt_server_passwd=wapt_server_passwd,
                             progress_hook=wapt.progress_hook)
    mainrepo.update()
    return entry.as_dict()
Esempio n. 11
0
def duplicate_from_file(package_filename,
                        new_prefix='test',
                        target_directory=None,
                        authorized_certs=None,
                        set_maturity=None):
    r"""Duplicate a downloaded package to match prefix defined in waptconfigfile
    renames all dependencies

    Returns:
        str: source directory

    >>> from common import Wapt
    >>> wapt = Wapt(config_filename = r'C:\Users\htouvet\AppData\Local\waptconsole\waptconsole.ini')
    >>> sources = duplicate_from_external_repo(wapt.config_filename,r'C:\tranquilit\wapt\tests\packages\tis-wapttest.wapt')
    >>> res = wapt.build_upload(sources,wapt_server_user='******',wapt_server_passwd='password')
    >>> res[0]['package'].depends
    u'test-wapttestsub,test-7zip'
    """
    def rename_package(oldname, prefix):
        sp = oldname.split('-', 1)
        if len(sp) == 2:
            return "%s-%s" % (prefix, sp[-1])
        else:
            return oldname

    source_package = PackageEntry(waptfile=package_filename)
    # authorized_certs is a directoyr instead a list of certificates.
    if authorized_certs is not None and authorized_certs != '' and not isinstance(
            authorized_certs, list):
        bundle = SSLCABundle()
        bundle.add_pems(makepath(authorized_certs, '*.crt'), trust_first=True)
        bundle.add_pems(makepath(authorized_certs, '*.cer'), trust_first=True)
        bundle.add_pems(makepath(authorized_certs, '*.pem'), trust_all=True)
    else:
        bundle = authorized_certs or None

    source_package.unzip_package(target_dir=target_directory, cabundle=bundle)
    source_package.invalidate_signature()

    package = PackageEntry(waptfile=source_package.sourcespath)
    oldname = source_package.package
    package.package = rename_package(oldname, new_prefix)
    package.inc_build()
    if set_maturity is not None:
        package.maturity = set_maturity

    result = package['sourcespath']

    # renames dependencies
    if package.depends:
        newdepends = []
        depends = ensure_list(package.depends)
        for dependname in depends:
            newname = rename_package(dependname, new_prefix)
            newdepends.append(newname)

        package.depends = ','.join(newdepends)

    # renames conflicts
    if package.conflicts:
        newconflicts = []
        conflicts = ensure_list(package.conflicts)
        for dependname in conflicts:
            newname = rename_package(dependname, new_prefix)
            newconflicts.append(newname)

        package.conflicts = ','.join(newconflicts)

    package.save_control_to_wapt()
    return result
Esempio n. 12
0
def get_packages_filenames(packages,
                           with_depends=True,
                           waptconfigfile=None,
                           repo_name='wapt-templates',
                           remoterepo=None,
                           package_request=None,
                           privaterepo=None,
                           local_prefix=None):
    """Returns list of package filenames (latest version) and md5 matching comma separated list of packages names and their dependencies
    helps to batch download a list of selected packages using tools like curl or wget

    Args:
        packages (list): list of package entries as dicts or PackageEntry
        with_depends (bool): get recursively the all depends filenames
        waptconfigfile (str): path to wapt ini file
        repo_name : section name in wapt ini file for repo parameters (repo_url, http_proxy, timeout, verify_cert)
        remoterepo (WaptRemoteRepo) : remote repo to query.
                                      Mutually exclusive with waptconfigfile and repo_name
        privaterepo (WaptRemoteRepo) : local private repo where to check if dependencies already exists
    Returns:
        list: list of (wapt file basename,md5)

    >>> get_packages_filenames(r"c:\users\htouvet\AppData\Local\waptconsole\waptconsole.ini","tis-firefox-esr,tis-flash,tis-wapttest")
    [u'tis-firefox-esr_24.4.0-0_all.wapt', u'tis-flash_12.0.0.77-3_all.wapt', u'tis-wapttest.wapt', u'tis-wapttestsub_0.1.0-1_all.wapt', u'tis-7zip_9.2.0-15_all.wapt']
    """
    result = []
    defaults = {
        'repo_url': 'https://store.wapt.fr/wapt',
        'http_proxy': '',
        'verify_cert': '0',
    }

    try:
        import waptconsole
        progress_hook = waptconsole.UpdateProgress
        private_key_password_callback = waptconsole.GetPrivateKeyPassword
    except ImportError as e:

        def print_progress(show=False, n=0, max=100, msg=''):
            if show:
                print('%s %s/%s\r' % (msg, n, max), end='')
            else:
                if not msg:
                    msg = 'Done'
                print("%s%s" % (msg, ' ' * (80 - len(msg))))

        progress_hook = print_progress
        private_key_password_callback = None

    if remoterepo is None:
        config = RawConfigParser(defaults=defaults)
        config.read(waptconfigfile)

        remoterepo = WaptRemoteRepo(name=repo_name, config=config)
        remoterepo.private_key_password_callback = private_key_password_callback
        remoterepo.update()

    if privaterepo is None and waptconfigfile:
        config = RawConfigParser(defaults=defaults)
        config.read(waptconfigfile)

        privaterepo = WaptRemoteRepo(name='wapt', config=config)
        privaterepo.private_key_password_callback = private_key_password_callback
        privaterepo.update()

    if package_request is not None and isinstance(package_request, dict):
        package_request = PackageRequest(**package_request)

    for pe in packages:
        if not isinstance(pe, PackageEntry):
            pe = PackageEntry(**pe)

        # propagate capa to parent package
        if package_request is None:
            request_filter = PackageRequest()
            if pe.locale != 'all' and pe.locale:
                request_filter.locales = [pe.locale]
            if pe.architecture != 'all' and pe.architecture:
                request_filter.architectures = [pe.architecture]
            if pe.min_os_version:
                request_filter.min_os_version = pe.min_os_version
            if pe.max_os_version:
                request_filter.max_os_version = pe.max_os_version
        else:
            request_filter = package_request

        if pe.filename:
            result.append((
                pe.filename,
                pe.md5sum,
            ))
            if with_depends and pe.depends:
                depends_list = []
                for depname in ensure_list(pe.depends):
                    request_filter.request = depname
                    pe_dep = remoterepo.packages_matching(request_filter)

                    if privaterepo and local_prefix:
                        request_filter.request = change_prefix(
                            depname, local_prefix)
                        pe_local = privaterepo.packages_matching(
                            request_filter)
                    else:
                        pe_local = None

                    if pe_dep and not pe_local:
                        depends_list.append(pe_dep[-1])

                for (fn, md5) in get_packages_filenames(depends_list,
                                                        remoterepo=remoterepo):
                    if not (fn, md5) in result:
                        result.append((
                            fn,
                            md5,
                        ))
    return result
Esempio n. 13
0
def unzip(zipfn, target=None, filenames=None):
    """Unzip the files from zipfile with patterns in filenames to target directory

    Args:
        zipfn (str) : path to zipfile. (can be relative to temporary unzip location of package)
        target (str) : target location. Defaults to dirname(zipfile) + basename(zipfile)
        filenames (str or list of str): list of filenames / glob patterns (path sep is normally a slash)

    Returns:
        list : list of extracted files

    >>> unzip(r'C:\tranquilit\wapt\tests\packages\tis-7zip_9.2.0-15_all.wapt')
    [u'C:\\tranquilit\\wapt\\tests\\packages\\tis-7zip_9.2.0-15_all\\7z920-x64.msi',
     u'C:\\tranquilit\\wapt\\tests\\packages\\tis-7zip_9.2.0-15_all\\7z920.msi',
     u'C:\\tranquilit\\wapt\\tests\\packages\\tis-7zip_9.2.0-15_all\\setup.py',
     u'C:\\tranquilit\\wapt\\tests\\packages\\tis-7zip_9.2.0-15_all\\WAPT/control',
     u'C:\\tranquilit\\wapt\\tests\\packages\\tis-7zip_9.2.0-15_all\\WAPT/wapt.psproj',
     u'C:\\tranquilit\\wapt\\tests\\packages\\tis-7zip_9.2.0-15_all\\WAPT/manifest.sha256',
     u'C:\\tranquilit\\wapt\\tests\\packages\\tis-7zip_9.2.0-15_all\\WAPT/signature']

    >>> unzip(r'C:\tranquilit\wapt\tests\packages\tis-7zip_9.2.0-15_all.wapt',filenames=['*.msi','*.py'])
    [u'C:\\tranquilit\\wapt\\tests\\packages\\tis-7zip_9.2.0-15_all\\7z920-x64.msi',
     u'C:\\tranquilit\\wapt\\tests\\packages\\tis-7zip_9.2.0-15_all\\7z920.msi',
     u'C:\\tranquilit\\wapt\\tests\\packages\\tis-7zip_9.2.0-15_all\\setup.py']

    >>> unzip(r'C:\tranquilit\wapt\tests\packages\tis-7zip_9.2.0-15_all.wapt',filenames='WAPT/*')
    [u'C:\\tranquilit\\wapt\\tests\\packages\\tis-7zip_9.2.0-15_all\\WAPT/control',
     u'C:\\tranquilit\\wapt\\tests\\packages\\tis-7zip_9.2.0-15_all\\WAPT/wapt.psproj',
     u'C:\\tranquilit\\wapt\\tests\\packages\\tis-7zip_9.2.0-15_all\\WAPT/manifest.sha256',
     u'C:\\tranquilit\\wapt\\tests\\packages\\tis-7zip_9.2.0-15_all\\WAPT/signature']

    >>> unzip(r'C:\tranquilit\wapt\tests\packages\tis-7zip_9.2.0-15_all.wapt',filenames='WAPT/control')
    [u'C:\\tranquilit\\wapt\\tests\\packages\\tis-7zip_9.2.0-15_all\\WAPT\\control']

    .. versionadded:: 1.3.11

    """
    zipf = ZipFile(zipfn, allowZip64=True)
    if target is None:
        target = makepath(os.path.dirname(os.path.abspath(zipfn)),
                          os.path.splitext(os.path.basename(zipfn))[0])

    if filenames is not None:
        filenames = [
            pattern.replace('\\', '/') for pattern in ensure_list(filenames)
        ]

    def match(fn, filenames):
        # return True if fn matches one of the pattern in filenames
        if filenames is None:
            return True
        else:
            for pattern in filenames:
                if glob.fnmatch.fnmatch(fn, pattern):
                    return True
            return False

    if filenames is not None:
        files = [fn for fn in zipf.namelist() if match(fn, filenames)]
        zipf.extractall(target, members=files)
    else:
        files = zipf.namelist()
        zipf.extractall(target)

    return [makepath(target, fn.replace('/', os.sep)) for fn in files]
Esempio n. 14
0
def duplicate_from_file(package_filename,new_prefix='test',target_directory=None,authorized_certs=None,set_maturity=None):
    r"""Duplicate a downloaded package to match prefix defined in waptconfigfile
    renames all dependencies

    Returns:
        str: source directory

    >>> from common import Wapt
    >>> wapt = Wapt(config_filename = r'C:\Users\htouvet\AppData\Local\waptconsole\waptconsole.ini')
    >>> sources = duplicate_from_external_repo(wapt.config_filename,r'C:\tranquilit\wapt\tests\packages\tis-wapttest.wapt')
    >>> res = wapt.build_upload(sources,wapt_server_user='******',wapt_server_passwd='password')
    >>> res[0]['package'].depends
    u'test-wapttestsub,test-7zip'
    """
    def rename_package(oldname,prefix):
        sp = oldname.split('-',1)
        if len(sp) == 2:
            return "%s-%s" % (prefix,sp[-1])
        else:
            return oldname

    source_package = PackageEntry(waptfile = package_filename)
    # authorized_certs is a directoyr instead a list of certificates.
    if authorized_certs is not None and authorized_certs != '' and not isinstance(authorized_certs,list):
        bundle = SSLCABundle()
        bundle.add_pems(makepath(authorized_certs,'*.crt'))
        bundle.add_pems(makepath(authorized_certs,'*.cer'))
        bundle.add_pems(makepath(authorized_certs,'*.pem'))
    else:
        bundle = authorized_certs or None

    source_package.unzip_package(target_dir=target_directory,cabundle=bundle)
    source_package.invalidate_signature()

    package = PackageEntry(waptfile = source_package.sourcespath)
    oldname = source_package.package
    package.package = rename_package(oldname,new_prefix)
    package.inc_build()
    if set_maturity is not None:
        package.maturity = set_maturity

    result = package['sourcespath']

    # renames dependencies
    if package.depends:
        newdepends = []
        depends = ensure_list(package.depends)
        for dependname in depends:
            newname = rename_package(dependname,new_prefix)
            newdepends.append(newname)

        package.depends = ','.join(newdepends)

    # renames conflicts
    if package.conflicts:
        newconflicts = []
        conflicts = ensure_list(package.conflicts)
        for dependname in conflicts:
            newname = rename_package(dependname,new_prefix)
            newconflicts.append(newname)

        package.conflicts = ','.join(newconflicts)

    package.save_control_to_wapt()
    return result
Esempio n. 15
0
def main():
    parser=OptionParser(usage=__doc__,prog = 'wapt-signpackage')
    parser.add_option("-c","--certificate", dest="public_key", default='', help="Path to the PEM RSA certificate to embed identitiy in control. (default: %default)")
    parser.add_option("-k","--private-key", dest="private_key", default='', help="Path to the PEM RSA private key to sign packages.  (default: %default)")
    #parser.add_option("-w","--private-key-passwd", dest="private_key_passwd", default='', help="Path to the password of the private key. (default: %default)")
    parser.add_option("-l","--loglevel", dest="loglevel", default=None, type='choice',  choices=['debug','warning','info','error','critical'], metavar='LOGLEVEL',help="Loglevel (default: warning)")
    parser.add_option("-m","--message-digest", dest="md", default='sha256', help="Message digest type for signatures.  (default: %default)")
    parser.add_option("-s","--scan-packages", dest="doscan", default=False, action='store_true', help="Rescan packages and update local Packages index after signing.  (default: %default)")
    parser.add_option("-r","--remove-setup", dest="removesetup", default=False, action='store_true', help="Remove setup.py.  (default: %default)")
    parser.add_option("-i","--inc-release",    dest="increlease",    default=False, action='store_true', help="Increase release number when building package (default: %default)")
    parser.add_option("--maturity", dest="set_maturity", default=None, help="Set/change package maturity when signing package.  (default: None)")
    parser.add_option(     "--keep-signature-date", dest="keep_signature_date",default=False, action='store_true', help="Keep the current package signature date, and file changetime (default: %default)")
    parser.add_option(     "--if-needed", dest="if_needed", default=False, action='store_true',help="Re-sign package only if needed (default: warning)")
    (options,args) = parser.parse_args()

    loglevel = options.loglevel

    if len(logger.handlers) < 1:
        hdlr = logging.StreamHandler(sys.stderr)
        hdlr.setFormatter(logging.Formatter(
            u'%(asctime)s %(levelname)s %(message)s'))
        logger.addHandler(hdlr)

    if loglevel:
        setloglevel(logger,loglevel)
    else:
        setloglevel(logger,'warning')

    if len(args) < 1:
        print(parser.usage)
        sys.exit(1)

    if not options.public_key and not options.private_key:
        print('ERROR: No certificate found or specified')
        sys.exit(1)

    if options.private_key and os.path.isfile(options.private_key):
        key = SSLPrivateKey(options.private_key)
    else:
        cert = SSLCertificate(options.public_key or options.private_key)
        key = cert.matching_key_in_dirs()

    if not key:
        print('ERROR: No private key found or specified')
        sys.exit(1)

    args = ensure_list(args)

    ca_bundle = SSLCABundle()
    signers_bundle = SSLCABundle()
    signers_bundle.add_certificates_from_pem(pem_filename=options.public_key)

    waptpackages = []
    for arg in args:
        waptpackages.extend(glob.glob(arg))

    errors = []
    package_dirs = []
    for waptpackage in waptpackages:
        package_dir = os.path.abspath(os.path.dirname(waptpackage))
        if not package_dir in package_dirs:
            package_dirs.append(package_dir)

        print('Processing %s'%waptpackage)
        try:
            sign_needed=False
            pe = PackageEntry(waptfile = waptpackage)
            if options.removesetup:
                if pe.has_file('setup.py'):
                    with pe.as_zipfile(mode='a') as waptfile:
                        waptfile.remove('setup.py')
                    sign_needed=True

            if not sign_needed and options.if_needed:
                try:
                    pe.check_control_signature(trusted_bundle=signers_bundle,signers_bundle=signers_bundle)
                    for md in ensure_list(options.md):
                        if not pe.has_file(pe.get_signature_filename(md)):
                            raise Exception('Missing signature for md %s' % md)
                    logger.info('Skipping %s, already signed properly' % pe.asrequirement())
                    sign_needed = False
                except Exception as e:
                    logger.info('Sign is needed for %s because %s' % (pe.asrequirement(),e))
                    sign_needed = True

            if options.increlease:
                pe.inc_build()
                sign_needed = True

            if options.set_maturity is not None and pe.maturity != options.set_maturity:
                pe.maturity = options.set_maturity
                sign_needed = True

            if not options.if_needed or sign_needed:
                pe.sign_package(private_key=key,certificate = signers_bundle.certificates(),mds = ensure_list(options.md),keep_signature_date=options.keep_signature_date)
                newfn = pe.make_package_filename()
                if newfn != pe.filename:
                    newfn_path = os.path.join(package_dir,newfn)
                    if not os.path.isfile(newfn_path):
                        print(u"Renaming file from %s to %s to match new package's properties" % (pe.filename,newfn))
                        shutil.move(os.path.join(package_dir,pe.filename),newfn_path)
                    else:
                        print('WARNING: unable to rename file from %s to %s because target already exists' % (pe.filename,newfn))

            print('Done')
        except Exception as e:
            print(u'Error: %s'%ensure_unicode(e.message))
            errors.append([waptpackage,repr(e)])

    if options.doscan:
        for package_dir in package_dirs:
            if os.path.isfile(os.path.join(package_dir,'Packages')):
                print(u'Launching the update of Packages index in %s ...'% ensure_unicode(package_dir))
                repo = WaptLocalRepo(package_dir)
                repo.update_packages_index()
                print('Done')
    else:
        print("Don't forget to rescan your repository with wapt-scanpackages %s" % os.path.dirname(waptpackages[0]))

    if errors:
        print('Package not processed properly: ')
        for fn,error in errors:
            print(u'%s : %s' % (fn,error))

        sys.exit(1)
    else:
        sys.exit(0)
Esempio n. 16
0
def edit_hosts_depends(
    waptconfigfile,
    hosts_list,
    append_depends=[],
    remove_depends=[],
    append_conflicts=[],
    remove_conflicts=[],
    sign_certs=None,
    sign_key=None,
    key_password=None,
    wapt_server_user=None,
    wapt_server_passwd=None,
    cabundle=None,
):
    """Add or remove packages from host packages

    Args:

    Returns:
        dict: { updated: of uuid of machines actually updated
                unchanged : list of uuid skipped because of no change needed
                discarded : list of uuid discarded due to errors}

    >>> edit_hosts_depends('c:/wapt/wapt-get.ini','htlaptop.tranquilit.local','toto','tis-7zip','admin','password')
    """
    if sign_certs is None:
        sign_bundle_fn = inifile_readstring(waptconfigfile, u'global',
                                            u'personal_certificate_path')
        sign_bundle = SSLCABundle(sign_bundle_fn)
        sign_certs = sign_bundle.certificates()
        # we assume a unique signer.
        if cabundle is None:
            cabundle = sign_bundle

    if not sign_certs:
        raise Exception(u'No personal signer certificate found in %s' %
                        sign_bundle_fn)

    try:
        import waptconsole
        progress_hook = waptconsole.UpdateProgress
        private_key_password_callback = waptconsole.GetPrivateKeyPassword
    except ImportError as e:

        def print_progress(show=False, n=0, max=100, msg=''):
            if show:
                print('%s %s/%s\r' % (msg, n, max), end='')
            else:
                if not msg:
                    msg = 'Done'
                print("%s%s" % (msg, ' ' * (80 - len(msg))))

        progress_hook = print_progress
        private_key_password_callback = None

    if sign_key is None:
        sign_key = sign_certs[0].matching_key_in_dirs(
            private_key_password=key_password,
            password_callback=private_key_password_callback)

    progress_hook(True, 0, len(hosts_list),
                  'Loading %s hosts packages' % len(hosts_list))

    host_repo = WaptHostRepo(name='wapt-host',
                             host_id=[h['uuid'] for h in hosts_list],
                             cabundle=cabundle)
    host_repo.private_key_password_callback = private_key_password_callback
    host_repo.load_config_from_file(waptconfigfile)
    total_hosts = len(host_repo.packages())
    discarded_uuids = [p.package for p in host_repo.discarded]

    append_depends = ensure_list(append_depends)
    remove_depends = ensure_list(remove_depends)
    append_conflicts = ensure_list(append_conflicts)
    remove_conflicts = ensure_list(remove_conflicts)

    packages = []
    discarded = []
    unchanged = []

    progress_hook(True, 0, len(hosts_list),
                  'Editing %s hosts' % len(hosts_list))
    i = 0
    try:
        for hostrec in hosts_list:
            host_id = hostrec['uuid']
            i += 1
            # don't change discarded packages.
            if host_id in discarded_uuids:
                discarded.append(host_id)
            else:
                host = host_repo.get(host_id)
                if host is None:
                    host = PackageEntry(package=host_id, section='host')

                if progress_hook(True, i, len(hosts_list),
                                 'Editing %s' % host.package):
                    break

                logger.debug(u'Edit host %s : +%s -%s' %
                             (host.package, append_depends, remove_depends))

                depends = host.depends
                conflicts = host.conflicts

                conflicts = add_to_csv_list(conflicts, append_conflicts)
                conflicts = remove_from_csv_list(conflicts, remove_conflicts)
                depends = remove_from_csv_list(depends, ensure_list(conflicts))

                depends = add_to_csv_list(depends, append_depends)
                depends = remove_from_csv_list(depends, remove_depends)
                conflicts = remove_from_csv_list(conflicts,
                                                 ensure_list(depends))

                if depends != host.depends or conflicts != host.conflicts:
                    host.depends = depends
                    host.conflicts = conflicts
                    host.inc_build()
                    host_file = host.build_management_package()
                    host.sign_package(sign_certs, sign_key)
                    packages.append(host)
                else:
                    unchanged.append(host.package)

        # upload all in one step...
        progress_hook(True, 3, 3, 'Upload %s host packages' % len(packages))
        server = WaptServer().load_config_from_file(waptconfigfile)
        server.private_key_password_callback = private_key_password_callback
        server.upload_packages(packages,
                               auth=(wapt_server_user, wapt_server_passwd),
                               progress_hook=progress_hook)

        return dict(updated=[p.package for p in packages],
                    discarded=discarded,
                    unchanged=unchanged)

    finally:
        logger.debug('Cleanup')
        try:
            i = 0
            for s in packages:
                i += 1
                progress_hook(True, i, len(packages), 'Cleanup')
                if os.path.isfile(s.localpath):
                    os.remove(s.localpath)
            progress_hook(False)
        except WindowsError as e:
            logger.critical('Unable to remove temporary directory %s: %s' %
                            (s, repr(e)))
            progress_hook(False)
Esempio n. 17
0
    def load(self):
        """Load waptservice parameters from global wapt-get.ini file"""
        config = ConfigParser.RawConfigParser()
        if os.path.exists(self.config_filename):
            config.read(self.config_filename)
            self.config_filedate = os.stat(self.config_filename).st_mtime
        else:
            raise Exception(_("FATAL. Couldn't open config file : {}").format(self.config_filename))
        # lecture configuration
        if config.has_section('global'):
            if config.has_option('global', 'waptservice_user'):
                self.waptservice_user = config.get('global', 'waptservice_user')
            else:
                self.waptservice_user = None

            if config.has_option('global','waptservice_password'):
                self.waptservice_password = config.get('global', 'waptservice_password')
            else:
                logger.info(u"No password set for local waptservice, using local computer security")
                self.waptservice_password=None  # = password

            if config.has_option('global','waptservice_port'):
                port = config.get('global','waptservice_port')
                if port:
                    self.waptservice_port = int(port)
                else:
                    self.waptservice_port = None
            else:
                self.waptservice_port=8088

            if config.has_option('global','language'):
                self.language = config.get('global','language')

            if config.has_option('global','secret_key'):
                self.secret_key = config.get('global','secret_key')

            if config.has_option('global','waptservice_poll_timeout'):
                self.waptservice_poll_timeout = int(config.get('global','waptservice_poll_timeout'))
            else:
                self.waptservice_poll_timeout = 10

            if config.has_option('global','waptupgrade_task_period'):
                self.waptupgrade_task_period = int(config.get('global','waptupgrade_task_period'))
            else:
                self.waptupgrade_task_period = None

            if config.has_option('global','waptupdate_task_period'):
                self.waptupdate_task_period = int(config.get('global','waptupdate_task_period'))
            else:
                self.waptupdate_task_period = 120

            if config.has_option('global','waptaudit_task_period'):
                self.waptaudit_task_period = config.get('global','waptaudit_task_period')

            if config.has_option('global','dbpath'):
                self.dbpath =  config.get('global','dbpath')
            else:
                self.dbpath = os.path.join(wapt_root_dir,'db','waptdb.sqlite')

            if self.dbpath != ':memory:':
                self.dbdir = os.path.dirname(self.dbpath)
                if not os.path.isdir(self.dbdir):
                    os.makedirs(self.dbdir)
            else:
                self.dbdir = None

            if config.has_option('global','loglevel'):
                self.loglevel = config.get('global','loglevel')

            if config.has_option('global','log_to_windows_events'):
                self.log_to_windows_events = config.getboolean('global','log_to_windows_events')

            if config.has_option('global','allow_user_service_restart'):
                self.allow_user_service_restart = config.getboolean('global','allow_user_service_restart')

            if config.has_option('global','notify_user'):
                self.notify_user = config.getboolean('global','notify_user')

            if config.has_option('global','wapt_server'):
                self.waptserver = common.WaptServer().load_config(config)
                if self.waptserver.server_url:
                    waptserver_url = urlparse.urlparse(self.waptserver.server_url)
                    self.websockets_host = waptserver_url.hostname
                    self.websockets_proto = waptserver_url.scheme

                    if waptserver_url.port is None:
                        if waptserver_url.scheme == 'https':
                            self.websockets_port = 443
                        else:
                            self.websockets_port = 80
                    else:
                        self.websockets_port = waptserver_url.port

                    if waptserver_url.path in ('','/'):
                        self.websockets_root = 'socket.io'
                    else:
                        self.websockets_root = '%s/socket.io' % waptserver_url.path[1:]
                else:
                    self.waptserver = None
                    self.websockets_host = None
                    self.websockets_proto = None
                    self.websockets_port = None
                    self.websockets_verify_cert = False
            else:
                self.waptserver = None
                self.websockets_host = None
                self.websockets_proto = None
                self.websockets_port = None
                self.websockets_verify_cert = False


            if config.has_option('global','websockets_verify_cert'):
                try:
                    self.websockets_verify_cert = config.getboolean('global','websockets_verify_cert')
                except:
                    self.websockets_verify_cert = config.get('global','websockets_verify_cert')
                    if not os.path.isfile(self.websockets_verify_cert):
                        logger.warning(u'websockets_verify_cert certificate %s declared in configuration file can not be found. Waptserver websockets communication will fail' % self.websockets_verify_cert)
            else:
                self.websockets_verify_cert = False

            if config.has_option('global','websockets_ping'):
                self.websockets_ping = config.getint('global','websockets_ping')

            if config.has_option('global','websockets_retry_delay'):
                self.websockets_retry_delay = config.getint('global','websockets_retry_delay')

            if config.has_option('global','websockets_check_config_interval'):
                self.websockets_check_config_interval = config.getint('global','websockets_check_config_interval')

            if config.has_option('global','websockets_hurry_interval'):
                self.websockets_hurry_interval = config.getint('global','websockets_hurry_interval')

            if config.has_option('global','signature_clockskew'):
                self.signature_clockskew = config.getint('global','signature_clockskew')

            # settings for waptexit / shutdown policy
            #   recommended settings :
            #       hiberboot_enabled = 0
            #       max_gpo_script_wait = 180
            #       pre_shutdown_timeout = 180
            for param in ('hiberboot_enabled','max_gpo_script_wait','pre_shutdown_timeout'):
                if config.has_option('global',param):
                    setattr(self,param,config.getint('global',param))
                else:
                    setattr(self,param,None)

            # waptwua settings (Enterprise)
            if config.has_option('global','waptwua_enabled'):
                setattr(self,'waptwua_enabled',config.getboolean('global','waptwua_enabled'))
            else:
                setattr(self,'waptwua_enabled',None)

            for param in ['waptwua_allowed_updates','waptwua_forbidden_updates','waptwua_allowed_severities','waptwua_allowed_classifications']:
                if config.has_option('global',param):
                    setattr(self,param,ensure_list(config.get('global',param)))
                else:
                    setattr(self,param,None)

            for param in ['waptwua_download_scheduling','waptwua_install_scheduling']:
                if config.has_option('global',param):
                    setattr(self,param,config.get('global',param))
                else:
                    setattr(self,param,None)

        else:
            raise Exception (_("FATAL, configuration file {} has no section [global]. Please check Waptserver documentation").format(self.config_filename))
Esempio n. 18
0
def main():
    parser=OptionParser(usage=__doc__,prog = 'wapt-signpackage')
    parser.add_option("-c","--certificate", dest="public_key", default='', help="Path to the PEM RSA certificate to embed identitiy in control. (default: %default)")
    parser.add_option("-k","--private-key", dest="private_key", default='', help="Path to the PEM RSA private key to sign packages.  (default: %default)")
    #parser.add_option("-w","--private-key-passwd", dest="private_key_passwd", default='', help="Path to the password of the private key. (default: %default)")
    parser.add_option("-l","--loglevel", dest="loglevel", default=None, type='choice',  choices=['debug','warning','info','error','critical'], metavar='LOGLEVEL',help="Loglevel (default: warning)")
    parser.add_option("-m","--message-digest", dest="md", default='sha256', help="Message digest type for signatures.  (default: %default)")
    parser.add_option("-s","--scan-packages", dest="doscan", default=False, action='store_true', help="Rescan packages and update local Packages index after signing.  (default: %default)")
    parser.add_option("-r","--remove-setup", dest="removesetup", default=False, action='store_true', help="Remove setup.py.  (default: %default)")
    parser.add_option("-i","--inc-release",    dest="increlease",    default=False, action='store_true', help="Increase release number when building package (default: %default)")
    parser.add_option("--maturity", dest="set_maturity", default=None, help="Set/change package maturity when signing package.  (default: None)")
    parser.add_option(     "--keep-signature-date", dest="keep_signature_date",default=False, action='store_true', help="Keep the current package signature date, and file changetime (default: %default)")
    parser.add_option(     "--if-needed", dest="if_needed", default=False, action='store_true',help="Re-sign package only if needed (default: warning)")
    (options,args) = parser.parse_args()

    loglevel = options.loglevel

    if len(logger.handlers) < 1:
        hdlr = logging.StreamHandler(sys.stderr)
        hdlr.setFormatter(logging.Formatter(
            u'%(asctime)s %(levelname)s %(message)s'))
        logger.addHandler(hdlr)

    if loglevel:
        setloglevel(logger,loglevel)
    else:
        setloglevel(logger,'warning')

    if len(args) < 1:
        print(parser.usage)
        sys.exit(1)

    if not options.public_key and not options.private_key:
        print('ERROR: No certificate found or specified')
        sys.exit(1)

    if options.private_key and os.path.isfile(options.private_key):
        key = SSLPrivateKey(options.private_key)
    else:
        cert = SSLCertificate(options.public_key or options.private_key)
        key = cert.matching_key_in_dirs()

    if not key:
        print('ERROR: No private key found or specified')
        sys.exit(1)

    args = ensure_list(args)

    ca_bundle = SSLCABundle()
    signers_bundle = SSLCABundle()
    signers_bundle.add_certificates_from_pem(pem_filename=options.public_key)

    waptpackages = []
    for arg in args:
        waptpackages.extend(glob.glob(arg))

    errors = []
    package_dirs = []
    for waptpackage in waptpackages:
        package_dir = os.path.abspath(os.path.dirname(waptpackage))
        if not package_dir in package_dirs:
            package_dirs.append(package_dir)

        print('Processing %s'%waptpackage)
        try:
            sign_needed=False
            pe = PackageEntry(waptfile = waptpackage)
            if options.removesetup:
                if pe.has_file('setup.py'):
                    with pe.as_zipfile(mode='a') as waptfile:
                        waptfile.remove('setup.py')
                    sign_needed=True

            if not sign_needed and options.if_needed:
                try:
                    pe.check_control_signature(trusted_bundle=signers_bundle,signers_bundle=signers_bundle)
                    for md in ensure_list(options.md):
                        if not pe.has_file(pe.get_signature_filename(md)):
                            raise Exception('Missing signature for md %s' % md)
                    logger.info('Skipping %s, already signed properly' % pe.asrequirement())
                    sign_needed = False
                except Exception as e:
                    logger.info('Sign is needed for %s because %s' % (pe.asrequirement(),e))
                    sign_needed = True

            if options.increlease:
                pe.inc_build()
                sign_needed = True

            if options.set_maturity is not None and pe.maturity != options.set_maturity:
                pe.maturity = options.set_maturity
                sign_needed = True

            if not options.if_needed or sign_needed:
                pe.sign_package(private_key=key,certificate = signers_bundle.certificates(),mds = ensure_list(options.md),keep_signature_date=options.keep_signature_date)
                newfn = pe.make_package_filename()
                if newfn != pe.filename:
                    newfn_path = os.path.join(package_dir,newfn)
                    if not os.path.isfile(newfn_path):
                        print(u"Renaming file from %s to %s to match new package's properties" % (pe.filename,newfn))
                        os.rename(os.path.join(package_dir,pe.filename),newfn_path)
                    else:
                        print('WARNING: unable to rename file from %s to %s because target already exists' % (pe.filename,newfn))

            print('Done')
        except Exception as e:
            print(u'Error: %s'%ensure_unicode(e.message))
            errors.append([waptpackage,repr(e)])

    if options.doscan:
        for package_dir in package_dirs:
            if os.path.isfile(os.path.join(package_dir,'Packages')):
                print(u'Launching the update of Packages index in %s ...'% ensure_unicode(package_dir))
                repo = WaptLocalRepo(package_dir)
                repo.update_packages_index()
                print('Done')
    else:
        print("Don't forget to rescan your repository with wapt-scanpackages %s" % os.path.dirname(waptpackages[0]))

    if errors:
        print('Package not processed properly: ')
        for fn,error in errors:
            print(u'%s : %s' % (fn,error))

        sys.exit(1)
    else:
        sys.exit(0)
Esempio n. 19
0
def add_ads_groups(waptconfigfile,
                   hosts_list,
                   wapt_server_user,
                   wapt_server_passwd,
                   key_password=None):
    # initialise wapt api with local config file
    wapt = Wapt(config_filename=waptconfigfile)
    wapt.dbpath = ':memory:'

    # get current packages status from repositories
    wapt.update(register=False, filter_on_host_cap=False)

    hosts_list = ensure_list(hosts_list)

    # get the collection of hosts from waptserver inventory
    all_hosts = wapt.waptserver.get(
        'api/v1/hosts?columns=uuid,computer_fqdn,depends',
        auth=(wapt_server_user, wapt_server_passwd))['result']
    if hosts_list:
        hosts = [h for h in all_hosts if h['computer_fqdn'] in hosts_list]
    else:
        hosts = hosts_list

    result = []

    for h in hosts:
        try:
            hostname = h['computer_fqdn']
            print('Computer %s... \r' % hostname, end='')

            groups = get_computer_groups(h['computer_name'])
            wapt_groups = h['depends']
            additional = [
                group for group in groups
                if not group in wapt_groups and wapt.is_available(group)
            ]

            if additional:
                # now update the host package : download and append missing packages
                tmpdir = mkdtemp()
                try:
                    package = wapt.edit_host(hostname, target_directory=tmpdir)
                    control = package['package']
                    depends = ensure_list(control.depends)

                    control.depends = ','.join(depends + additional)
                    control.save_control_to_wapt(package.sourcespath)
                    buid_res = wapt.build_upload(
                        package.sourcespath,
                        private_key_passwd=key_password,
                        wapt_server_user=wapt_server_user,
                        wapt_server_passwd=wapt_server_passwd,
                        inc_package_release=True)[0]
                    print("  done, new packages: %s" % (','.join(additional)))
                    if os.path.isfile(buid_res):
                        os.remove(buid_res)
                    result.append(hostname)
                finally:
                    # cleanup of temporary
                    if os.path.isdir(tmpdir):
                        rmtree(tmpdir)
        except Exception as e:
            print(" error %s" % e)
            raise

    return result
Esempio n. 20
0
def add_ads_groups(waptconfigfile,
        hostdicts_list,
        sign_certs=None,
        sign_key=None,
        key_password=None,
        wapt_server_user=None,wapt_server_passwd=None,
        cabundle = None):

    if sign_certs is None:
        sign_bundle_fn = inifile_readstring(waptconfigfile,u'global',u'personal_certificate_path')
        sign_bundle = SSLCABundle(sign_bundle_fn)
        sign_certs = sign_bundle.certificates()
        # we assume a unique signer.
        if cabundle is None:
            cabundle = sign_bundle

    if not sign_certs:
        raise Exception(u'No personal signer certificate found in %s' % sign_bundle_fn)

    if sign_key is None:
        sign_key = sign_certs[0].matching_key_in_dirs(private_key_password=key_password)

    main_repo = WaptRemoteRepo(name='wapt',cabundle = cabundle)
    main_repo.load_config_from_file(waptconfigfile)

    host_repo = WaptHostRepo(name='wapt-host',host_id=[h['uuid'] for h in hostdicts_list],cabundle = cabundle)
    host_repo.load_config_from_file(waptconfigfile)

    total_hosts = len(host_repo.packages())
    discarded_uuids = [p.package for p in host_repo.discarded]


    try:
        import waptconsole
        progress_hook = waptconsole.UpdateProgress
    except ImportError as e:
        def print_progress(show=False,n=0,max=100,msg=''):
            if show:
                print('%s %s/%s\r' % (msg,n,max),end='')
            else:
                if not msg:
                    msg='Done'
                print("%s%s"%(msg,' '*(80-len(msg))))
        progress_hook = print_progress

    packages = []
    discarded = []
    unchanged = []

    try:
        progress_hook(True,0,len(hostdicts_list),'Editing %s hosts' % len(hostdicts_list))
        i = 0
        for h in hostdicts_list:
            try:
                host_package = None
                host_id = h['uuid']
                hostname = h['computer_name']
                groups = get_computer_groups(hostname)
                host_package = host_repo.get(host_id,PackageEntry(package=host_id,section='host'))
                if progress_hook(True,i,len(hostdicts_list),'Checking %s' % host_package.package):
                    break

                wapt_groups = ensure_list(host_package['depends'])
                additional = [group for group in groups if not group in wapt_groups and (main_repo.get(group,None) is not None)]
                if additional:
                    logger.info(u'Adding %s to %s' % (','.join(additional),host_package.package))
                    if progress_hook(True,i,len(hostdicts_list),'Editing %s' % host_package.package):
                        break
                    wapt_groups.extend(additional)
                    host_package.depends = ','.join(wapt_groups)
                    host_package.build_management_package()
                    host_package.inc_build()
                    host_file = host_package.build_management_package()
                    host_package.sign_package(sign_certs,sign_key)
                    packages.append(host_package)
                else:
                    unchanged.append(host_package.package)
            except Exception as e:
                if host_package:
                    discarded.append(host_package.package)
                logger.critical(u'Discarding because %s' % ensure_unicode(e))

        # upload all in one step...
        progress_hook(True,3,3,'Upload %s host packages' % len(packages))
        server = WaptServer().load_config_from_file(waptconfigfile)
        server.upload_packages(packages,auth=(wapt_server_user,wapt_server_passwd),progress_hook=progress_hook)
        return dict(updated = packages,
                    discarded = discarded,
                    unchanged = unchanged)

    finally:
        logger.debug('Cleanup')
        try:
            i = 0
            for s in packages:
                i+=1
                progress_hook(True,i,len(packages),'Cleanup')
                if os.path.isfile(s.localpath):
                    os.remove(s.localpath)
            progress_hook(False)
        except WindowsError as e:
            logger.critical('Unable to remove temporary directory %s: %s'% (s,repr(e)))
            progress_hook(False)
Esempio n. 21
0
def edit_hosts_depends(waptconfigfile,hosts_list,
        append_depends=[],
        remove_depends=[],
        append_conflicts=[],
        remove_conflicts=[],
        sign_certs=None,
        sign_key=None,
        key_password=None,
        wapt_server_user=None,wapt_server_passwd=None,
        cabundle = None,
        ):
    """Add or remove packages from host packages

    Args:

    Returns:
        dict: { updated: of uuid of machines actually updated
                unchanged : list of uuid skipped because of no change needed
                discarded : list of uuid discarded due to errors}

    >>> edit_hosts_depends('c:/wapt/wapt-get.ini','htlaptop.tranquilit.local','toto','tis-7zip','admin','password')
    """
    if sign_certs is None:
        sign_bundle_fn = inifile_readstring(waptconfigfile,u'global',u'personal_certificate_path')
        sign_bundle = SSLCABundle(sign_bundle_fn)
        sign_certs = sign_bundle.certificates()
        # we assume a unique signer.
        if cabundle is None:
            cabundle = sign_bundle

    if not sign_certs:
        raise Exception(u'No personal signer certificate found in %s' % sign_bundle_fn)

    if sign_key is None:
        sign_key = sign_certs[0].matching_key_in_dirs(private_key_password=key_password)

    try:
        import waptconsole
        progress_hook = waptconsole.UpdateProgress
    except ImportError as e:
        def print_progress(show=False,n=0,max=100,msg=''):
            if show:
                print('%s %s/%s\r' % (msg,n,max),end='')
            else:
                if not msg:
                    msg='Done'
                print("%s%s"%(msg,' '*(80-len(msg))))
        progress_hook = print_progress

    hosts_list = ensure_list(hosts_list)

    progress_hook(True,0,len(hosts_list),'Loading %s hosts packages' % len(hosts_list))

    host_repo = WaptHostRepo(name='wapt-host',host_id=hosts_list,cabundle = cabundle)
    host_repo.load_config_from_file(waptconfigfile)
    total_hosts = len(host_repo.packages())
    discarded_uuids = [p.package for p in host_repo.discarded]

    hosts_list = ensure_list(hosts_list)
    append_depends = ensure_list(append_depends)
    remove_depends = ensure_list(remove_depends)
    append_conflicts = ensure_list(append_conflicts)
    remove_conflicts = ensure_list(remove_conflicts)

    packages = []
    discarded = []
    unchanged = []

    progress_hook(True,0,len(hosts_list),'Editing %s hosts' % len(hosts_list))
    i = 0
    try:
        for host_id in hosts_list:
            i+=1
            # don't change discarded packages.
            if host_id in discarded_uuids:
                discarded.append(host_id)
            else:
                host = host_repo.get(host_id)
                if host is None:
                    host = PackageEntry(package=host_id,section='host')

                if progress_hook(True,i,len(hosts_list),'Editing %s' % host.package):
                    break

                logger.debug(u'Edit host %s : +%s -%s'%(
                    host.package,
                    append_depends,
                    remove_depends))


                depends = host.depends
                conflicts = host.conflicts

                conflicts = add_to_csv_list(conflicts,append_conflicts)
                conflicts = remove_from_csv_list(conflicts,remove_conflicts)
                depends = remove_from_csv_list(depends,ensure_list(conflicts))

                depends = add_to_csv_list(depends,append_depends)
                depends = remove_from_csv_list(depends,remove_depends)
                conflicts = remove_from_csv_list(conflicts,ensure_list(depends))

                if depends != host.depends or conflicts != host.conflicts:
                    host.depends = depends
                    host.conflicts = conflicts
                    host.inc_build()
                    host_file = host.build_management_package()
                    host.sign_package(sign_certs,sign_key)
                    packages.append(host)
                else:
                    unchanged.append(host.package)

        # upload all in one step...
        progress_hook(True,3,3,'Upload %s host packages' % len(packages))
        server = WaptServer().load_config_from_file(waptconfigfile)
        server.upload_packages(packages,auth=(wapt_server_user,wapt_server_passwd),progress_hook=progress_hook)
        return dict(updated = [p.package for p in packages],
                    discarded = discarded,
                    unchanged = unchanged)

    finally:
        logger.debug('Cleanup')
        try:
            i = 0
            for s in packages:
                i+=1
                progress_hook(True,i,len(packages),'Cleanup')
                if os.path.isfile(s.localpath):
                    os.remove(s.localpath)
            progress_hook(False)
        except WindowsError as e:
            logger.critical('Unable to remove temporary directory %s: %s'% (s,repr(e)))
            progress_hook(False)
Esempio n. 22
0
def build_waptupgrade_package(waptconfigfile,target_directory=None,wapt_server_user=None,wapt_server_passwd=None,key_password=None,sign_digests=None,priority='critical'):
    if target_directory is None:
        target_directory = tempfile.gettempdir()

    if not wapt_server_user:
        wapt_server_user = raw_input('WAPT Server user :'******'WAPT Server password :'******'ascii')

    wapt = common.Wapt(config_filename=waptconfigfile,disable_update_server_status=True)
    wapt.dbpath = r':memory:'
    wapt.use_hostpackages = False

    # try to get a progress hook inside waptconsole
    try:
        import waptconsole
        progress_hook = waptconsole.UpdateProgress
    except ImportError:
        def print_progress(show=False,n=0,max=100,msg=''):
            if show:
                print('%s %s/%s\r' % (msg,n,max),end='')
            else:
                if not msg:
                    msg='Done'
                print("%s%s"%(msg,' '*(80-len(msg))))
        progress_hook = print_progress

    wapt.progress_hook = progress_hook

    if sign_digests is None:
        sign_digests = wapt.sign_digests

    if not wapt.personal_certificate_path or not os.path.isfile(wapt.personal_certificate_path):
        raise Exception(u'No personal certificate provided or not found (%s) for signing waptupgrade package' % wapt.personal_certificate_path)

    waptget = get_file_properties('wapt-get.exe')
    entry = PackageEntry(waptfile = makepath(wapt.wapt_base_dir,'waptupgrade'))
    patchs_dir = makepath(entry.sourcespath,'patchs')
    mkdirs(patchs_dir)
    filecopyto(makepath(wapt.wapt_base_dir,'waptdeploy.exe'),makepath(patchs_dir,'waptdeploy.exe'))

    entry.package = '%s-waptupgrade' % wapt.config.get('global','default_package_prefix')
    rev = entry.version.split('-')[1]
    entry.version = '%s-%s' % (waptget['FileVersion'],rev)
    entry.inc_build()
    entry.save_control_to_wapt()
    entry.build_package(target_directory=target_directory)
    entry.priority = priority
    certs = wapt.personal_certificate()
    key = wapt.private_key(private_key_password=key_password)
    if not certs[0].is_code_signing:
        raise Exception(u'%s is not a code signing certificate' % wapt.personal_certificate_path)
    entry.sign_package(private_key=key,certificate = certs,private_key_password=key_password,mds = ensure_list(sign_digests))

    wapt.http_upload_package(entry.localpath,wapt_server_user=wapt_server_user,wapt_server_passwd=wapt_server_passwd,progress_hook=progress_hook)
    return entry.as_dict()
Esempio n. 23
0
def add_ads_groups(waptconfigfile,
                   hostdicts_list,
                   sign_certs=None,
                   sign_key=None,
                   key_password=None,
                   wapt_server_user=None,
                   wapt_server_passwd=None,
                   cabundle=None):

    if sign_certs is None:
        sign_bundle_fn = inifile_readstring(waptconfigfile, u'global',
                                            u'personal_certificate_path')
        sign_bundle = SSLCABundle(sign_bundle_fn)
        sign_certs = sign_bundle.certificates()
        # we assume a unique signer.
        if cabundle is None:
            cabundle = sign_bundle

    if not sign_certs:
        raise Exception(u'No personal signer certificate found in %s' %
                        sign_bundle_fn)

    if sign_key is None:
        sign_key = sign_certs[0].matching_key_in_dirs(
            private_key_password=key_password)

    try:
        import waptconsole
        progress_hook = waptconsole.UpdateProgress
        private_key_password_callback = waptconsole.GetPrivateKeyPassword
    except ImportError as e:

        def print_progress(show=False, n=0, max=100, msg=''):
            if show:
                print('%s %s/%s\r' % (msg, n, max), end='')
            else:
                if not msg:
                    msg = 'Done'
                print("%s%s" % (msg, ' ' * (80 - len(msg))))

        progress_hook = print_progress
        private_key_password_callback = None

    main_repo = WaptRemoteRepo(name='wapt', cabundle=cabundle)
    main_repo.load_config_from_file(waptconfigfile)
    main_repo.private_key_password_callback = private_key_password_callback

    host_repo = WaptHostRepo(name='wapt-host',
                             host_id=[h['uuid'] for h in hostdicts_list],
                             cabundle=cabundle)
    host_repo.load_config_from_file(waptconfigfile)
    host_repo.private_key_password_callback = private_key_password_callback

    total_hosts = len(host_repo.packages())
    discarded_uuids = [p.package for p in host_repo.discarded]

    packages = []
    discarded = []
    unchanged = []

    try:
        progress_hook(True, 0, len(hostdicts_list),
                      'Editing %s hosts' % len(hostdicts_list))
        i = 0
        for h in hostdicts_list:
            try:
                host_package = None
                host_id = h['uuid']
                hostname = h['computer_name']
                groups = get_computer_groups(hostname)
                host_package = host_repo.get(
                    host_id, PackageEntry(package=host_id, section='host'))
                if progress_hook(True, i, len(hostdicts_list),
                                 'Checking %s' % host_package.package):
                    break

                wapt_groups = ensure_list(host_package['depends'])
                additional = [
                    group for group in groups if not group in wapt_groups and (
                        main_repo.get(group, None) is not None)
                ]
                if additional:
                    logger.info(u'Adding %s to %s' %
                                (','.join(additional), host_package.package))
                    if progress_hook(True, i, len(hostdicts_list),
                                     'Editing %s' % host_package.package):
                        break
                    wapt_groups.extend(additional)
                    host_package.depends = ','.join(wapt_groups)
                    host_package.build_management_package()
                    host_package.inc_build()
                    host_file = host_package.build_management_package()
                    host_package.sign_package(sign_certs, sign_key)
                    packages.append(host_package)
                else:
                    unchanged.append(host_package.package)
            except Exception as e:
                if host_package:
                    discarded.append(host_package.package)
                logger.critical(u'Discarding because %s' % ensure_unicode(e))

        # upload all in one step...
        progress_hook(True, 3, 3, 'Upload %s host packages' % len(packages))
        server = WaptServer().load_config_from_file(waptconfigfile)
        server.private_key_password_callback = private_key_password_callback
        server.upload_packages(packages,
                               auth=(wapt_server_user, wapt_server_passwd),
                               progress_hook=progress_hook)
        return dict(updated=packages, discarded=discarded, unchanged=unchanged)

    finally:
        logger.debug('Cleanup')
        try:
            i = 0
            for s in packages:
                i += 1
                progress_hook(True, i, len(packages), 'Cleanup')
                if os.path.isfile(s.localpath):
                    os.remove(s.localpath)
            progress_hook(False)
        except WindowsError as e:
            logger.critical('Unable to remove temporary directory %s: %s' %
                            (s, repr(e)))
            progress_hook(False)
Esempio n. 24
0
    def on_trigger_host_action(self,args,result_callback=None):
        try:
            start_time = time.time()
            actions = args
            if not isinstance(actions,list):
                actions =[actions]
            logger.debug('Host actions "%s" triggered by SocketIO' % ",".join([action['action'] for action in actions]))
            # check signatures
            if not self.wapt:
                raise Exception('Wapt not available')
            verified_by = None
            for action in actions:
                name = action['action']
                verified_by = None
                signer_cert_chain = SSLCABundle().add_pem(action['signer_certificate']).certificates()
                chain = self.wapt.cabundle.check_certificates_chain(signer_cert_chain)
                if chain:
                    required_attributes = ['uuid','action']
                    if name in ['trigger_install_packages','trigger_remove_packages','trigger_forget_packages']:
                        required_attributes.append('packages')
                    if name in ['trigger_change_description']:
                        required_attributes.append('computer_description')
                    if name in waptservice_remote_actions:
                        required_attributes.extend(waptservice_remote_actions[name].required_attributes)

                    verified_by = chain[0].verify_claim(action,max_age_secs=waptconfig.signature_clockskew,
                        required_attributes=required_attributes)
                if not verified_by:
                    raise SSLVerifyException('Bad signature for action %s, aborting' % action)

            if verified_by:
                verified_by = verified_by.get('verified_by',None)

            result = []
            for action in actions:
                uuid = action['uuid']
                if uuid != self.wapt.host_uuid:
                    raise Exception('Task is not targeted to this host. task''s uuid does not match host''uuid')
                name = action['action']
                if name in ['trigger_cancel_all_tasks']:
                    data = [t.as_dict() for t in self.task_manager.cancel_all_tasks()]
                    result.append(data)

                elif name in ['trigger_host_update','trigger_host_register']:
                    if name == 'trigger_host_update':
                        task = WaptUpdate()
                    elif name == 'trigger_host_register':
                        task = WaptRegisterComputer(computer_description = action.get('computer_description',None))
                    task.force = action.get('force',False)
                    task.notify_user = action.get('notify_user',False)
                    task.notify_server_on_finish = action.get('notify_server',False)
                    task.created_by = verified_by
                    data = self.task_manager.add_task(task).as_dict()
                    result.append(data)

                elif name in ['trigger_change_description']:
                    desc = action.get('computer_description',None)
                    if desc is not None:
                        setuphelpers.set_computer_description(desc)
                        msg = u'Computer description of %s changed to %s' % (setuphelpers.get_hostname(),setuphelpers.get_computer_description())
                        if not setuphelpers.get_computer_description() == desc:
                            raise Exception(u'Computer description has not been changed')
                        result.append(dict(success=True,
                            msg = msg,
                            result = msg,
                            ))
                        if action.get('notify_server',False):
                            task = WaptUpdate(created_by=verified_by)
                            task.notify_server_on_finish = True
                            self.task_manager.add_task(task)
                            result.append(task.as_dict())

                elif name == 'trigger_host_upgrade':
                    notify_user = action.get('notify_user',False)
                    notify_server_on_finish = action.get('notify_server',False)
                    force = action.get('force',False)
                    self.wapt.update(force=False)
                    upgrades = self.wapt.list_upgrade()
                    to_install = upgrades['upgrade']+upgrades['additional']+upgrades['install']
                    for req in to_install:
                        result.append(self.task_manager.add_task(WaptPackageInstall(req,force=force,notify_user=notify_user,created_by=verified_by)).as_dict())
                        self.task_manager.add_task(WaptAuditPackage(packagename=req,force=False,
                            notify_user=notify_user,
                            notify_server_on_finish=False,
                            priority=200,
                            created_by=verified_by)).as_dict()
                    result.append(self.task_manager.add_task(WaptUpgrade(notify_user=notify_user,created_by=verified_by,priority=200)).as_dict())
                    result.append(self.task_manager.add_task(WaptCleanup(notify_user=False,created_by=verified_by,priority=200)).as_dict())

                elif name in  ['trigger_install_packages','trigger_remove_packages','trigger_forget_packages']:
                    packagenames = ensure_list(action['packages'])
                    for packagename in packagenames:
                        if name == 'trigger_install_packages':
                            task = WaptPackageInstall(packagename=packagename)
                        elif name == 'trigger_remove_packages':
                            task = WaptPackageRemove(packagename=packagename)
                        elif name == 'trigger_forget_packages':
                            task = WaptPackageForget(packagenames=packagename)
                        task.force = action.get('force',False)
                        task.notify_user = action.get('notify_user',False)
                        task.notify_server_on_finish = action.get('notify_server',False)
                        task.created_by=verified_by

                        result.append(self.task_manager.add_task(task).as_dict())
                        if name == 'trigger_install_packages':
                            self.task_manager.add_task(WaptAuditPackage(packagename=packagename,force=task.force,
                                    notify_user=task.notify_user,
                                    notify_server_on_finish=task.notify_server_on_finish,
                                    priority=200)).as_dict()

                elif name == 'trigger_waptservicerestart':
                    msg = setuphelpers.create_onetime_task('waptservicerestart','cmd.exe','/C net stop waptservice & net start waptservice')
                    result.append(dict(success=True,msg = msg,result = msg))
                elif name in waptservice_remote_actions:
                    waptservice_remote_actions[name].trigger_action(self,action,verified_by)
                else:
                    raise EWaptException('Unhandled remote action %s' % name)

            #self.emit('trigger_update_result',{'result':data})
            if result_callback:
                result_callback(make_response(result,uuid=self.wapt.host_uuid,request_time=time.time()-start_time))
        except BaseException as e:
            logger.info('Exception for actions %s: %s' % (repr(args),repr(e)))
            if result_callback:
                result_callback(make_response_from_exception(e,uuid=self.wapt.host_uuid,request_time=time.time()-start_time))
Esempio n. 25
0
 def _as_attribute(cls, k, v):
     if k in ['depends', 'conflicts']:
         return ensure_list(v or None)
     else:
         return v or None
Esempio n. 26
0
def proxy_host_request(request, action):
    """Proxy a waptconsole action to wapt clients using websockets

    Args:
        uuid: can be a list or a single uuid
        notify_user: 0/1
        notify_server: 0/1

    Returns:
        dict:
            'result':
                'success' (list)
                'errors' (list)
            'msg' (str)
            'success'(bool)
            'request_time' (float)
            'error_code'
    """
    try:
        start_time = time.time()
        all_args = {k: v for k, v in request.args.iteritems()}
        if request.json:
            all_args.update(request.json)

        uuids = ensure_list(all_args['uuid'])
        del(all_args['uuid'])
        timeout = float(request.args.get('timeout', app.conf.get('clients_read_timeout', 5)))

        result = dict(success=[], errors=[])
        tasks = []
        for uuid in uuids:
            try:
                host_data = Hosts\
                    .select(Hosts.uuid, Hosts.computer_fqdn,
                            Hosts.server_uuid,
                            Hosts.listening_address,
                            Hosts.listening_port,
                            Hosts.listening_protocol,
                            Hosts.listening_timestamp,
                            )\
                    .where((Hosts.server_uuid == get_server_uuid()) & (Hosts.uuid == uuid) & (~Hosts.listening_address.is_null()) & (Hosts.listening_protocol == 'websockets'))\
                    .dicts()\
                    .first(1)

                if host_data and host_data.get('listening_address', None):
                    msg = u''
                    logger.info(
                        'Launching %s with args %s for %s at address %s...' %
                        (action, all_args, uuid, host_data['listening_address']))

                    args = dict(all_args)
                    sid = host_data['listening_address']
                    computer_fqdn = host_data['computer_fqdn']

                    def emit_action(sid, uuid, action, action_args, computer_fqdn, timeout=5):
                        try:
                            got_result = []

                            def result_callback(data):
                                got_result.append(data)

                            logger.debug(u'Emit %s to %s (%s)' % (action, uuid, computer_fqdn))
                            socketio.emit(action, action_args, room=sid, callback=result_callback)
                            # with for asynchronous answer...
                            wait_loop = timeout * 20
                            while not got_result:
                                wait_loop -= 1
                                if wait_loop < 0:
                                    raise EWaptTimeoutWaitingForResult('Timeout, client did not send result within %s s' % timeout)
                                socketio.sleep(0.05)

                            # action succedded
                            result['success'].append(
                                dict(
                                    uuid=uuid,
                                    msg=msg,
                                    computer_fqdn=computer_fqdn,
                                    result=got_result[0],
                                ))
                        except Exception as e:
                            result['errors'].append(
                                dict(
                                    uuid=uuid,
                                    msg='%s' % repr(e),
                                    computer_fqdn='',
                                ))
                    if sid:
                        tasks.append(socketio.start_background_task(
                            emit_action, sid=sid, uuid=uuid, action=action, action_args=args, computer_fqdn=computer_fqdn))

                else:
                    result['errors'].append(
                        dict(
                            uuid=uuid,
                            msg='Host %s is not registered or not connected wia websockets' % uuid,
                            computer_fqdn='',
                        ))
            except Exception as e:
                result['errors'].append(
                    dict(
                        uuid=uuid,
                        msg='Host %s error %s' % (uuid, repr(e)),
                        computer_fqdn='',
                    ))

        # wait for all background tasks to terminate or timeout...
        # assume the timeout should be longer if more hosts to perform
        wait_loop = timeout * len(tasks)
        while True:
            running = [t for t in tasks if t.is_alive()]
            if not running:
                break
            wait_loop -= 1
            if wait_loop < 0:
                break
            socketio.sleep(0.05)

        msg = ['Success : %s, Errors: %s' % (len(result['success']), len(result['errors']))]
        if result['errors']:
            msg.extend(['%s: %s' % (e['computer_fqdn'], e['msg'])
                        for e in result['errors']])

        return make_response(result,
                             msg='\n- '.join(msg),
                             success=len(result['success']) > 0,
                             request_time=time.time() - start_time)
    except Exception as e:
        return make_response_from_exception(e)