Join a computer to an Active Directory domain. Requires a reboot.

    Args:

        domain (str):
            The domain to which the computer should be joined, e.g.
            ``example.com``

        username (str):
            Username of an account which is authorized to join computers to the
            specified domain. Needs to be either fully qualified like
            ``user@domain.tld`` or simply ``user``

        password (str):
            Password of the specified user

        account_ou (str):
            The DN of the OU below which the account for this computer should be
            created when joining the domain, e.g.
            ``ou=computers,ou=departm_432,dc=my-company,dc=com``

        account_exists (bool):
            If set to ``True`` the computer will only join the domain if the
            account already exists. If set to ``False`` the computer account
            will be created if it does not exist, otherwise it will use the
            existing account. Default is ``False``

        restart (bool):
            ``True`` will restart the computer after a successful join. Default
            is ``False``

            .. versionadded:: 2015.8.2/2015.5.7

    Returns:
        dict: Returns a dictionary if successful, otherwise ``False``

    CLI Example:

    .. code-block:: bash

        salt 'minion-id' system.join_domain domain='domain.tld' \\
                         username='joinuser' password='joinpassword' \\
                         account_ou='ou=clients,ou=org,dc=domain,dc=tld' \\
                         account_exists=False, restart=True

def join_domain(domain,
                username=None,
                password=None,
                account_ou=None,
                account_exists=False,
                restart=False):
    '''
    Join a computer to an Active Directory domain. Requires a reboot.

    Args:

        domain (str):
            The domain to which the computer should be joined, e.g.
            ``example.com``

        username (str):
            Username of an account which is authorized to join computers to the
            specified domain. Needs to be either fully qualified like
            ``user@domain.tld`` or simply ``user``

        password (str):
            Password of the specified user

        account_ou (str):
            The DN of the OU below which the account for this computer should be
            created when joining the domain, e.g.
            ``ou=computers,ou=departm_432,dc=my-company,dc=com``

        account_exists (bool):
            If set to ``True`` the computer will only join the domain if the
            account already exists. If set to ``False`` the computer account
            will be created if it does not exist, otherwise it will use the
            existing account. Default is ``False``

        restart (bool):
            ``True`` will restart the computer after a successful join. Default
            is ``False``

            .. versionadded:: 2015.8.2/2015.5.7

    Returns:
        dict: Returns a dictionary if successful, otherwise ``False``

    CLI Example:

    .. code-block:: bash

        salt 'minion-id' system.join_domain domain='domain.tld' \\
                         username='joinuser' password='joinpassword' \\
                         account_ou='ou=clients,ou=org,dc=domain,dc=tld' \\
                         account_exists=False, restart=True
    '''
    if six.PY2:
        domain = _to_unicode(domain)
        username = _to_unicode(username)
        password = _to_unicode(password)
        account_ou = _to_unicode(account_ou)

    status = get_domain_workgroup()
    if 'Domain' in status:
        if status['Domain'] == domain:
            return 'Already joined to {0}'.format(domain)

    if username and '\\' not in username and '@' not in username:
        username = '{0}@{1}'.format(username, domain)

    if username and password is None:
        return 'Must specify a password if you pass a username'

    # remove any escape characters
    if isinstance(account_ou, six.string_types):
        account_ou = account_ou.split('\\')
        account_ou = ''.join(account_ou)

    err = _join_domain(domain=domain, username=username, password=password,
                       account_ou=account_ou, account_exists=account_exists)

    if not err:
        ret = {'Domain': domain,
               'Restart': False}
        if restart:
            ret['Restart'] = reboot()
        return ret

    raise CommandExecutionError(win32api.FormatMessage(err).rstrip())