#
#coding:utf-8
#
#Author  : QCSun
#Email   : qcsun@sunhpc.com
#Times   : 2023-04-14 05:21:02
#WebSite : https://www.sunhpc.com

import os
import sys
import time
import socket
import sunhpc
import random
import argparse
from sunhpc.db.mappings.base import *

class command(sunhpc.commands.build.command):
    pass

class Command(command):
    """
    Initialzed the sunhpc database.
    """
    def run(self, params, args):

        '''
        pars = argparse.ArgumentParser(description="Initialzed the sunhpc database")
        pars.add_argument('-c', dest='config', metavar='config', default='/opt/sunhpc', help='use config file')
        argv = pars.parse_args(args=args)
        '''

        ap = self.ap.handler()
        op = self.ap.add_group('Configure')
        op.add_argument(
                '-c', '--config', metavar='config', action='store', 
                default='/opt/sunhpc/etc/sunhpc.conf', 
                help='Use config file'
                )
        op.add_argument(
                '-f', '--force', action='store_true',
                default=False, 
                help='Force reinitialzed sunhpc database file.'
                )

        argv = ap.parse_args(args)

        #self.setdebug(True)

        lock = os.path.join(self.newdb._dbPath, self.newdb._dbLock)
        self.init_tables(lock)

        # get cluster config file
        results = self.init_config(argv)

        # Return sql initialze data query list.
        query = self.init_database(results)

        # Add data to database.
        for i in query:
            if self.debug:
                print (i)
            self.db.execute(i)

        #[self.db.execute(d) for d in query]

        #print (session)

    def init_tables(self, lock):
        """create the database file"""
        print ('Starting initialzed the sunhpc database ...')
        if os.path.exists(lock):
            with open(lock, 'r') as f:
                data = f.readline()

            self.abort('Error - In %s date. The sunhpc database has been initialized to be complete.' % data)
        else:
            # Use sqlalchemy initialze the database.
            #Base.metadata.create_all(self.newdb.engine)

            # Use sqlite initialze the database
            for i in self.baseTables():
                if self.debug:
                    print (i)
                self.db.execute(i)

            current_time = int(time.time())
            localtime    = time.localtime(current_time)
            today        = time.strftime('%Y-%m-%d %H:%M:%S', localtime)
            with open(lock, 'w') as f:
                f.write('%s\n' % today)

    def askResponse(self, key, conf, ask, default=None):
        # key: publichostname conf: config file
        # ask: 提示信息, default:默认值.

        if key in conf:
            return conf[key]

        tmp = None
        if isinstance(default, type([])) or isinstance(default, type(())):
            while tmp not in default:
                tmp = input('Please input \033[1;93m%s\033[0m default[ "\033[1;31m%s\033[0m" ]: ' % (ask, ','.join(default)))
        else:
            while not tmp:
                tmp = input('Please input \033[1;93m%s\033[0m default[ "\033[1;31m%s\033[0m" ]: ' % (ask, default)) or default

        return tmp

    def init_config(self, args):

        confs   = {}
        results = {}

        # 读取配置文件中信息.
        if os.path.exists(args.config):
            with open(args.config, 'r') as f:
                for i in f.readlines():
                    r = i.split()
                    if i.startswith('#') or len(r) < 2:
                        continue

                    key, val = r[0], ' '.join(r[1:])
                    confs[key.lower()] = val

        results['country']   = self.askResponse('country',   confs, 'Country code', 'CN')
        results['state']     = self.askResponse('state',     confs, 'State name', 'LiaoNing')
        results['city']  = self.askResponse('city',  confs, 'Locality name', 'DaLian')
        results['url']       = 'https://www.sunhpc.com'
        results['name']      = 'Sunhpc-cluster'
        results['contact']   = 'info@sunhpc.com'
        results['worksdir']  = '/export'
        results['distrodir'] = '/export/sunhpc'
        results['partition'] = 'default'

        # safe security 
        results['safeport']     = '372'
        results['safedirs']     = 'safe.d'
        results['safesecurity'] = 'safe-security'

        try:
            # Hostname = socket.getfqdn(socket.gethostname())
            devices = self.getNetcard()
            interface = list(devices.keys())

            results['publichostname']  = self.askResponse('publichostname', confs, 'PublicHostname', 'cluster.sunhpc.com')
            results['publicinterface'] = self.askResponse('publicinterface', confs, 'PublicInterface', interface)

            wan_dev = results['publicinterface']
            results['publicaddress'] = self.askResponse('publicaddress', confs, 'PublicAddress %s' % wan_dev, devices[wan_dev])

            try:
                gwaddr = devices[wan_dev].split('.')[:-1]
                gwaddr.append('1')
                gwaddr = "%s" % '.'.join(gwaddr)
            except (KeyError, IndexError):
                gwaddr = devices[wan_dev]

            results['publicgateway'] = self.askResponse(
                    'publicgateway', confs, 'PublicGateway (%s:%s)' % (wan_dev, gwaddr), gwaddr)

            results['publicnetmask'] = self.askResponse(
                    'publicnetmask', confs, 'PublicNetmask (%s:%s)' % (wan_dev, devices[wan_dev]), '255.255.255.0')

            results['publicdnsserver'] = self.askResponse('publicdnsserver', confs, 'PublicDNSServer', '223.5.5.5')

            wan_mac  = os.popen("nmcli device show %s|grep -i general.hwaddr|awk '{print $2}'" % wan_dev).readline().strip()
            results['publicmacaddress'] = self.askResponse('publicmacaddr', confs, 'PublicMACAddress', wan_mac)

            wan_cidr = self.net.netmask_to_cidr(results['publicnetmask'])
            results['publiccidr'] = self.askResponse('publiccidr', confs, 'PublicCIDR', wan_cidr)

            wan_network = self.net.getNetwork(results['publicaddress'], results['publicnetmask'])
            results['publicnetwork'] = self.askResponse('publicnetwork', confs, 'PublicNetwork', wan_network)

            results['publicdomain']  = 'sunhpc.com'
            results['publicmtu']     = '1500'
            results['publicntphost'] = 'pool.ntp.org'


            # private network configure
            results['privatehostname'] = self.askResponse('privatehostname', confs, 'PrivateHostname', 'cluster')

            interface.remove(results['publicinterface'])
            if len(interface) == 1:
                interface = interface[0]
            results['privateinterface'] = self.askResponse('privateinterface', confs, 'PrivateInterface', interface)

            lan_dev = results['privateinterface']
            results['privateaddress'] = self.askResponse(
                    'privateaddress', confs, 'PrivateAddress %s' % lan_dev, devices[lan_dev])

            results['privatenetmask'] = self.askResponse(
                    'privatenetmask', confs, 'PrivateNetmask (%s:%s)' % (lan_dev, devices[lan_dev]), '255.255.255.0')

            lan_mac = os.popen("nmcli device show %s|grep -i general.hwaddr|awk '{print $2}'" % lan_dev).readline().strip()
            results['privatemacaddress'] = self.askResponse(
                    'privateMacAddress', confs, 'PrivateMacAddress (%s:%s)' % (lan_dev, devices[lan_dev]), lan_mac)

            lan_cidr = self.net.netmask_to_cidr(results['privatenetmask'])
            results['privatecidr'] = self.askResponse(
                    'privatecidr', confs, 'PrivateCIDR (%s:%s)' % (lan_dev, results['privatenetmask']), lan_cidr)

            lan_network = self.net.getNetwork(results['privateaddress'], results['privatenetmask'])
            results['privatenetwork'] = self.askResponse('privatenetwork', confs, 
                'PrivateNetwork (%s:%s/%s)' % (lan_dev, results['privateaddress'], results['privatenetmask']), lan_network)

            results['privatedomain'] = self.askResponse('privatednsdomain', confs, 'PrivateDomain', 'local')
            results['privatemtu'] = self.askResponse('privatemtu', confs, 'PrivateMTU', '1500')

            domain = '%s.%s' % (results['privatehostname'], results['privatedomain'])
            results['privatentphost'] = self.askResponse('privatentphost', confs, 'PrivateNTPHost', domain)

        except KeyError as e:
            self.msg("The %s config file error. Field -> *" % conf, 'a', e.args)

        results['timezone'] = self.askResponse('timezone', confs, 'Time zone', 'Asia/Shanghai')

        results['bootargs']     = 'net.ifnames=0 biosdevname=0 ksdevice=bootif'
        results['basedir']      = 'install'
        results['ganglia']      = '224.0.0.3'
        results['nextserver']   = results['privateaddress']
        results['plugin_port']  = '12345'
        results['pxefilename']  = 'pxelinux.0'
        results['pxelinuxdir']  = '/tftpboot/pxelinux'
        results['distribution'] = 'sunhpc-dist'

        self.dictOutput(results)

        tmp = ''
        commands = ['s', 'save', 'q', 'quit', 'e', 'exit']
        while tmp not in commands:
            print ('--------------------------------------------------')
            print ('\ts/save   : Save vars to %s, database and quit' % args.config)
            print ('\tq/quit   : Quit the and not save')
            print ('\tModify key=value e.g,. plugin_port=2222')
            tmp = input('Please input command: ').lower()
            value = tmp.split('=', 1)
            if len(value) == 2 and value[0] in results:
                results[value[0]] = value[1]
                self.dictOutput(results)

        if tmp in ['s', 'save']:
            with open(args.config, 'w') as f:
                f.write('#\n# sunhpc cluster config file.\n#\n')
                for k in results:
                    value = "%s    %s\n" % (k.lower(), results[k])
                    f.write(value)
            self.msg('Has been written to the configuration file %s' % args.config)

        return results

    def init_database(self, results):
        queuelist   = []

        category    = [
                "insert into categories values (1, 'global', 'Global Default')",
                "insert into categories values (2, 'os', 'OS System name')",
                "insert into categories values (3, 'appliance', 'Logical appliances')",
                "insert into categories values (4, 'rack', 'Machine room racks')",
                "insert into categories values (5, 'host', 'Physical and virtual')"
                ]
        queuelist.extend(category)

        catindex    = [
                "insert into catindex values (1, 'global', 1)",
                "insert into catindex values (2, 'linux', 2)",
                "insert into catindex values (3, 'other', 2)",
                "insert into catindex values (4, 'frontend', 3)",
                "insert into catindex values (5, 'compute', 3)",
                "insert into catindex values (6, 'nas', 3)",
                "insert into catindex values (7, 'network', 3)",
                "insert into catindex values (8, 'power', 3)",
                "insert into catindex values (9, 'devel-server', 3)",
                "insert into catindex values (10, 'login', 3)"
                ]
        queuelist.extend(catindex)

        bootver     = '%s-%s' % (sunhpc.version, self.arch)
        vmlinuz     = 'vmlinuz-%s' % bootver
        initrds     = 'initrd-%s'  % bootver
        defArgs     = "net.ifnames=0 biosdevname=0"
        insArgs     = "%s inst.ks.sendmac ksdevice=bootif" % (defArgs)
        resArgs     = "%s rescue" % defArgs
        lesArgs     = "%s vnc"    % defArgs
        bootaction  = [ 
                "insert into bootactions values (1, 'install', '%s', '%s', '%s')" % (vmlinuz, initrds, insArgs),
                "insert into bootactions values (2, 'os', 'localboot 0', NULL, NULL)",
                "insert into bootactions values (3, 'memtest', 'kernel memtest', NULL, NULL)",
                "insert into bootactions values (4, 'install headless', '%s', '%s', '%s')" % (vmlinuz, initrds, lesArgs),
                "insert into bootactions values (5, 'rescue', '%s', '%s', '%s')" % (vmlinuz, initrds, resArgs),
                "insert into bootactions values (6, 'pxeflash', 'kernel memdisk bigraw', 'pxeflash.img', 'keeppxe')"]

        queuelist.extend(bootaction)

        cmds    = "dmidecode -t memory|sed s/[[:space:]]//g|grep '^Size'|grep -E 'MB|GB'"
        Names   = os.popen("cat /sys/class/dmi/id/product_name").readline().strip()
        Vender  = os.popen("cat /sys/class/dmi/id/sys_vendor").readline().strip()
        Serial  = os.popen("cat /sys/class/dmi/id/product_serial").readline().strip()
        CPUs    = os.popen("dmidecode -t processor|grep Version|cut -d ':' -f2|wc -l").readline().strip()
        Core    = os.popen("cat /proc/cpuinfo |grep processor|wc -l").readline().strip()
        Model   = os.popen("dmidecode -t processor|grep Version|head -n1|cut -d ':' -f2").readline().strip()
        MemNumb = os.popen("%s|wc -l" % cmds).readline().strip()
        MemSize = os.popen("%s|head -n1|cut -d ':' -f2" % cmds).readline().strip()

        part        = sunhpc.core.partition.Partition()
        part.discoveredDisks()
        disks       = part.getDisks()
        nodeDisks   = part.getNodePartInfo(disks)
        disklist    = sorted(nodeDisks)
        for disk in disklist:
            for d in nodeDisks[disk]:
                dev, sec, size, partid, fstype, bootflags, partflags, mountpoint = d
                if dev and sec and size:
                    queuelist.append('''
                insert into partitions(
            node, device, mountpoint, sectorstart, partitionsize, fstype, partitionflags, formatflags) values 
                (1, "%s", "%s", "%s" ,"%s", "%s", "%s", "%s")''' % (
            dev, mountpoint, sec, size, fstype, bootflags, partflags))

        for attr in self.attributions(results):
            k, v, s, n = attr
            queuelist.append('insert into attributes values (NULL, "%s","%s", NULL, "%s", %d)' % (k, v, s, n))

        # add frontend node
        lhostname = results['privatehostname']
        nodes = [ "insert into nodes values (1, '%s', %d, 0, 0, '%s', '%s', '', 'install')" \
                    % (lhostname, int(Core), self.arch, self.os)]
        queuelist.extend(nodes)

        # add frontend network
        network = [ "insert into networks values (1, 1, '%s', '%s', '%s', '%s', '2')" % 
                        (results['publicmacaddress'], results['publicaddress'], lhostname, results['publicinterface']),
                    "insert into networks values (2, 1, '%s', '%s', '%s', '%s', '1')" % 
                        (results['privatemacaddress'], results['privateaddress'], lhostname, results['privateinterface'])]
        queuelist.extend(network)

        # add subnet data
        subnet = [ "insert into subnets values (1, 'private', '%s', '%s', '%s', '%s', '1')" % 
                        (results['privatedomain'], results['privatenetwork'], 
                        results['privatenetmask'], results['privatemtu']),
                   "insert into subnets values (2, 'public', '%s', '%s', '%s', '%s', '0')" % 
                        (results['publicdomain'], results['publicnetwork'], 
                        results['publicnetmask'], results['publicmtu'])]
        queuelist.extend(subnet)
        return queuelist
    
    def attributions(self, results):

        attrs = [
                ('Info_CertificateCountry',     results['country'],             1, 1),
                ('Info_CertificateState',       results['state'],               1, 1),
                ('Info_CertificateLocality',    results['city'],                1, 1),
                ('Info_CertificateOrganization','DLHP',                         1, 1),
                ('Info_ClusterUrl',             results['url'],                 1, 1),
                ('Info_ClusterName',            results['name'],                1, 1),
                ('Info_ClusterContact',         results['contact'],             1, 1),
                ('Kickstart_WorksDir',          results['worksdir'],            1, 1),
                ('Kickstart_DistroDir',         results['distrodir'],           1, 1),
                ('Kickstart_Partition',         results['partition'],           1, 1),

                ('Kickstart_PublicHostname',    results['publichostname'],      1, 1),
                ('Kickstart_PublicInterface',   results['publicinterface'],     1, 1),
                ('Kickstart_PublicAddress',     results['publicaddress'],       1, 1),
                ('Kickstart_PublicMacAddr',     results['publicmacaddress'],    1, 1),
                ('Kickstart_PublicNetmask',     results['publicnetmask'],       1, 1),
                ('Kickstart_PublicNetmaskCIDR', results['publiccidr'],          1, 1),
                ('Kickstart_PublicGateway',     results['publicgateway'],       1, 1),
                ('Kickstart_PublicNetwork',     results['publicnetwork'],       1, 1),
                ('Kickstart_PublicNTPHost',     results['publicntphost'],       1, 1),
                ('Kickstart_PublicDNSServer',   results['publicdnsserver'],     1, 1),
                ('Kickstart_PublicDomain',      results['publicdomain'],        1, 1),
                ('Kickstart_PublicMTU',         results['publicmtu'],           1, 1),

                ('Kickstart_PrivateHostname',   results['privatehostname'],     1, 1),
                ('Kickstart_PrivateInterface',  results['privateinterface'],    1, 1),
                ('Kickstart_PrivateAddress',    results['privateaddress'],      1, 1),
                ('Kickstart_PrivateMacAddr',    results['privatemacaddress'],   1, 1),
                ('Kickstart_PrivateNetmask',    results['privatenetmask'],      1, 1),
                ('Kickstart_PrivateNetmaskCIDR',results['privatecidr'],         1, 1),
                ('Kickstart_PrivateGateway',    results['privateaddress'],      1, 1),
                ('Kickstart_PrivateNetwork',    results['privatenetwork'],      1, 1),
                ('Kickstart_PrivateNTPHost',    results['privatentphost'],      1, 1),
                ('Kickstart_PrivateDNSServer',  results['privateaddress'],      1, 1),
                ('Kickstart_PrivateDomain',     results['privatedomain'],       1, 1),
                ('Kickstart_PrivateMTU',        results['privatemtu'],          1, 1),

                ('Kickstart_Plugin_Port',       results['plugin_port'],         1, 1),
                ('Kickstart_Plugin_Keys',       self.daemon_pass(),             1, 1),

                ('Kickstart_Timezone',          results['timezone'],            1, 1),
                ('Kickstart_Bootargs',          results['bootargs'],            1, 1),
                ('distribution',                results['distribution'],        1, 1),
                ('Kickstart_BaseDir',           results['basedir'],             1, 1),

                ('safeport',                    results['safeport'],            1, 1),
                ('safedirs',                    results['safedirs'],            1, 1),
                ('safesecurity',                results['safesecurity'],        1, 1),

                ('sunhpc_version',              sunhpc.version,                 1, 1),
                ('sunhpc_major',                self.major,                     1, 1),
                ('sunhpc_minor',                self.minor,                     1, 1),
                ('sunhpc_micro',                self.micro,                     1, 1),
                ('sunhpc_release',              sunhpc.release,                 1, 1),
                ('ganglia_address',             results['ganglia'],             1, 1),

                ('dhcp_filename',               results['pxefilename'],         1, 1),
                ('dhcp_nextserver',             results['nextserver'],          1, 1),
                ('pxelinuxdir',                 results['pxelinuxdir'],         1, 1),

                ('kickstartable',               'yes',                          3, 4),
                ('kickstartable',               'yes',                          3, 5),
                ('kickstartable',               'yes',                          3, 6),
                ('kickstartable',               'no',                           3, 7),
                ('kickstartable',               'no',                           3, 8),
                ('kickstartable',               'yes',                          3, 9),
                ('kickstartable',               'yes',                          3, 10),

                ('managed',                     'true',                         1, 1),
                ('os',                          'linux',                        1, 1)
                ]
        return attrs

    def baseTables(self):
        """Base data tables"""

        drop    = 'DROP TABLE IF EXISTS tablename'
        tables  = ['Nodes', 'Networks', 'Subnets', 'PublicKeys', 'SecNodes', 
                   'Attributes', 'Partitions', 'Categories', 'Catindex',
                   'Rolls', 'Bootactions', 'distributions', 
                   'SecGlobals'
                  ]
        datalist = []

        Categories = '''
        CREATE TABLE Categories (
            ID          integer primary key autoincrement,
            Name        varchar(64) NOT NULL unique default '0',
            Description varchar(512) default null
        )'''
        datalist.append(Categories)

        Catindex = '''
        CREATE TABLE Catindex (
            ID          integer primary key autoincrement,
            Name        varchar(64) not null default '0',
            Category    integer not null,
            Foreign key(Category) references categories(ID) on delete cascade on update restrict
        )'''
        datalist.append(Catindex)

        Nodes = '''
        CREATE TABLE Nodes (
            ID            integer primary key autoincrement,
            Name          varchar(128) default NULL,
            CPUs          integer(11) NOT NULL default '1',
            Rack          integer(11) default NULL,
            Rank          integer(11) default NULL,
            Arch          varchar(32) default NULL,
            OS            varchar(64) NOT NULL default 'linux',
            Alias         varchar(64) default '',
            Status        varchar(32) default 'os'
        )'''
        datalist.append(Nodes)

        Networks = '''
        CREATE TABLE Networks (
            ID        integer NOT NULL primary key autoincrement,
            Node      integer(11) default NULL,
            MAC       varchar(64) default NULL,
            IP        varchar(32) default NULL,
            Name      varchar(128) default NULL,
            Device    varchar(32) default NULL,
            Subnet    integer(11) default NULL,
            Foreign key(subnet) references subnets(id) on delete cascade on update restrict,
            Foreign key(node) references nodes(id) on delete cascade on update restrict
        )'''
        datalist.append(Networks)

        Subnets = '''
        CREATE TABLE Subnets (
            ID          integer NOT NULL primary key autoincrement,
            name        varchar(32) UNIQUE NOT NULL,
            dnszone     varchar(64) UNIQUE NOT NULL ,
            subnet      varchar(32) NOT NULL,
            netmask     varchar(32) NOT NULL,
            mtu         integer(11) default '1500',
            servedns    boolean     default false
        )'''
        datalist.append(Subnets)

        PublicKeys = '''
        CREATE TABLE PublicKeys (
            ID             integer NOT NULL primary key autoincrement,
            Public_Key     varchar(4096) default NULL,
            Description    varchar(4096) default NULL,
            Node           integer(11) NOT NULL default '0',
            Foreign key(Node) references nodes(id) on delete cascade on update restrict
        )'''
        datalist.append(PublicKeys)

        SecNodes = '''
        CREATE TABLE SecNodes (
            Attr      varchar(128) default NULL,
            Enc       varchar(64) default NULL,
            Value     text,
            Node      integer(11) NOT NULL default '0',
            PRIMARY KEY (Node, Attr)
        )'''
        datalist.append(SecNodes)

        Attributes = '''
        CREATE TABLE Attributes (
            ID      integer NOT NULL primary key autoincrement,
            Attr    varchar(128) NOT NULL,
            Value   text,
            Shadow  text,
            Category int(11) NOT NULL,
            Catindex int(11) NOT NULL,
            Foreign key(Catindex) references catindex(id) on delete cascade on update restrict
        )'''
        datalist.append(Attributes)

        Partitions = '''
        CREATE TABLE Partitions (
            ID              integer NOT NULL primary key autoincrement,
            Node            integer(11)  NOT NULL default '0',
            Device          varchar(128) NOT NULL default '',
            Mountpoint      varchar(128) NOT NULL default '',
            SectorStart     varchar(128) NOT NULL default '',
            PartitionSize   varchar(128) NOT NULL default '',
            PartitionID     varchar(128) NOT NULL default '',
            FsType          varchar(128) NOT NULL default '',
            PartitionFlags  varchar(128) NOT NULL default '',
            FormatFlags     varchar(128) NOT NULL default ''
        )'''
        datalist.append(Partitions)

        Firewalls = '''
        CREATE TABLE Firewalls (
            ID          integer NOT NULL primary key autoincrement,
            Rulename    varchar(128) NOT NULL,
            Service     varchar(256),
            Protocol    varchar(256),
            Ports       varchar(256),
            Action      varchar(256),
            Comment     varchar(256),
            Node        integer(11)  NOT NULL default '0'
        )'''
        datalist.append(Firewalls)

        Rolls = '''
        CREATE TABLE Rolls (
            ID        integer NOT NULL primary key autoincrement,
            Name      varchar(128) NOT NULL default '',
            Version   varchar(32)  NOT NULL default '',
            Arch      varchar(32)  NOT NULL default '',
            OS        varchar(64)  NOT NULL default 'linux',
            Enabled   varchar(11)  NOT NULL default 'yes'
        )'''
        datalist.append(Rolls)

        Bootactions = '''
        CREATE TABLE Bootactions (
            ID        integer NOT NULL primary key autoincrement,
            Action    varchar(1024) default NULL,
            Kernel    varchar(1024) default NULL,
            Ramdisk   varchar(1024) default NULL,
            Args      varchar(1024) default NULL
        )'''
        datalist.append(Bootactions)

        Distributions = '''
        CREATE TABLE Distributions (
            ID        integer NOT NULL primary key autoincrement,
            Name      varchar(32) NOT NULL default '',
            OS        varchar(32) default '',
            Release   varchar(32) default ''
        )'''
        datalist.append(Distributions)

        SecGlobals = '''
        CREATE TABLE SecGlobals (
            Attr          varchar(128) default NULL,
            Value         text,
            Enc           varchar(128) default NULL,
            PRIMARY KEY (Attr)
        )'''
        datalist.append(SecGlobals)

        return datalist

    def daemon_pass(self):
        char  = 'abcdefghijklmnopqrstuvwxyz'
        char += '!@#$%+=-_^&*.?'
        char += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
        return ''.join(random.sample(char,16))



                























