Пример #1
0
    def save(self):
        enable = self.cleaned_data.get("ldap_enable")

        started = notifier().started("ldap")
        obj = super(LDAPForm, self).save()
        self.cifs.cifs_srv_netbiosname = self.cleaned_data.get(
            "ldap_netbiosname_a")
        self.cifs.cifs_srv_netbiosname_b = self.cleaned_data.get(
            "ldap_netbiosname_b")
        self.cifs.cifs_srv_netbiosalias = self.cleaned_data.get(
            "ldap_netbiosalias")
        self.cifs.save()

        if enable:
            if started is True:
                started = notifier().restart(
                    "ldap",
                    timeout=_fs().directoryservice.ldap.timeout.restart)
            if started is False:
                started = notifier().start(
                    "ldap", timeout=_fs().directoryservice.ldap.timeout.start)
            if started is False:
                self.instance.ldap_enable = False
                super(LDAPForm, self).save()
                raise MiddlewareError(_("LDAP failed to reload."))
        else:
            if started is True:
                started = notifier().stop(
                    "ldap", timeout=_fs().directoryservice.ldap.timeout.stop)

        return obj
Пример #2
0
    def tryConnect(self, host, port):
        max_tries = 3
        timeout = _fs().middlewared.plugins.service_monitor.socket_timeout
        connected = False

        i = 0
        while i < max_tries:

            # XXX What about UDP?
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.settimeout(timeout)

            try:
                s.connect((host, port))
                connected = True

            except Exception as e:
                self.logger.debug("[ServiceMonitorThread] Cannot connect: {0}:{1} with error: {2}".format(host, port, e))
                connected = False

            finally:
                s.settimeout(None)
                s.close()

            i += 1

        return connected
Пример #3
0
 def save(self):
     bsduser = super(bsdUserEmailForm, self).save(commit=True)
     try:
         notifier().reload("user", timeout=_fs().account.user.timeout.reload)
     except Exception as e:
         log.debug("ERROR: failed to reload user: %s", e)
     return bsduser
Пример #4
0
    def tryConnect(self, host, port):
        max_tries = 3
        timeout = _fs().middlewared.plugins.service_monitor.socket_timeout
        connected = False

        i = 0
        while i < max_tries:

            # XXX What about UDP?
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.settimeout(timeout)

            try:
                s.connect((host, port))
                connected = True

            except Exception as e:
                self.logger.debug("[ServiceMonitorThread] Cannot connect: {0}:{1} with error: {2}".format(host, port, e))
                connected = False

            finally:
                s.settimeout(None)
                s.close()

            i += 1

        return connected
Пример #5
0
    def is_valid(self):
        valid = super(NewPasswordForm, self).is_valid()
        if valid:
            qs = models.bsdUsers.objects.filter(bsdusr_uid=0,
                                                bsdusr_unixhash='*')
            if qs.exists():
                user = qs[0]
                user.set_password(self.cleaned_data['password'])
                user.save()
                self.user_cache = authenticate(
                    username=user.bsdusr_username,
                    password=self.cleaned_data['password'],
                )

                #
                # XXX hackity hackness XXX
                # Catch call timeout exceptions. We should really return this to the user
                # in the UI, but there is no easy way to currently do this. For now this
                # prevents a stack trace in the UI, which is slightly better than nothing ;-)
                # This same try/except structure is littered throughout this code.
                #
                try:
                    notifier().reload(
                        "user", timeout=_fs().account.user.timeout.reload)
                except Exception as e:
                    log.debug("ERROR: failed to reload user: %s", e)

        return valid
Пример #6
0
    def tryConnect(self, host, port):
        max_tries = 3
        connected = False
        sm_timeout = _fs().middlewared.plugins.service_monitor.socket_timeout
        host_list = []

        if self.name == 'activedirectory':

            for i in range(0, max_tries):
                # Make max_tries attempts to get SRV records from DNS
                host_list = FreeNAS_ActiveDirectory.get_ldap_servers(host)
                if host_list:
                    break
                else:
                    self.logger.debug(f'[ServiceMonitorThread] Attempt {i} to query SRV records failed')

            if not host_list:
                self.logger.debug(f'[ServiceMonitorThread] Query for SRV records for {host} failed')
                return False

            for h in host_list:
                port_is_listening = FreeNAS_ActiveDirectory.port_is_listening(str(h.target), h.port, errors=[], timeout=sm_timeout)
                if port_is_listening:
                    return True
                else:
                    self.logger.debug(f'[ServiceMonitorThread] Cannot connect: {h.target}:{h.port}')
                    connected = False

            return connected

        else:
            self.logger.debug(f'[ServiceMonitorThread] no monitoring has been written for {self.name}')
            return False
    def tryConnect(self, host, port):
        max_tries = 3
        connected = False

        timeout = _fs().middlewared.plugins.service_monitor.socket_timeout

        for i in range(0, max_tries):
            # XXX What about UDP?
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.settimeout(timeout)

            try:
                s.connect((host, port))
                connected = True

            except Exception as e:
                self.logger.debug(
                    "[ServiceMonitorThread] Cannot connect: %s:%d with error: %s"
                    % (host, port, e))
                connected = False

            finally:
                s.settimeout(None)
                s.close()

            if connected:
                break

        return connected
Пример #8
0
    def tryConnect(self, host, port):
        max_tries = 3
        connected = False
        sm_timeout = _fs().middlewared.plugins.service_monitor.socket_timeout
        host_list = []

        if self.name == 'activedirectory':

            for i in range(0, max_tries):
                # Make max_tries attempts to get SRV records from DNS
                host_list = FreeNAS_ActiveDirectory.get_ldap_servers(host)
                if host_list:
                    break
                else:
                    self.logger.debug(f'[ServiceMonitorThread] Attempt {i} to query SRV records failed')

            if not host_list:
                self.logger.debug(f'[ServiceMonitorThread] Query for SRV records for {host} failed')
                return False

            for h in host_list:
                port_is_listening = FreeNAS_ActiveDirectory.port_is_listening(str(h.target), h.port, errors=[], timeout=sm_timeout)
                if port_is_listening:
                    return True
                else:
                    self.logger.debug(f'[ServiceMonitorThread] Cannot connect: {h.target}:{h.port}')
                    connected = False

            return connected

        else:
            self.logger.debug(f'[ServiceMonitorThread] no monitoring has been written for {self.name}')
            return False
Пример #9
0
    def is_valid(self):
        valid = super(NewPasswordForm, self).is_valid()
        if valid:
            qs = models.bsdUsers.objects.filter(
                bsdusr_uid=0, bsdusr_unixhash='*'
            )
            if qs.exists():
                user = qs[0]
                user.set_password(self.cleaned_data['password'])
                user.save()
                self.user_cache = authenticate(
                    username=user.bsdusr_username,
                    password=self.cleaned_data['password'],
                )

                #
                # XXX hackity hackness XXX
                # Catch call timeout exceptions. We should really return this to the user
                # in the UI, but there is no easy way to currently do this. For now this
                # prevents a stack trace in the UI, which is slightly better than nothing ;-)
                # This same try/except structure is littered throughout this code.
                #
                try:
                    notifier().reload("user", timeout=_fs().account.user.timeout.reload)
                except Exception as e:
                    log.debug("ERROR: failed to reload user: %s", e)

        return valid
Пример #10
0
    def save(self, *args, **kwargs):
        obj = super(servicesForm, self).save(*args, **kwargs)
        _notifier = notifier()

        if obj.srv_service == 'cifs' and _notifier.started('domaincontroller'):
            obj.srv_enable = True
            obj.save()
            started = True

        elif obj.srv_service == 'domaincontroller':
            if obj.srv_enable is True:
                if _notifier.started('domaincontroller'):
                    started = _notifier.restart(
                        "domaincontroller",
                        timeout=_fs(
                        ).services.domaincontroller.timeout.restart)
                else:
                    started = _notifier.start(
                        "domaincontroller",
                        timeout=_fs().services.domaincontroller.timeout.start)
            else:
                started = _notifier.stop(
                    "domaincontroller",
                    timeout=_fs().services.domaincontroller.timeout.stop)

        else:
            """
            For now on, lets handle it properly for all services!
            """
            if obj.srv_enable:
                started = _notifier.start(obj.srv_service)
            else:
                started = _notifier.stop(obj.srv_service)

        self.started = started
        if started is True:
            if not obj.srv_enable:
                obj.srv_enable = True
                obj.save()

        elif started is False:
            if obj.srv_enable:
                obj.srv_enable = False
                obj.save()

        return obj
Пример #11
0
    def save(self):
        enable = self.cleaned_data.get("ldap_enable")

        started = notifier().started("ldap")
        obj = super(LDAPForm, self).save()
        self.cifs.cifs_srv_netbiosname = self.cleaned_data.get("ldap_netbiosname_a")
        self.cifs.cifs_srv_netbiosname_b = self.cleaned_data.get("ldap_netbiosname_b")
        self.cifs.cifs_srv_netbiosalias = self.cleaned_data.get("ldap_netbiosalias")
        self.cifs.save()

        if enable:
            if started is True:
                started = notifier().restart("ldap", timeout=_fs().directoryservice.ldap.timeout.restart)
            if started is False:
                started = notifier().start("ldap", timeout=_fs().directoryservice.ldap.timeout.start)
            if started is False:
                self.instance.ldap_enable = False
                super(LDAPForm, self).save()
                raise MiddlewareError(_("LDAP failed to reload."))
        else:
            if started is True:
                started = notifier().stop("ldap", timeout=_fs().directoryservice.ldap.timeout.stop)

        return obj
Пример #12
0
 def save(self):
     user = models.bsdUsers.objects.get(id=self.userid)
     models.bsdGroupMembership.objects.filter(
         bsdgrpmember_user=user).delete()
     groupid_list = self.cleaned_data['bsduser_to_group']
     for groupid in groupid_list:
         group = models.bsdGroups.objects.get(id=groupid)
         m = models.bsdGroupMembership(bsdgrpmember_group=group,
                                       bsdgrpmember_user=user)
         m.save()
     try:
         notifier().reload("user",
                           timeout=_fs().account.user.timeout.reload)
     except Exception as e:
         log.debug("ERROR: failed to reload user: %s", e)
Пример #13
0
    def save(self):
        ins = super(bsdGroupsForm, self).save()

        if self.instance and hasattr(self.instance, "_original_bsdgrp_group") and \
            self.instance._original_bsdgrp_group != self.instance.bsdgrp_group:
            notifier().groupmap_delete(ntgroup=self.instance._original_bsdgrp_group)

        notifier().groupmap_add(unixgroup=self.instance.bsdgrp_group,
            ntgroup=self.instance.bsdgrp_group)

        try:
            notifier().reload("user", timeout=_fs().account.user.timeout.reload)
        except Exception as e:
            log.debug("ERROR: failed to reload user: %s", e)
        return ins
Пример #14
0
 def save(self, commit=True):
     if commit:
         _notifier = notifier()
         unixhash, smbhash = _notifier.user_changepassword(
             username=str(self.instance.bsdusr_username),
             password=str(self.cleaned_data['bsdusr_password']),
         )
         self.instance.bsdusr_unixhash = unixhash
         self.instance.bsdusr_smbhash = smbhash
         self.instance.save()
         try:
             _notifier.reload("user", timeout=_fs().account.user.timeout.reload)
         except Exception as e:
             log.debug("ERROR: failed to reload user: %s", e)
     return self.instance
Пример #15
0
 def save(self):
     user = models.bsdUsers.objects.get(id=self.userid)
     models.bsdGroupMembership.objects.filter(
         bsdgrpmember_user=user
     ).delete()
     groupid_list = self.cleaned_data['bsduser_to_group']
     for groupid in groupid_list:
         group = models.bsdGroups.objects.get(id=groupid)
         m = models.bsdGroupMembership(
             bsdgrpmember_group=group,
             bsdgrpmember_user=user)
         m.save()
     try:
         notifier().reload("user", timeout=_fs().account.user.timeout.reload)
     except Exception as e:
         log.debug("ERROR: failed to reload user: %s", e)
Пример #16
0
    def check_AD(self, host, port):
        """
        Basic health checks to determine whether we can recover the AD service if a disruption occurs.
        Current tests:
        - Clockskew from DC is not greater than 5 minutes (MIT default). Kerberos has strict time requirements.
          This can vary based on the kerberos configuration, and so this may need to be a configurable field.
        - DC connectivity. We check this by using DNS to get SRV records for LDAP, and then trying to open a socket
          to the LDAP(S) port on each of the LDAP servers in the list.
        Future tests:
        - Validate service account password
        - Verify presence of computer object in DA
        """
        connected = False
        permitted_clockskew = datetime.timedelta(minutes=5)
        sm_timeout = _fs().middlewared.plugins.service_monitor.socket_timeout

        host_list = FreeNAS_ActiveDirectory.get_ldap_servers(host, self.config['ad_site'])

        if not host_list:
            self.alert(self.name, f'{self.name}: {host} not in connectable state. DNS query for SRV records for {host} failed.')
            self.logger.debug(f'[ServiceMonitorThread] DNS query for SRV records for {host} failed')
            return False

        for h in host_list:
            port_is_listening = FreeNAS_ActiveDirectory.port_is_listening(str(h.target),
                                                                          h.port,
                                                                          errors=[],
                                                                          timeout=sm_timeout)
            if port_is_listening:
                clockskew_within_spec = self.validate_time(str(h.target), permitted_clockskew)
                if not clockskew_within_spec:
                    return False

                return True
            else:
                self.logger.debug(f'[ServiceMonitorThread] Cannot connect: {h.target}:{h.port}')
                connected = False

        if not connected:
            self.alert(self.name, f'{self.name}: Unable to contact domain controller for {host}. Domain not in connectable state.')

        return connected
Пример #17
0
    def save(self):
        enable = self.cleaned_data.get("ad_enable")
        enable_monitoring = self.cleaned_data.get("ad_enable_monitor")
        monit_frequency = self.cleaned_data.get("ad_monitor_frequency")
        monit_retry = self.cleaned_data.get("ad_recover_retry")
        fqdn = self.cleaned_data.get("ad_domainname")
        sm = None

        if self.__original_changed():
            notifier().clear_activedirectory_config()

        started = notifier().started("activedirectory",
            timeout=_fs().directoryservice.activedirectory.timeout.started)
        obj = super(ActiveDirectoryForm, self).save()

        try:
            utils.get_idmap_object(obj.ds_type, obj.id, obj.ad_idmap_backend)
        except ObjectDoesNotExist:
            log.debug('IDMAP backend {} entry does not exist, creating one.'.format(obj.ad_idmap_backend))
            utils.get_idmap(obj.ds_type, obj.id, obj.ad_idmap_backend)

        self.cifs.cifs_srv_netbiosname = self.cleaned_data.get("ad_netbiosname_a")
        self.cifs.cifs_srv_netbiosname_b = self.cleaned_data.get("ad_netbiosname_b")
        self.cifs.cifs_srv_netbiosalias = self.cleaned_data.get("ad_netbiosalias")
        self.cifs.save()

        if enable:
            if started is True:
                timeout = _fs().directoryservice.activedirectory.timeout.restart
                try:
                    started = notifier().restart("activedirectory", timeout=timeout)
                except Exception as e:
                    raise MiddlewareError(
                        _("Active Directory restart timed out after %d seconds." % timeout),
                    )

            if started is False:
                timeout = _fs().directoryservice.activedirectory.timeout.start
                try:
                    started = notifier().start("activedirectory", timeout=timeout)
                except Exception as e:
                    raise MiddlewareError(
                        _("Active Directory start timed out after %d seconds." % timeout),
                    )
            if started is False:
                self.instance.ad_enable = False
                super(ActiveDirectoryForm, self).save()
                raise MiddlewareError(
                    _("Active Directory failed to reload."),
                )
        else:
            if started is True:
                timeout = _fs().directoryservice.activedirectory.timeout.stop
                try:
                    started = notifier().stop("activedirectory", timeout=timeout)
                except Exception as e:
                    raise MiddlewareError(
                        _("Active Directory stop timed out after %d seconds." % timeout),
                    )

        sm_name = 'activedirectory'
        try:
            sm = ServiceMonitor.objects.get(sm_name=sm_name)
        except Exception as e:
            log.debug("XXX: Unable to find ServiceMonitor: %s", e)
            pass

        #
        # Ports can be specified in the UI but there doesn't appear to be a way to
        # override them via SRV records. This should be fixed.
        #
        dcport = self.get_dcport()
        gcport = self.get_gcport()

        if not sm:
            try:
                log.debug("XXX: fqdn=%s dcport=%s frequency=%s retry=%s enable=%s",
                    fqdn, dcport, monit_frequency, monit_retry, enable_monitoring)

                sm = ServiceMonitor.objects.create(
                    sm_name=sm_name,
                    sm_host=fqdn,
                    sm_port=dcport,
                    sm_frequency=monit_frequency,
                    sm_retry=monit_retry,
                    sm_enable=enable_monitoring
                )
            except Exception as e:
                log.debug("XXX: Unable to create ServiceMonitor: %s", e)
                raise MiddlewareError(
                    _("Unable to create ServiceMonitor: %s" % e),
                )

        else:
            sm.sm_name = sm_name
            if fqdn != sm.sm_host:
                sm.sm_host = fqdn
            if dcport != sm.sm_port:
                sm.sm_port = dcport
            if monit_frequency != sm.sm_frequency:
                sm.sm_frequency = monit_frequency
            if monit_retry != sm.sm_retry:
                sm.sm_retry = monit_retry
            if enable_monitoring != sm.sm_enable:
                sm.sm_enable = enable_monitoring

            try:
                sm.save(force_update=True)
            except Exception as e:
                log.debug("XXX: Unable to create ServiceMonitor: %s", e)
                raise MiddlewareError(
                    _("Unable to save ServiceMonitor: %s" % e),
                )

        with client as c:
            if enable_monitoring and enable:
                log.debug("[ServiceMonitoring] Add %s service, frequency: %d, retry: %d" % ('activedirectory', monit_frequency, monit_retry))
                c.call('servicemonitor.restart')
            else:
                log.debug("[ServiceMonitoring] Remove %s service, frequency: %d, retry: %d" % ('activedirectory', monit_frequency, monit_retry))
                c.call('servicemonitor.restart')

        return obj
Пример #18
0
    def save(self, commit=True):
        _notifier = notifier()
        if self.instance.id is None:
            group = self.cleaned_data['bsdusr_group']
            if group is None:
                try:
                    gid = models.bsdGroups.objects.get(
                        bsdgrp_group=self.cleaned_data['bsdusr_username']
                    ).bsdgrp_gid
                except:
                    gid = -1
            else:
                gid = group.bsdgrp_gid
            uid, gid, unixhash, smbhash = _notifier.user_create(
                username=self.cleaned_data['bsdusr_username'],
                fullname=self.cleaned_data['bsdusr_full_name'].replace(':', ''),
                password=self.cleaned_data['bsdusr_password'],
                uid=self.cleaned_data['bsdusr_uid'],
                gid=gid,
                shell=str(self.cleaned_data['bsdusr_shell']),
                homedir=self.cleaned_data['bsdusr_home'],
                homedir_mode=int(
                    self.cleaned_data.get('bsdusr_mode', '755'),
                    8
                ),
                password_disabled=self.cleaned_data.get(
                    'bsdusr_password_disabled', False
                ),
            )
            bsduser = super(bsdUsersForm, self).save(commit=False)
            try:
                grp = models.bsdGroups.objects.get(bsdgrp_gid=gid)
            except models.bsdGroups.DoesNotExist:
                grp = models.bsdGroups(
                    bsdgrp_gid=gid,
                    bsdgrp_group=self.cleaned_data['bsdusr_username'],
                    bsdgrp_builtin=False,
                )
                grp.save()
            bsduser.bsdusr_group = grp
            bsduser.bsdusr_uid = uid
            bsduser.bsdusr_shell = self.cleaned_data['bsdusr_shell']
            bsduser.bsdusr_unixhash = unixhash
            bsduser.bsdusr_smbhash = smbhash
            bsduser.bsdusr_builtin = False
            bsduser.save()

        else:
            bsduser = super(bsdUsersForm, self).save(commit=False)
            bsduser.bsdusr_group = self.cleaned_data['bsdusr_group']
            bsduser.save()

            #
            # Check if updating password
            #
            bsdusr_password = self.cleaned_data.get("bsdusr_password", "")
            if self._api is True:
                bsdusr_password2 = bsdusr_password
            else:
                bsdusr_password2 = self.cleaned_data["bsdusr_password2"]
            if bsdusr_password and (bsdusr_password == bsdusr_password2):
                unixhash, smbhash = _notifier.user_changepassword(
                    username=bsduser.bsdusr_username,
                    password=bsdusr_password,
                )
                bsduser.bsdusr_unixhash = unixhash
                bsduser.bsdusr_smbhash = smbhash
                bsduser.save()

            homedir_mode = self.cleaned_data.get('bsdusr_mode')
            if (
                not bsduser.bsdusr_builtin and homedir_mode is not None and
                os.path.exists(bsduser.bsdusr_home)
            ):
                try:
                    homedir_mode = int(homedir_mode, 8)
                    os.chmod(bsduser.bsdusr_home, homedir_mode)
                except:
                    log.warn('ERROR: failed to set homedir mode', exc_info=True)

        #
        # Check if updating group membership
        #
        models.bsdGroupMembership.objects.filter(
            bsdgrpmember_user=bsduser
        ).delete()
        groupid_list = self.cleaned_data['bsdusr_to_group']
        for groupid in groupid_list:
            group = models.bsdGroups.objects.get(id=groupid)
            m = models.bsdGroupMembership(
                bsdgrpmember_group=group,
                bsdgrpmember_user=bsduser)
            m.save()

        try:
            _notifier.reload("user", timeout=_fs().account.user.timeout.reload)
        except Exception as e:
            log.debug("ERROR: failed to reload user: %s", e)
        if self.bsdusr_home_copy:
            p = pipeopen("su - %s -c '/bin/cp -a %s/* %s/'" % (
                self.cleaned_data['bsdusr_username'],
                self.bsdusr_home_saved,
                self.cleaned_data['bsdusr_home']
            ))
            p.communicate()

        with client as c:
            c.call('user.update', bsduser.id, {'sshpubkey': self.cleaned_data.get('bsdusr_sshpubkey')})
        return bsduser
Пример #19
0
    def save(self):
        enable = self.cleaned_data.get("ad_enable")
        enable_monitoring = self.cleaned_data.get("ad_enable_monitor")
        monit_frequency = self.cleaned_data.get("ad_monitor_frequency")
        monit_retry = self.cleaned_data.get("ad_recover_retry")
        fqdn = self.cleaned_data.get("ad_domainname")
        sm = None

        if self.__original_changed():
            notifier().clear_activedirectory_config()

        started = notifier().started(
            "activedirectory",
            timeout=_fs().directoryservice.activedirectory.timeout.started)
        obj = super(ActiveDirectoryForm, self).save()

        try:
            utils.get_idmap_object(obj.ds_type, obj.id, obj.ad_idmap_backend)
        except ObjectDoesNotExist:
            log.debug(
                'IDMAP backend {} entry does not exist, creating one.'.format(
                    obj.ad_idmap_backend))
            utils.get_idmap(obj.ds_type, obj.id, obj.ad_idmap_backend)

        self.cifs.cifs_srv_netbiosname = self.cleaned_data.get(
            "ad_netbiosname_a")
        self.cifs.cifs_srv_netbiosname_b = self.cleaned_data.get(
            "ad_netbiosname_b")
        self.cifs.cifs_srv_netbiosalias = self.cleaned_data.get(
            "ad_netbiosalias")
        self.cifs.save()

        if enable:
            if started is True:
                timeout = _fs(
                ).directoryservice.activedirectory.timeout.restart
                try:
                    started = notifier().restart("activedirectory",
                                                 timeout=timeout)
                except Exception as e:
                    raise MiddlewareError(
                        _("Active Directory restart timed out after %d seconds."
                          % timeout), )

            if started is False:
                timeout = _fs().directoryservice.activedirectory.timeout.start
                try:
                    started = notifier().start("activedirectory",
                                               timeout=timeout)
                except Exception as e:
                    raise MiddlewareError(
                        _("Active Directory start timed out after %d seconds."
                          % timeout), )
            if started is False:
                self.instance.ad_enable = False
                super(ActiveDirectoryForm, self).save()
                raise MiddlewareError(
                    _("Active Directory failed to reload."), )
        else:
            if started is True:
                timeout = _fs().directoryservice.activedirectory.timeout.stop
                try:
                    started = notifier().stop("activedirectory",
                                              timeout=timeout)
                except Exception as e:
                    raise MiddlewareError(
                        _("Active Directory stop timed out after %d seconds." %
                          timeout), )

        sm_name = 'activedirectory'
        try:
            sm = ServiceMonitor.objects.get(sm_name=sm_name)
        except Exception as e:
            log.debug("XXX: Unable to find ServiceMonitor: %s", e)
            pass

        #
        # Ports can be specified in the UI but there doesn't appear to be a way to
        # override them via SRV records. This should be fixed.
        #
        dcport = self.get_dcport()
        gcport = self.get_gcport()

        if not sm:
            try:
                log.debug(
                    "XXX: fqdn=%s dcport=%s frequency=%s retry=%s enable=%s",
                    fqdn, dcport, monit_frequency, monit_retry,
                    enable_monitoring)

                sm = ServiceMonitor.objects.create(
                    sm_name=sm_name,
                    sm_host=fqdn,
                    sm_port=dcport,
                    sm_frequency=monit_frequency,
                    sm_retry=monit_retry,
                    sm_enable=enable_monitoring)
            except Exception as e:
                log.debug("XXX: Unable to create ServiceMonitor: %s", e)
                raise MiddlewareError(
                    _("Unable to create ServiceMonitor: %s" % e), )

        else:
            sm.sm_name = sm_name
            if fqdn != sm.sm_host:
                sm.sm_host = fqdn
            if dcport != sm.sm_port:
                sm.sm_port = dcport
            if monit_frequency != sm.sm_frequency:
                sm.sm_frequency = monit_frequency
            if monit_retry != sm.sm_retry:
                sm.sm_retry = monit_retry
            if enable_monitoring != sm.sm_enable:
                sm.sm_enable = enable_monitoring

            try:
                sm.save(force_update=True)
            except Exception as e:
                log.debug("XXX: Unable to create ServiceMonitor: %s", e)
                raise MiddlewareError(
                    _("Unable to save ServiceMonitor: %s" % e), )

        with client as c:
            if enable_monitoring and enable:
                log.debug(
                    "[ServiceMonitoring] Add %s service, frequency: %d, retry: %d"
                    % ('activedirectory', monit_frequency, monit_retry))
                c.call('servicemonitor.restart')
            else:
                log.debug(
                    "[ServiceMonitoring] Remove %s service, frequency: %d, retry: %d"
                    % ('activedirectory', monit_frequency, monit_retry))
                c.call('servicemonitor.restart')

        return obj