예제 #1
0
 def write(self, text):
     '''Logs written output to listeners'''
     if text and text != '\n':
         if self.events:
             self.events.send_multipart(
                 [str('PRINT'), (ensure_unicode(text)).encode('utf8')])
         self.logs.append(ensure_unicode(text))
예제 #2
0
def dmi_info():
    """Hardware System information from BIOS estracted with dmidecode
    Convert dmidecode -q output to python dict

    Returns:
        dict

    >>> dmi = dmi_info()
    >>> 'UUID' in dmi['System_Information']
    True
    >>> 'Product_Name' in dmi['System_Information']
    True
    """

    result = {}
    # dmidecode is bugged on macOS, and prints "Bad address" repeatedly on stderr
    if platform.system() != 'Darwin':
        dmiout = ensure_unicode(run('dmidecode -q'))
    else:
        dmiout = ensure_unicode(run('dmidecode -q 2> /dev/null'))

    new_section = True
    for l in dmiout.splitlines():
        if not l.strip() or l.startswith('#'):
            new_section = True
            continue

        if not l.startswith('\t') or new_section:
            currobject = {}
            key = l.strip().replace(' ', '_')
            # already here... so add as array...
            if (key in result):
                if not isinstance(result[key], list):
                    result[key] = [result[key]]
                result[key].append(currobject)
            else:
                result[key] = currobject
            if l.startswith('\t'):
                print(l)
        else:
            if not l.startswith('\t\t'):
                currarray = []
                if ':' in l:
                    (name, value) = l.split(':', 1)
                    currobject[name.strip().replace(' ', '_')] = value.strip()
                else:
                    print("Error in line : %s" % l)
            else:
                # first line of array
                if not currarray:
                    currobject[name.strip().replace(' ', '_')] = currarray
                currarray.append(l.strip())
        new_section = False
    return result
예제 #3
0
def filecopyto(filename, target):
    """Copy file from absolute or package temporary directory to target directory

    If file is dll or exe, logs the original and new version.

    Args:
        filename (str): absolute path to file to copy,
                        or relative path to temporary package install content directory.

        target (str) : absolute path to target directory where to copy file.

        target is either a full filename or a directory name
        if filename is .exe or .dll, logger prints version numbers

    >>> if not os.path.isfile('c:/tmp/fc.test'):
    ...     with open('c:/tmp/fc.test','wb') as f:
    ...         f.write('test')
    >>> if not os.path.isdir('c:/tmp/target'):
    ...    os.mkdir('c:/tmp/target')
    >>> if os.path.isfile('c:/tmp/target/fc.test'):
    ...    os.unlink('c:/tmp/target/fc.test')
    >>> filecopyto('c:/tmp/fc.test','c:/tmp/target')
    >>> os.path.isfile('c:/tmp/target/fc.test')
    True
    """
    (dir, fn) = os.path.split(filename)
    if not dir:
        dir = os.getcwd()

    if os.path.isdir(target):
        target = os.path.join(target, os.path.basename(filename))
    if os.path.isfile(target):
        if os.path.splitext(target)[1] in ('.exe', '.dll'):
            try:
                ov = get_file_properties(target)['FileVersion']
                nv = get_file_properties(filename)['FileVersion']
                logger.info(u'Replacing %s (%s) -> %s' %
                            (ensure_unicode(target), ov, nv))
            except:
                logger.info(u'Replacing %s' % target)
        else:
            logger.info(u'Replacing %s' % target)
    else:
        if os.path.splitext(target)[1] in ('.exe', '.dll'):
            try:
                nv = get_file_properties(filename)['FileVersion']
                logger.info(u'Copying %s (%s)' % (ensure_unicode(target), nv))
            except:
                logger.info(u'Copying %s' % (ensure_unicode(target)))
        else:
            logger.info(u'Copying %s' % (ensure_unicode(target)))
    shutil.copy(filename, target)
예제 #4
0
def load_json(filenames=r'c:\tmp\*.json'):
    """Read a json host collection exported from wapt mongo and creates
            Wapt PG Host DB instances"""
    import glob
    convert_map = {
        'last_query_date':'last_seen_on',
        'update_status':'last_update_status',
        'softwares':'installed_softwares',
        'packages':'installed_packages',
        'wapt':'wapt_status',
        'host':'host_info',
    }
    for fn in glob.glob(filenames):
        print('Loading %s'%fn)
        recs = json.load(codecs.open(fn,'rb',encoding='utf8'))

        for rec in recs:
            computer_fqdn = rec['host']['computer_fqdn']
            uuid = rec['uuid']
            try:
                try:
                    # wapt update_status packages softwares host
                    newhost = Hosts()
                    for k in rec.keys():
                        if hasattr(newhost,convert_map.get(k,k)):
                            setattr(newhost,convert_map.get(k,k),rec[k])
                        else:
                            print '%s unknown key %s' % (computer_fqdn,k)

                    if 'host' in rec:
                        newhost.host_info = rec.get('host')

                    newhost.save(force_insert=True)
                    print('%s Inserted (%s)'%(newhost.computer_fqdn,newhost.uuid))
                except IntegrityError as e:
                    wapt_db.rollback()
                    updhost = Hosts.get(uuid=uuid)
                    for k in rec.keys():
                        if hasattr(updhost,convert_map.get(k,k)):
                            setattr(updhost,convert_map.get(k,k),rec[k])
                        else:
                            print '%s unknown key %s' % (computer_fqdn,k)
                    if 'host' in rec:
                        newhost.host_info = rec.get('host')
                    updhost.save()
                    print('%s Updated'%computer_fqdn)
            except Exception as e:
                print(u'Error for %s : %s'%(ensure_unicode(computer_fqdn),ensure_unicode(e)))
                wapt_db.rollback()
                raise e
예제 #5
0
파일: winsetup.py 프로젝트: tranquilit/WAPT
def migrate_pg_db(old_pgsql_root_dir,old_pgsql_data_dir,pgsql_root_dir,pgsql_data_dir):
    #
    try:
        cwd = os.getcwd()
        tmpdir = os.path.join(cwd,'temp')
        mkdir_p(tmpdir)
        os.chdir(tmpdir)
        setuphelpers.run(r'icacls "%s" /t /grant  "*S-1-1-0":(OI)(CI)(M)' % tmpdir)

        old_pgsql_root_dir = old_pgsql_root_dir.replace('\\','/')
        old_pgsql_data_dir = old_pgsql_data_dir.replace('\\','/')
        pgsql_root_dir = pgsql_root_dir.replace('\\','/')
        pgsql_data_dir = pgsql_data_dir.replace('\\','/')

        cmd = r'"{pgsql_root_dir}/bin/pg_upgrade.exe" -U postgres --old-datadir "{old_pgsql_data_dir}" --new-datadir "{pgsql_data_dir}" --old-bindir "{old_pgsql_root_dir}/bin" --new-bindir "{pgsql_root_dir}/bin"'.format(**locals())

        print('Running %s' % cmd)
        print(run(cmd,cwd=tmpdir))
        os.rename(old_pgsql_root_dir,old_pgsql_root_dir+'.old')
        os.rename(old_pgsql_data_dir,old_pgsql_data_dir+'.old')
        return True
    except Exception as e:
        print('Unable to migrate database : %s' % ensure_unicode(e))
        return False
    finally:
        os.chdir(cwd)
예제 #6
0
def user_local_appdata():
    r"""Return the local appdata profile of current user

    Returns:
        str: path like u'C:\\Users\\user\\AppData\\Local'
    """
    return ensure_unicode(makepath(os.environ['HOME'], '.config'))
예제 #7
0
def migrate_pg_db(old_pgsql_root_dir, old_pgsql_data_dir, pgsql_root_dir,
                  pgsql_data_dir):
    #
    try:
        cwd = os.getcwd()
        tmpdir = os.path.join(cwd, 'temp')
        mkdir_p(tmpdir)
        os.chdir(tmpdir)
        setuphelpers.run(r'icacls "%s" /t /grant  "*S-1-1-0":(OI)(CI)(M)' %
                         tmpdir)

        old_pgsql_root_dir = old_pgsql_root_dir.replace('\\', '/')
        old_pgsql_data_dir = old_pgsql_data_dir.replace('\\', '/')
        pgsql_root_dir = pgsql_root_dir.replace('\\', '/')
        pgsql_data_dir = pgsql_data_dir.replace('\\', '/')

        cmd = r'"{pgsql_root_dir}/bin/pg_upgrade.exe" -U postgres --old-datadir "{old_pgsql_data_dir}" --new-datadir "{pgsql_data_dir}" --old-bindir "{old_pgsql_root_dir}/bin" --new-bindir "{pgsql_root_dir}/bin"'.format(
            **locals())

        print('Running %s' % cmd)
        print(run(cmd, cwd=tmpdir))
        os.rename(old_pgsql_root_dir, old_pgsql_root_dir + '.old')
        os.rename(old_pgsql_data_dir, old_pgsql_data_dir + '.old')
        return True
    except Exception as e:
        print('Unable to migrate database : %s' % ensure_unicode(e))
        return False
    finally:
        os.chdir(cwd)
예제 #8
0
 def _run(self):
     """Launch an external 'wapt-get waptupgrade' process to upgrade local copy of wapt client"""
     from setuphelpers import run
     output = ensure_unicode(
         run('"%s" %s' %
             (os.path.join(wapt_root_dir, 'wapt-get.exe'), 'waptupgrade')))
     self.result = {'result': 'OK', 'message': output}
예제 #9
0
def host_info_common_unix():
    """Read main workstation informations, returned as a dict

    Returns:
        dict: main properties of host, networking and windows system

    .. versionchanged:: 1.4.1
         returned keys changed :
           dns_domain -> dnsdomain

    >>> hi = host_info()
    >>> 'computer_fqdn' in hi and 'connected_ips' in hi and 'computer_name' in hi and 'mac' in hi
    True
    """
    info = {}
    try:
        dmi = dmi_info()
        info['system_manufacturer'] = dmi['System_Information']['Manufacturer']
        info['system_productname'] = dmi['System_Information']['Product_Name']
    except:
        logger.warning(
            'Error while running dmidecode, dmidecode needs root privileges')
        pass

    info['computer_name'] = socket.gethostname()
    info['computer_fqdn'] = socket.getfqdn()
    info['dnsdomain'] = get_domain_from_socket()

    try:
        if os.path.isfile('/etc/samba/smb.conf'):
            config = configparser.RawConfigParser(strict=False)
            config.read('/etc/samba/smb.conf')
            if config.has_option('global', 'workgroup'):
                info['workgroup_name'] = config.get('global', 'workgroup')
    except:
        info['workgroup_name'] = ''

    info['connected_ips'] = get_local_IPs()

    list_mac = {}
    for c in networking():
        if 'mac' in c and 'addr' in c:
            for m in c['addr']:
                if m['addr'] in info['connected_ips']:
                    list_mac[c['mac']] = None

    info['networking'] = networking()
    info['gateways'] = [get_default_gateways()]
    info['dns_servers'] = get_dns_servers()
    info['mac'] = list(list_mac)
    info['kernel_version'] = get_kernel_version()
    #Fix for vscode don't know why it doesn't work : KeyError: 'brand'
    try:
        info['cpu_name'] = cpuinfo.get_cpu_info()['brand']
    except:
        pass
    info['environ'] = {k: ensure_unicode(v) for k, v in os.environ.items()}
    info['main_ip'] = get_main_ip()

    return info
예제 #10
0
 def run(self):
     while True:
         func, args, kargs = self.tasks.get()
         try:
             func(*args, **kargs)
         except Exception, e:
             logger.info(u"%s" % ensure_unicode(e))
         finally:
예제 #11
0
 def run(self):
     while True:
         func, args, kargs = self.tasks.get()
         try:
             func(*args, **kargs)
         except Exception, e:
             logger.info(u"%s" % ensure_unicode(e))
         finally:
예제 #12
0
 def _run(self):
     def cjoin(l):
         return u','.join([u'%s'%p for p in l])
     try:
         self.result = self.wapt.cleanup(obsolete_only=not self.force)
         self.summary = _(u"Packages erased : {}").format(cjoin(self.result))
     except Exception as e:
         self.result = {}
         self.summary = _(u"Error while clearing local cache : {}").format(ensure_unicode(e))
         raise Exception(self.summary)
예제 #13
0
 def worker(pipe, on_write=None):
     while True:
         line = pipe.readline()
         if not line:
             break
         else:
             if on_write:
                 on_write(ensure_unicode(line))
             if pipe == proc.stderr:
                 return_stderr.append(line)
             else:
                 output.append(line)
예제 #14
0
 def _run(self):
     if self.wapt.waptserver_available():
         print('Sending host status to server')
         try:
             self.result = self.wapt.update_server_status(force=self.force)
             self.summary = _(u'WAPT Server has been notified')
             print('Done.')
         except Exception as e:
             self.result = {}
             self.summary = _(u"Error while sending to the server : {}").format(ensure_unicode(e))
     else:
         self.result = {}
         self.summary = _(u'WAPT Server is not available')
예제 #15
0
 def _run(self):
     if self.wapt.waptserver_available():
         try:
             self.result = self.wapt.register_computer(
                 description=self.computer_description)
             self.summary = _(u"Inventory has been sent to the WAPT server")
         except Exception as e:
             self.result = {}
             self.summary = _(
                 u"Error while sending inventory to the server : {}"
             ).format(ensure_unicode(e))
             raise
     else:
         self.result = {}
         self.summary = _(u'WAPT Server is not available')
         raise Exception(self.summary)
예제 #16
0
 def as_dict(self):
     return copy.deepcopy(
         dict(
             id=self.id,
             classname=self.__class__.__name__,
             priority=self.priority,
             order=self.order,
             create_date=self.create_date and self.create_date.isoformat(),
             start_date=self.start_date and self.start_date.isoformat(),
             finish_date=self.finish_date and self.finish_date.isoformat(),
             logs=u'\n'.join([ensure_unicode(l) for l in self.logs]),
             result=common.jsondump(self.result),
             summary=self.summary,
             progress=self.progress,
             runstatus=self.runstatus,
             description=u"{}".format(self),
             pidlist=u"{0}".format(self.external_pids),
             notify_user=self.notify_user,
             notify_server_on_start=self.notify_server_on_start,
             notify_server_on_finish=self.notify_server_on_finish,
             created_by=self.created_by,
         ))
예제 #17
0
def get_current_user():
    r"""Get the login name for the current user.
    >>> get_current_user()
    u'htouvet'
    """
    return ensure_unicode(getpass.getuser())
예제 #18
0
def update_host_data(data):
    """Helper function to insert or update host data in db

    Args :
        data (dict) : data to push in DB with at least 'uuid' key
                        if uuid key already exists, update the data
                        eld insert
                      only keys in data are pushed to DB.
                        Other data (fields) are left untouched
    Returns:
        dict : with uuid,computer_fqdn,host_info from db after update
    """
    migrate_map_13_14 = {
        'packages': None,
        'installed_packages': None,
        'softwares': None,
        'installed_softwares': None,
        'update_status': 'last_update_status',
        'host': 'host_info',
        'wapt': 'wapt_status',
        'update_status': 'last_update_status',
    }

    uuid = data['uuid']
    try:
        existing = Hosts.select(
            Hosts.uuid, Hosts.computer_fqdn).where(Hosts.uuid == uuid).first()
        if not existing:
            logger.debug('Inserting new host %s with fields %s' %
                         (uuid, data.keys()))
            # wapt update_status packages softwares host
            newhost = Hosts()
            for k in data.keys():
                # manage field renaming between 1.3 and >= 1.4
                target_key = migrate_map_13_14.get(k, k)
                if target_key and hasattr(newhost, target_key):
                    set_host_field(newhost, target_key, data[k])

            newhost.save(force_insert=True)
        else:
            logger.debug('Updating %s for fields %s' % (uuid, data.keys()))

            updhost = Hosts.get(uuid=uuid)
            for k in data.keys():
                # manage field renaming between 1.3 and >= 1.4
                target_key = migrate_map_13_14.get(k, k)
                if target_key and hasattr(updhost, target_key):
                    set_host_field(updhost, target_key, data[k])
            updhost.save()

        # separate tables
        # we are tolerant on errors here a we don't know exactly if client send good encoded data
        # but we still want to get host in table
        try:
            if ('installed_softwares' in data) or ('softwares' in data):
                installed_softwares = data.get('installed_softwares',
                                               data.get('softwares', None))
                if not update_installed_softwares(uuid, installed_softwares):
                    logger.critical(
                        'Unable to update installed_softwares for %s' % uuid)
        except Exception as e:
            logger.critical(
                u'Unable to update installed_softwares for %s: %s' %
                (uuid, traceback.format_exc()))

        try:
            if ('installed_packages' in data) or ('packages' in data):
                installed_packages = data.get('installed_packages',
                                              data.get('packages', None))
                if not update_installed_packages(uuid, installed_packages):
                    logger.critical(
                        'Unable to update installed_packages for %s' % uuid)
        except Exception as e:
            logger.critical(u'Unable to update installed_packages for %s: %s' %
                            (uuid, traceback.format_exc()))

        result_query = Hosts.select(Hosts.uuid, Hosts.computer_fqdn)
        return result_query.where(Hosts.uuid == uuid).dicts().dicts().first(1)

    except Exception as e:
        logger.warning(traceback.format_exc())
        logger.critical(u'Error updating data for %s : %s' %
                        (uuid, ensure_unicode(e)))
        wapt_db.rollback()
        raise e
예제 #19
0
 def write(self, text):
     '''Logs written output to listeners'''
     if text and text != '\n':
         if self.events:
             self.events.post_event('PRINT',ensure_unicode(text))
         self.logs.append(ensure_unicode(text))
예제 #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)
예제 #21
0
def get_fqdn():
    return ensure_unicode(
        get_hostname()) if os.name == 'nt' else ensure_unicode(
            socket.getfqdn())
예제 #22
0
def copytree2(src,
              dst,
              ignore=None,
              onreplace=default_skip,
              oncopy=default_oncopy,
              enable_replace_at_reboot=True):
    r"""Copy src directory to dst directory. dst is created if it doesn't exists
    src can be relative to installation temporary dir

    oncopy is called for each file copy. if False is returned, copy is skipped
    onreplace is called when a file will be overwritten.

    Args:
        src (str): path to source directory (absolute path or relative to package extraction tempdir)
        dst (str): path to target directory (created if not present)
        ignore (func) : callback func(root_dir,filenames) which returns names to ignore
        onreplace (func) : callback func(src,dst):boolean called when a file will be replaced to decide what to do.
                        default is to not replace if target exists. can be default_overwrite or default_overwrite_older or
                        custom function.
        oncopy (func) : callback func(msg,src,dst) called when a file is copied.
                        default is to log in debug level the operation
        enable_replace_at_reboot (boolean): if True, files which are locked will be scheduled for replace at next reboot

    Returns:

    Raises:

    >>> copytree2(r'c:\tranquilit\wapt\tests',r'c:\tranquilit\wapt\tests2')
    >>> isdir(r'c:\tranquilit\wapt\tests2')
    True
    >>> remove_tree(r'c:\tranquilit\wapt\tests2')
    >>> isdir(r'c:\tranquilit\wapt\tests2')
    False
    """
    logger.debug('Copy tree from "%s" to "%s"' %
                 (ensure_unicode(src), ensure_unicode(dst)))
    # path relative to temp directory...
    tempdir = os.getcwd()
    if not os.path.isdir(src) and os.path.isdir(os.path.join(tempdir, src)):
        src = os.path.join(tempdir, src)

    names = os.listdir(src)
    if ignore is not None:
        ignored_names = ignore(src, names)
    else:
        ignored_names = set()

    if not os.path.isdir(dst):
        if oncopy('create directory', src, dst):
            os.makedirs(dst)
    errors = []
    skipped = []
    for name in names:
        if name in ignored_names:
            continue
        srcname = os.path.join(src, name)
        dstname = os.path.join(dst, name)
        try:
            if os.path.isdir(srcname):
                if oncopy('directory', srcname, dstname):
                    copytree2(srcname,
                              dstname,
                              ignore=ignore,
                              onreplace=onreplace,
                              oncopy=oncopy)
            else:
                try:
                    if os.path.isfile(dstname):
                        if onreplace(srcname, dstname) and oncopy(
                                'overwrites', srcname, dstname):
                            os.unlink(dstname)
                            shutil.copy2(srcname, dstname)
                    else:
                        if oncopy('copy', srcname, dstname):
                            shutil.copy2(srcname, dstname)
                except (IOError, os.error) as e:
                    # file is locked...
                    if enable_replace_at_reboot and e.errno in (5, 13):
                        filecopyto(srcname, dstname + '.pending')
                        replace_at_next_reboot(tmp_filename=dstname +
                                               '.pending',
                                               target_filename=dstname)
                    else:
                        raise

        except (IOError, os.error) as why:
            logger.critical(u'Error copying from "%s" to "%s" : %s' %
                            (ensure_unicode(src), ensure_unicode(dst),
                             ensure_unicode(why)))
            errors.append((srcname, dstname, str(why)))
        # catch the Error from the recursive copytree so that we can
        # continue with other files
        except shutil.Error as err:
            #errors.extend(err.args[0])
            errors.append(err)
    try:
        shutil.copystat(src, dst)
    except WindowsError:
        # can't copy file access times on Windows
        pass
    except OSError as why:
        errors.extend((src, dst, str(why)))
    if errors:
        raise shutil.Error(errors)
예제 #23
0
def default_oncopy(msg, src, dst):
    logger.debug(
        u'%s : "%s" to "%s"' %
        (ensure_unicode(msg), ensure_unicode(src), ensure_unicode(dst)))
    return True
예제 #24
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)
예제 #25
0
 def cjoin(l):
     return u','.join([u'%s' % ensure_unicode(p) for p in l])
예제 #26
0
def run(cmd,
        shell=True,
        timeout=600,
        accept_returncodes=[0, 3010],
        on_write=None,
        pidlist=None,
        return_stderr=True,
        **kwargs):
    r"""Run the command cmd in a shell and return the output and error text as string

    Args:
        cmd : command and arguments, either as a string or as a list of arguments
        shell (boolean) : True is assumed
        timeout (int) : maximum time to wait for cmd completion is second (default = 600)
                        a TimeoutExpired exception is raised if tiemout is reached.
        on_write : callback when a new line is printed on stdout or stderr by the subprocess
                        func(unicode_line). arg is enforced to unicode
        accept_returncodes (list) : list of return code which are considered OK default = (0,1601)
        pidlist (list): external list where to append the pid of the launched process.
        return_stderr (bool or list) : if True, the error lines are returned to caller in result.
                                       if a list is provided, the error lines are appended to this list

        all other parameters from the psutil.Popen constructor are accepted

    Returns:
        RunOutput : bytes like output of stdout and optionnaly stderr streams.
                    returncode attribute

    Raises:
        CalledProcessError: if return code of cmd is not in accept_returncodes list
        TimeoutExpired:  if process is running for more than timeout time.

    .. versionchanged:: 1.3.9
            return_stderr parameters to disable stderr or get it in a separate list
            return value has a returncode attribute to

    .. versionchanged:: 1.4.0
            output is not forced to unicode

    .. versionchanged:: 1.4.1
          error code 1603 is no longer accepted by default.

    .. versionchanged:: 1.5.1
          If cmd is unicode, encode it to default filesystem encoding before
            running it.

    >>> run(r'dir /B c:\windows\explorer.exe')
    'explorer.exe\r\n'

    >>> out = []
    >>> pids = []
    >>> def getlines(line):
    ...    out.append(line)
    >>> run(r'dir /B c:\windows\explorer.exe',pidlist=pids,on_write=getlines)
    u'explorer.exe\r\n'

    >>> print out
    ['explorer.exe\r\n']
    >>> try:
    ...     run(r'ping /t 127.0.0.1',timeout=3)
    ... except TimeoutExpired:
    ...     print('timeout')
    timeout
    """
    logger.info(u'Run "%s"' % (ensure_unicode(cmd), ))
    output = []

    if return_stderr is None or return_stderr == False:
        return_stderr = []
    elif not isinstance(return_stderr, list):
        return_stderr = output

    if pidlist is None:
        pidlist = []

    # unicode cmd is not understood by shell system anyway...
    if isinstance(cmd, unicode):
        cmd = cmd.encode(sys.getfilesystemencoding())

    try:
        proc = psutil.Popen(cmd,
                            shell=shell,
                            bufsize=1,
                            stdin=PIPE,
                            stdout=PIPE,
                            stderr=PIPE,
                            **kwargs)
    except RuntimeError as e:
        # be sure to not trigger encoding errors.
        raise RuntimeError(e[0], repr(e[1]))
    # keep track of launched pid if required by providing a pidlist argument to run
    if not proc.pid in pidlist:
        pidlist.append(proc.pid)

    def worker(pipe, on_write=None):
        while True:
            line = pipe.readline()
            if not line:
                break
            else:
                if on_write:
                    on_write(ensure_unicode(line))
                if pipe == proc.stderr:
                    return_stderr.append(line)
                else:
                    output.append(line)

    stdout_worker = RunReader(worker, proc.stdout, on_write)
    stderr_worker = RunReader(worker, proc.stderr, on_write)
    stdout_worker.start()
    stderr_worker.start()
    stdout_worker.join(timeout)
    if stdout_worker.is_alive():
        # kill the task and all subtasks
        if proc.pid in pidlist:
            pidlist.remove(proc.pid)
            killtree(proc.pid)
        raise TimeoutExpired(cmd, ''.join(output), timeout)
    stderr_worker.join(timeout)
    if stderr_worker.is_alive():
        if proc.pid in pidlist:
            pidlist.remove(proc.pid)
            killtree(proc.pid)
        raise TimeoutExpired(cmd, ''.join(output), timeout)
    proc.returncode = proc.wait()
    if proc.pid in pidlist:
        pidlist.remove(proc.pid)
        killtree(proc.pid)
    if accept_returncodes is not None and not proc.returncode in accept_returncodes:
        if return_stderr != output:
            raise CalledProcessErrorOutput(proc.returncode, cmd,
                                           ''.join(output + return_stderr))
        else:
            raise CalledProcessErrorOutput(proc.returncode, cmd,
                                           ''.join(output))
    else:
        if proc.returncode == 0:
            logger.info(u'%s command returns code %s' %
                        (ensure_unicode(cmd), proc.returncode))
        else:
            logger.warning(u'%s command returns code %s' %
                           (ensure_unicode(cmd), proc.returncode))
    result = RunOutput(output)
    result.returncode = proc.returncode
    return result
예제 #27
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)
예제 #28
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)