#!/usr/bin/python3
#-*- coding: UTF-8 -*-
# ver 0.3

from subprocess import Popen, PIPE, STDOUT, call
import io
import re
import os
import gi
import socket
import configparser
import threading
gi.require_version('Gtk', '3.0')
from gi.repository import Gdk, Gtk, GObject

class MessageDialogWindow(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="MessageDialog Example")

        box = Gtk.Box(spacing=6)
        self.add(box)

        button1 = Gtk.Button("Information")
        button1.connect("clicked", self.on_info_clicked)
        box.add(button1)

        button2 = Gtk.Button("Error")
        button2.connect("clicked", self.on_error_clicked)
        box.add(button2)

        button3 = Gtk.Button("Warning")
        button3.connect("clicked", self.on_warn_clicked)
        box.add(button3)

        button4 = Gtk.Button("Question")
        button4.connect("clicked", self.on_question_clicked)
        box.add(button4)

    def on_info_clicked(self, info):
        dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.INFO,
            Gtk.ButtonsType.OK, "Информация")
        dialog.format_secondary_text(info)
        dialog.run()

        dialog.destroy()

    def on_error_clicked(self, error):
        dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.ERROR,
            Gtk.ButtonsType.CANCEL, "Ошибка!")
        dialog.format_secondary_text(
            error)
        dialog.run()

        dialog.destroy()

    def on_warn_clicked(self, widget):
        dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.WARNING,
            Gtk.ButtonsType.OK_CANCEL, "This is an WARNING MessageDialog")
        dialog.format_secondary_text(
            "And this is the secondary text that explains things.")
        response = dialog.run()
        if response == Gtk.ResponseType.OK:
            print("WARN dialog closed by clicking OK button")
        elif response == Gtk.ResponseType.CANCEL:
            print("WARN dialog closed by clicking CANCEL button")

        dialog.destroy()

    def on_question_clicked(self, question):
        dialog = Gtk.MessageDialog(self, 0, Gtk.MessageType.QUESTION,
            Gtk.ButtonsType.YES_NO, "Внимание!")
        dialog.format_secondary_text(
            question)
        response = dialog.run()
        if response == Gtk.ResponseType.YES:
            dialog.destroy() 
            return(True)
        elif response == Gtk.ResponseType.NO:
            dialog.destroy()
            return(False)

        dialog.destroy()

class ListBoxWindow(Gtk.Window):

    def __init__(self, hostname):
        
        self.hostname = hostname
        
        Gtk.Window.__init__(self, title="Ввод РЕД ОС в домен MS Active Directory",resizable=False)
        self.set_border_width(10)
        box_outer = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6)
        self.add(box_outer)

        listbox = Gtk.ListBox()
        listbox.set_selection_mode(Gtk.SelectionMode.NONE)
        box_outer.pack_start(listbox, True, True, 0)

        row = Gtk.ListBoxRow()
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
        row.add(hbox)
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        hbox.pack_start(vbox, True, True, 0)

        label1 = Gtk.Label("Имя домена", xalign=0)
        vbox.pack_start(label1, True, True, 0)

        self.entry_domain = Gtk.Entry()
        self.entry_domain.props.valign = Gtk.Align.CENTER
        hbox.pack_start(self.entry_domain, False, True, 0)

        listbox.add(row)

        row = Gtk.ListBoxRow()
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
        row.add(hbox)
        label = Gtk.Label("Тип домена", xalign=0)
        self.combo = Gtk.ComboBoxText()
        self.combo.insert(0, "0", "MS Active Directory 2008r2 и выше")
        self.combo.insert(1, "1", "MS Active Directory 2003")
        self.combo.insert(2, "2", "Samba4 DC")
        self.combo.insert(3, "3", "IPA")
        self.combo.set_active(0)
        hbox.pack_start(label, True, True, 0)
        hbox.pack_start(self.combo, False, True, 0)

        listbox.add(row)

        row = Gtk.ListBoxRow()
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
        row.add(hbox)
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        hbox.pack_start(vbox, True, True, 0)

        label2 = Gtk.Label("Имя компьютера без домена", xalign=0)
        vbox.pack_start(label2, True, True, 0)

        self.entry_hostname = Gtk.Entry()
        self.entry_hostname.props.valign = Gtk.Align.CENTER
        self.entry_hostname.set_text(self.hostname)
        hbox.pack_start(self.entry_hostname, False, True, 0)

        listbox.add(row)
        
        row = Gtk.ListBoxRow()
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
        row.add(hbox)
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        hbox.pack_start(vbox, True, True, 0)

        labelLogin = Gtk.Label("Имя администратора домена", xalign=0)
        vbox.pack_start(labelLogin, True, True, 0)

        self.entry_login = Gtk.Entry()
        self.entry_login.props.valign = Gtk.Align.CENTER
        self.entry_login.set_text("Administrator")
        hbox.pack_start(self.entry_login, False, True, 0)

        listbox.add(row)
        
        row = Gtk.ListBoxRow()
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
        row.add(hbox)
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        hbox.pack_start(vbox, True, True, 0)

        labelPass = Gtk.Label("Пароль администратора домена", xalign=0)
        vbox.pack_start(labelPass, True, True, 0)

        self.entry_pass = Gtk.Entry()
        self.entry_pass.props.valign = Gtk.Align.CENTER
        self.entry_pass.set_visibility(False)
        self.entry_pass.set_invisible_char("*")
        hbox.pack_start(self.entry_pass, False, True, 0)
        
        listbox.add(row)
        
        row = Gtk.ListBoxRow()
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
        row.add(hbox)
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        hbox.pack_start(vbox, True, True, 0)

        labelNTP = Gtk.Label("Адрес NTP сервера (необязательно)", xalign=0)
        vbox.pack_start(labelNTP, True, True, 0)    
        self.entry_ntp = Gtk.Entry()
        self.entry_ntp.props.valign = Gtk.Align.CENTER
        hbox.pack_start(self.entry_ntp, False, True, 0)

        listbox.add(row)
        
        row = Gtk.ListBoxRow()
        hbox = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=50)
        row.add(hbox)
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        hbox.pack_start(vbox, True, True, 0)
        self.button1 = Gtk.Button(label="Ввести в домен")
        self.button1.connect("clicked", self.on_join)
        vbox.pack_start(self.button1, True, True, 0)

        listbox.add(row)

    def set_hostname(self, text):
        self.hostname = self.entry_hostname.get_text()
        print(self.hostname)
    def kerberos_check():
        return True if subprocess.call(['klist', '-s']) == 0 else False
    def set_watch(self):
        watch_cursor = Gdk.Cursor(Gdk.CursorType.WATCH)
        self.get_window().set_cursor(watch_cursor)
        self.button1.set_label("Работаю...")
        self.button1.set_sensitive(False)

    def end_watch(self):
        self.get_window().set_cursor(None)
        self.button1.set_label("Ввести в домен")
        self.button1.set_sensitive(True)
        return False
        
    def on_join(self, entry):
        
        # Проверка на пустые поля
        domain = self.entry_domain.get_text()
        hostname_inp = self.entry_hostname.get_text()
        ad_login = self.entry_login.get_text()
        ad_pass = self.entry_pass.get_text()
        ntp = self.entry_ntp.get_text()
        if domain is '':
            error_msg = 'В поле "Имя домена" ничего не введено! Введите значение'
            error_message(error_msg)
        elif hostname_inp is '':
            error_msg = 'В поле "Имя компьютера" ничего не введено! Введите значение'
            error_message(error_msg)
        elif ad_login is '':
            error_msg = 'В поле "Имя администратора домена" ничего не введено! Введите значение'
            error_message(error_msg)
        elif ad_pass is '':
            error_msg = 'В поле "Пароль администратора домена" ничего не введено! Введите значение'
            error_message(error_msg)
        else:
            if ntp is '':
                #question_msg = 'В поле "Fдрес NTP сервера" ничего не введено! Если вы продолжите, то NTP сервером будет сам контроллер домена.'
                #qntp = question_message(question_msg)
                ntp = get_ip(domain) # получение ip адреса
            # Проверка выбранного домена
            domain_type = self.combo.get_active_text()
            lineLen = len(domain_type)
            #print(lineLen)
            if lineLen is 33: # если 2008r2 и выше
                # Проверка правильности выбора типа домена
                if check_domain_type(domain) != 'ipa':
                    print('good chek')
                else:
                    error_msg = 'Вы пытаетесь ввести компьютер в домен IPA, но выбрали неверный тип домена! '
                    error_message(error_msg) 
                    return 0
                # Проверка на членство в домене
                domain_is = get_domain()
                if domain_is == None:
                    # Проверка доступности домена
                    if realm_discover(domain) is True:
                        # Установка курсора
                        self.set_watch()
                        # Установка имени компьютера
                        if self.hostname != hostname_inp:
                            self.hostname = self.entry_hostname.get_text()
                            set_hostname(self.hostname)
                        # Добавление тайм сервера
                        delete_all_str_in_file('/etc/chrony.conf','server') # удаление всех серверов времени
                        with open("/etc/chrony.conf", "a") as myfile: # Добавление своего сервера времени
                            myfile.write('server ' + ntp + ' iburst')                        
                        call(['systemctl', 'restart', 'chronyd']) 
                        call(['systemctl', 'enable', 'chronyd'])
                        # Ввод в домен
                        p = Popen(['realm', 'join' ,'-U',ad_login, domain], stdout=PIPE, stdin=PIPE, stderr=PIPE, universal_newlines=True)
                        out, err = p.communicate(ad_pass)
                        if err != '':
                            self.end_watch()
                            error_message(err)
                        else:              
                            # Правка sssd
                            path = '/etc/sssd/sssd.conf'
                            section = 'domain/' + domain
                            set_setting(path, section, "use_fully_qualified_names", "False")
                            set_setting(path, section, "ad_gpo_access_control", "permissive")
                            realm = domain.split('.')[0]
                            set_setting('/etc/samba/smb.conf', 'global', "workgroup", realm.upper())
                            set_setting('/etc/samba/smb.conf', 'global', "security", 'ADS')
                            set_setting('/etc/samba/smb.conf', 'global', "realm", domain.upper())
                            set_setting('/etc/samba/smb.conf', 'global', "client max protocol", 'NT1')
                            set_setting('/etc/samba/smb.conf', 'global', "idmap config * : range", '3000-7999')
                            edit_config('/etc/krb5.conf', 'default_ccache_name', 'FILE:/tmp/krb5cc_%{uid}')
                            # Выполнение authconfig
                            call(['authconfig', '--enablemkhomedir', '--enablesssdauth', '--updateall'])
                            # Перезапуск sssd
                            call(['systemctl', 'restart', 'smb'])
                            call(['systemctl', 'enable', 'sssd'])
                            call(['systemctl', 'restart', 'sssd'])
                            # Проверка на членство в домене.
                            domain_check = get_domain()
                            self.end_watch()
                            if domain_check == None:
                                error_msg = 'Неизвестная ошибка ввода в домен ' + domain
                                error_message(error_msg)
                            else:
                                info = 'Ввод в домен ' + domain + ' успешен!'
                                info_message(info)
                                self.destroy()
                    else:
                        error_msg = 'Домен ' + domain + ' недоступен. Проверьте DNS'
                        error_message(error_msg)
                    
                else:
                    error_msg = 'Ваш компьютер уже является членом домена ' + domain_is
                    error_message(error_msg)
                
                # Так сложно из за того, что вывод нужно из байт привести к тексту utf-8
                #with Popen(['realm', 'discover', '-v', 'ad.redos'], stdout=PIPE, stderr=STDOUT, bufsize=1) as process:
                #    for line in io.TextIOWrapper(process.stdout, encoding="utf-8"):
                #        index = line.find("configured: no")
                #        if index != -1:
                #        print(index)
                #self.hostname = self.entry_hostname.get_text()
                #set_hostname(self.hostname)
            
            elif lineLen is 24: # если 2003
                # Проверка на членство в домене
                if check_domain_type(domain) != 'ipa':
                    print('good chek')
                else:
                    error_msg = 'Вы пытаетесь ввести компьютер в домен IPA, но выбрали неверный тип домена! '
                    error_message(error_msg)                    
                    return 0
                domain_is = get_domain()
                if domain_is == None:
                    # Проверка доступности домена
                    if realm_discover(domain) is True:
                        self.set_watch()
                        # Установка имени компьютера
                        if self.hostname != hostname_inp:
                            self.hostname = self.entry_hostname.get_text()
                            hostnameDomain = self.hostname + '.' + domain
                            set_hostname(hostnameDomain)
                        # Добавление тайм сервера
                        delete_all_str_in_file('/etc/chrony.conf','server') # удаление всех серверов времени
                        with open("/etc/chrony.conf", "a") as myfile: # Добавление своего сервера времени
                            myfile.write('server ' + ntp + ' iburst')   
                        call(['systemctl', 'restart', 'chronyd']) 
                        call(['systemctl', 'enable', 'chronyd'])
                        # Ввод в домен
                        p = Popen(['realm', 'join' ,'-U',ad_login, domain], stdout=PIPE, stdin=PIPE, stderr=PIPE, universal_newlines=True)
                        out, err = p.communicate(ad_pass)
                        if err != '':
                            self.end_watch()
                            error_message(err)
                        else:              
                            # Правка sssd
                            path = '/etc/sssd/sssd.conf'
                            section = 'domain/' + domain
                            set_setting(path, section, "use_fully_qualified_names", "False")
                            set_setting(path, section, "ad_gpo_access_control", "permissive")
                            # Правка krb5.conf
                            path = '/etc/krb5.conf'
                            section = 'libdefaults' + domain
                            set_setting(path, section, "default_tkt_enctypes", "RC4-HMAC, DES-CBC-CRC, DES3-CBC-SHA1,DES-CBC-MD5")
                            set_setting(path, section, "default_tgs_enctypes", "RC4-HMAC, DES-CBC-CRC, DES3-CBC-SHA1, DES-CBC-MD5")
                            realm = domain.split('.')[0]
                            set_setting('/etc/samba/smb.conf', 'global', "workgroup", realm.upper())
                            set_setting('/etc/samba/smb.conf', 'global', "security", 'ADS')
                            set_setting('/etc/samba/smb.conf', 'global', "realm", domain.upper())
                            set_setting('/etc/samba/smb.conf', 'global', "client max protocol", 'NT1')
                            set_setting('/etc/samba/smb.conf', 'global', "idmap config * : range", '3000-7999')
                            edit_config('/etc/krb5.conf', 'default_ccache_name', 'FILE:/tmp/krb5cc_%{uid}')
                            # Выполнение authconfig
                            call(['authconfig', '--enablemkhomedir', '--enablesssdauth', '--updateall'])
                            # Перезапуск sssd
                            call(['systemctl', 'restart', 'smb'])
                            call(['systemctl', 'enable', 'sssd'])
                            call(['systemctl', 'restart', 'sssd'])
                            # Проверка на членство в домене.
                            domain_check = get_domain()
                            self.end_watch()
                            if domain_check == None:
                                error_msg = 'Неизвестная ошибка ввода в домен ' + domain
                                error_message(error_msg)
                            else:
                                if kerberos_check() == False:
                                    kinit = '/usr/bin/kinit'
                                    kinit_args = [ kinit, '%s' % (ad_login) ]
                                    kinit = subprocess.Popen(kinit_args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
                                    kinit.stdin.write('%s\n' % ad_pass)
                                    if kerberos_check() == False:
                                        error_message(kinit.stderr.read())
                                    kinit.wait()
                                else:
                                    info = 'Ввод в домен ' + domain + ' успешен!'
                                    info_message(info)
                                    self.destroy()
                            
                    else:
                        error_msg = 'Домен ' + domain + ' недоступен. Проверьте DNS'
                        error_message(error_msg)
                    
                else:
                    error_msg = 'Ваш компьютер уже является членом домена ' + domain_is
                    error_message(error_msg)
            elif lineLen is 9: # если Samba DC
                # Проверка на членство в домене
                if check_domain_type(domain) != 'ipa':
                    print('good chek')
                else:
                    error_msg = 'Вы пытаетесь ввести компьютер в домен IPA, но выбрали неверный тип домена! '
                    error_message(error_msg)
                    return 0
                # Проверка на членство в домене
                domain_is = get_domain()
                if domain_is == None:
                    # Проверка доступности домена
                    if realm_discover(domain) is True:
                        self.set_watch()
                        # Установка имени компьютера
                        if self.hostname != hostname_inp:
                            self.hostname = self.entry_hostname.get_text()
                            set_hostname(self.hostname)
                        # Добавление тайм сервера
                        delete_all_str_in_file('/etc/chrony.conf','server') # удаление всех серверов времени
                        with open("/etc/chrony.conf", "a") as myfile: # Добавление своего сервера времени
                            myfile.write('server ' + ntp + ' iburst')                       
                        call(['systemctl', 'restart', 'chronyd']) 
                        call(['systemctl', 'enable', 'chronyd'])
                        # Ввод в домен
                        p = Popen(['realm', 'join' ,'-U',ad_login, domain], stdout=PIPE, stdin=PIPE, stderr=PIPE, universal_newlines=True)
                        out, err = p.communicate(ad_pass)
                        if err != '':
                            self.end_watch()
                            error_message(err)
                        else:              
                            # Правка sssd
                            path = '/etc/sssd/sssd.conf'
                            section = 'domain/' + domain
                            set_setting(path, section, "use_fully_qualified_names", "False")
                            set_setting(path, section, "ad_gpo_access_control", "permissive")
                            realm = domain.split('.')[0]
                            set_setting('/etc/samba/smb.conf', 'global', "workgroup", realm.upper())
                            set_setting('/etc/samba/smb.conf', 'global', "security", 'ADS')
                            set_setting('/etc/samba/smb.conf', 'global', "realm", domain.upper())
                            set_setting('/etc/samba/smb.conf', 'global', "client max protocol", 'NT1')
                            set_setting('/etc/samba/smb.conf', 'global', "idmap config * : range", '3000-7999')
                            edit_config('/etc/krb5.conf', 'default_ccache_name', 'FILE:/tmp/krb5cc_%{uid}')
                            # Выполнение authconfig
                            call(['authconfig', '--enablemkhomedir', '--enablesssdauth', '--updateall'])
                            # Перезапуск sssd
                            call(['systemctl', 'restart', 'smb'])
                            call(['systemctl', 'enable', 'sssd'])
                            call(['systemctl', 'restart', 'sssd'])
                            # Проверка на членство в домене.
                            domain_check = get_domain()
                            self.end_watch()
                            if domain_check == None:
                                error_msg = 'Неизвестная ошибка ввода в домен, возможно вы ввели неверные учетные данные администратора!' + domain
                                error_message(error_msg)
                            else:
                                info = 'Ввод в домен ' + domain + ' успешен!'
                                info_message(info)
                                self.destroy()
                            
                    else:
                        error_msg = 'Домен ' + domain + ' недоступен. Проверьте DNS'
                        error_message(error_msg)
                    
                else:
                    error_msg = 'Ваш компьютер уже является членом домена ' + domain_is
                    error_message(error_msg)
            elif lineLen is 3: # если IPA
                # Проверка на членство в домене
                if check_domain_type(domain) == 'ipa':
                    print('good chek')
                else:
                    error_msg = 'Вы пытаетесь ввести компьютер в домен AD, но выбрали неверный тип домена! '
                    error_message(error_msg)
                    return 0
                # Проверка на членство в домене
                domain_is = get_domain()
                if domain_is == None:
                    # Проверка доступности домена
                    if realm_discover(domain) is True:
                        self.set_watch()
                        # Установка имени компьютера
                        if self.hostname != hostname_inp:
                            self.hostname = self.entry_hostname.get_text()
                            hostnameDomain = self.hostname + '.' + domain
                            set_hostname(hostnameDomain)
                        else:
                            hostn = self.hostname.split('.')[0]
                            hostnameDomain = hostn + '.' + domain
                            set_hostname(hostnameDomain)
                        # Добавление тайм сервера
                        delete_all_str_in_file('/etc/chrony.conf','server') # удаление всех серверов времени
                        with open("/etc/chrony.conf", "a") as myfile: # Добавление своего сервера времени
                            myfile.write('server ' + ntp + ' iburst')   
                        call(['systemctl', 'restart', 'chronyd']) 
                        call(['systemctl', 'enable', 'chronyd'])
                        # Ввод в домен
                        principal='--principal='+ad_login
                        princ_password = '--password='+ad_pass
                        p = Popen(['ipa-client-install', '--mkhomedir', '--enable-dns-updates' ,principal, princ_password], stdout=PIPE, stdin=PIPE, stderr=PIPE, universal_newlines=True)
                        out, err = p.communicate('yes')
                        self.end_watch()
                        print('1111111111111111111111111111')
                        print(stderr)
                        print('1111111111111111111111111111')
                        if err != '':      
                            error_message(err)
                        # Проверка на членство в домене.
                        domain_check = get_domain()
                        if domain_check == None:
                            error_msg = 'Неизвестная ошибка ввода в домен ' + domain
                            error_message(error_msg)
                        else:
                            info = 'Ввод в домен ' + domain + ' успешен!'
                            info_message(info)
                            self.destroy()
                            
                    else:
                        error_msg = 'Домен ' + domain + ' недоступен. Проверьте DNS'
                        error_message(error_msg)
                    
                else:
                    error_msg = 'Ваш компьютер уже является членом домена ' + domain_is
                    error_message(error_msg)
            else:
                error_msg = 'Ошибка типа домена'
                error_message(error_msg)
def set_setting(path, section, setting, value): # Добавляет или изменяет параметры в конфигах через configparser
    config = configparser.ConfigParser()
    config.read(path)
    config.set(section, setting, value)
    with open(path, "w") as config_file:
        config.write(config_file)

def delete_all_str_in_file(file, str):  # Удаляет все строки из файла, содержащие str
    with open(file) as f:
        lines = f.readlines()
        pattern = re.compile(re.escape(str))
        with open(file, 'w') as f:
            for line in lines:
                result = pattern.search(line)
                if result is None:
                    f.write(line)
        
def realm_discover(domain):  # Проверка на доступность домена, True если доступен
    # Так сложно из за того, что вывод нужно из байт привести к тексту utf-8
    with Popen(['realm', 'discover', '-v', domain], stdout=PIPE, stderr=STDOUT, bufsize=1) as process:
        for line in io.TextIOWrapper(process.stdout, encoding="utf-8"):
            index = line.find("  domain-name: " + domain)
            if index == 0:
                return True
    return False

def get_ip(domain):
    with Popen(['realm', 'discover', '-v', domain], stdout=PIPE, stderr=STDOUT, bufsize=1) as process:
        for line in io.TextIOWrapper(process.stdout, encoding="utf-8"):
            for word in line.split():
                try:
                    socket.inet_aton(word)
                    return word
                    break
                except socket.error:
                    rt='sd'

def check_domain_type(domain):
    with Popen(['realm', 'discover', '-v', domain], stdout=PIPE, stderr=STDOUT, bufsize=1) as process:
        for line in io.TextIOWrapper(process.stdout, encoding="utf-8"):
            if 'server-software:' in line:
                return(line[19:].strip())
                break

def error_message(error):  # Вывод окна с ошибкой, принимает строку с ошибкой
    win = MessageDialogWindow()
    win.on_error_clicked(error)
    
def question_message(question):  # Вывод окна с ошибкой, принимает строку с ошибкой
    win = MessageDialogWindow()
    return(win.on_question_clicked(question))
    
def info_message(info):  # Вывод окна с информацией, принимает строку с ошибкой
    win = MessageDialogWindow()
    win.on_info_clicked(info)

def get_domain():  # Проверяет членство в домене, если в домене возвращает имя домена, если нет - None
    with Popen(['realm', 'list'], stdout=PIPE, stderr=STDOUT, bufsize=1) as process:
        for line in io.TextIOWrapper(process.stdout, encoding="utf-8"):
            return line.split()[0].strip()
            break
  
def get_hostname():  # Получает имя компьютера
    hostname = socket.gethostname()
    return hostname

def set_hostname(hostname):  # Задает имя компьютера
    bashCommand = "hostnamectl set-hostname " + hostname
    process = Popen(bashCommand.split(), stdout=PIPE)
    output, error = process.communicate()

def get_domain_type(): # Возвращает тип контроллера домена
    with Popen(['realm', 'list'], stdout=PIPE, stderr=STDOUT, bufsize=1) as process:
        for line in io.TextIOWrapper(process.stdout, encoding="utf-8"):        
            if 'server-software:' in line:
                return(line[19:].strip())
                break

def edit_config(fileName, sourceText, replaceText): # Изменяет параметры в конфигах. Принимает имя файла, параметр, нужное значение. Если такого параметра нет, возвращает False.
    file = open(fileName, 'r') #Opens the file in read-mode
    text = file.read() #Reads the file and assigns the value to a variable
    file.close() #Closes the file (read session)
    param = sourceText
    spase = ""
    f = open(fileName, 'r')
    for line in f.readlines():
        index = line.find(param)
        if index != -1:
            sourceText = line
            i = 0
            while i < index:
                spase = spase + ' '
                i+=1        
    replaceText = spase + param + ' = ' + replaceText + '\n'
    file = open(fileName, 'w') #Opens the file again, this time in write-mode
    file.write(text.replace(sourceText, replaceText)) #replaces all instances of our keyword
    file.close() #Closes the file (write session)
    print('All went well, the modifications are done')

def domain_leave(domain_name, domain_type):
    print(domain_type)
    print(domain_name)
    if domain_type == 'ipa':
        print('leave ipa...')
        p = Popen(['ipa-client-install', '--uninstall'], stdout=PIPE, stdin=PIPE, stderr=PIPE, universal_newlines=True)
        out, err = p.communicate('no')
        if err != '':
            print(err)
        domain_check = get_domain()
        if domain_check == None:
            info_message('Компьютер успешно выведен из домена')
        else:
            error_message('Ошибка вывода из домена!')
            exit(1)
        question_msg = 'Вы хотите перезагрузить компьютер для завершения настроек?'
        qntp = question_message(question_msg)
        if qntp is True:
            call('reboot')
            exit(0)
    else:
        print('leave ad...')
        call(['realm', 'leave', '-v',domain_name])
        domain_check = get_domain()
        if domain_check == None:
            delete_all_str_in_file('/etc/samba/smb.conf', 'idmap')
            delete_all_str_in_file('/etc/samba/smb.conf', 'realm')
            set_setting('/etc/samba/smb.conf', 'global', "workgroup", "WORKGROUP")
            set_setting('/etc/samba/smb.conf', 'global', "security", 'user')
            set_setting('/etc/samba/smb.conf', 'global', "client max protocol", 'SMB3_11')
            delete_all_str_in_file('/etc/samba/smb.conf', 'default_ccache_name')
            edit_config('/etc/krb5.conf', 'default_ccache_name', 'KEYRING:persistent:%{uid}')
            call(['sss_cache', '-E'])
            call(['systemctl', 'restart', 'smb'])
            info_message('Компьютер успешно выведен из домена')
        else:
            call(['realm', 'leave', '-v',domain_name])
            domain_check = get_domain()
            if domain_check == None:
                delete_all_str_in_file('/etc/samba/smb.conf', 'idmap')
                delete_all_str_in_file('/etc/samba/smb.conf', 'realm')
                set_setting('/etc/samba/smb.conf', 'global', "workgroup", "WORKGROUP")
                set_setting('/etc/samba/smb.conf', 'global', "security", 'user')
                set_setting('/etc/samba/smb.conf', 'global', "client max protocol", 'SMB3_11')
                delete_all_str_in_file('/etc/samba/smb.conf', 'default_ccache_name')
                edit_config('/etc/krb5.conf', 'default_ccache_name', 'KEYRING:persistent:%{uid}')
                call(['sss_cache', '-E'])
                call(['systemctl', 'restart', 'smb'])
                info_message('Компьютер успешно выведен из домена')
            else:
                error_message('Ошибка вывода из домена!')
                exit(1)
        question_msg = 'Вы хотите перезагрузить компьютер для завершения настроек?'
        qntp = question_message(question_msg)
        if qntp is True:
            call('reboot')
            exit(0)

if __name__ == "__main__":
    if not os.geteuid() == 0:
        error_msg = 'Ввод в домен доступен только пользователю root '
        error_message(error_msg)
    else:
        domain_check = get_domain()
        if domain_check == None:
            def_hostname = get_hostname()
            win = ListBoxWindow(def_hostname)
            win.connect("destroy", Gtk.main_quit)
            win.show_all()
            Gtk.main()
        else:
            domain_type = get_domain_type()
            question_msg = 'Вы уже состоите в домене ' + domain_check + ' на базе ' + domain_type + '. Вывести из домена и продолжить?'
            qntp = question_message(question_msg)
            if qntp is True:
                domain_leave(domain_check, domain_type)
                def_hostname = get_hostname()
                win = ListBoxWindow(def_hostname)
                win.connect("destroy", Gtk.main_quit)
                
                win.show_all()
                Gtk.main()
            elif qntp is False:
                exit(1)
