def run(self): while True: if not self.initialized: try: with Client() as c: self.disks = c.call("disk.disks_for_temperature_monitoring") self.powermode = c.call("smart.config")["powermode"] except Exception as e: print(f"Failed to query disks for temperature monitoring: {e!r}") else: self.initialized = True if not self.initialized: time.sleep(self.interval) continue if not self.disks: return try: with Client() as c: self.temperatures = { disk: temperature for disk, temperature in c.call("disk.temperatures", self.disks, self.powermode).items() if temperature is not None } except Exception as e: print(f"Failed to collect disks temperatures: {e!r}") self.temperatures = {} time.sleep(self.interval)
def stop(): db = get_db_values() Client().call('datastore.update', 'directoryservice.ActiveDirectory', db['ad']['id'], {'ad_enable': 'False'}) Client().call('datastore.update', 'services.services', db['cifs_srv']['id'], {'srv_enable': 'False'}) service_launcher("samba_server", "stop")
def main(): client = Client() cifs_config = Struct( client.call('datastore.query', 'services.cifs', None, {'get': True})) krb_config = Struct( client.call('datastore.query', 'services.cifs', None, {'get': True})) if not validate_hosts(cifs_config): print("restarting ix-hostname service") service_launcher("ix-hostname", "quietstart") # validate_klist("krb_config.krb_realm") service_launcher("ix-kerberos", "quietstart") service_launcher("ix-nsswitch", "quietstart") if not service_launcher("ix-kinit", "status"): if not service_launcher("ix-kinit", "quietstart"): print("ix-kinit failed") service_launcher("ix-pre-samba", "quietstart") service_launcher("ix-activedirectory", "quietstart") service_launcher("samba_server", "restart") service_launcher("ix-pam", "quietstart") service_launcher("ix-cache", "quietstart")
def _observer(self, message): self.observer_queue.put(message) logger = logging.getLogger("middlewared.plugins.zettarepl") try: if isinstance(message, (PeriodicSnapshotTaskStart, PeriodicSnapshotTaskSuccess, PeriodicSnapshotTaskError)): task_id = int(message.task_id.split("_")[-1]) if isinstance(message, PeriodicSnapshotTaskStart): with Client() as c: context = c.call("vmware.periodic_snapshot_task_begin", task_id, job=True) self.vmware_contexts[task_id] = context if context and context["vmsynced"]: # If there were no failures and we successfully took some VMWare snapshots # set the ZFS property to show the snapshot has consistent VM snapshots # inside it. return message.response(properties={"freenas:vmsynced": "Y"}) if isinstance(message, (PeriodicSnapshotTaskSuccess, PeriodicSnapshotTaskError)): context = self.vmware_contexts.pop(task_id, None) if context: with Client() as c: c.call("vmware.periodic_snapshot_task_end", context, job=True) except ClientException as e: if e.error: logger.error("Unhandled exception in ZettareplProcess._observer: %r", e.error) if e.trace: logger.error("Unhandled exception in ZettareplProcess._observer:\n%s", e.trace["formatted"]) except Exception: logger.error("Unhandled exception in ZettareplProcess._observer", exc_info=True)
def make_it_so(args): parent_dir = None args.pathName if not os.path.exists(args.pathName): """ This is experimental and doesn't get called yet. Samba bails out early if the path doesn't exist. I can probably modify samba to allow this in this case. """ parent_dir = os.path.dirname(args.pathName) bn = os.path.basename(args.pathName) if not os.path.exists(parent_dir): return 1 pds = Client().call('pool.dataset.query', [('mountpoint', '=', parent_dir)])['id'] Client.call('pool.dataset.create', { 'name': f'{pds}/{bn}', 'share_type': 'SMB', 'atime': 'OFF', }) Client().call('sharing.smb.create', { 'path': args.pathName, 'name': args.shareName, 'comment': args.comment, }) return 0
def main(): client = Client() sssd_conf = None if client.call('notifier.common', 'system', 'ldap_enabled') and client.call('notifier.common', 'system', 'ldap_anonymous_bind'): sys.exit(1) sssd_setup() if os.path.exists(SSSD_CONFIGFILE): sssd_conf = SSSD_CONFIGFILE cookie = get_directoryservice_cookie(client) if not cookie: sys.exit(1) def nullfunc(): pass sc = SSSDConf(client=client, path=sssd_conf, parse=nullfunc, cookie=cookie) sc.add_sssd_section() sc.add_nss_section() sc.add_pam_section() if client.call('notifier.common', 'system', 'activedirectory_enabled') and activedirectory_has_unix_extensions(client): add_activedirectory_section(client, sc) if client.call('notifier.common', 'system', 'ldap_enabled'): add_ldap_section(client, sc) sc.save(SSSD_CONFIGFILE)
def main(): client = Client() ldap_conf = "/usr/local/etc/openldap/ldap.conf" if client.call('notifier.common', 'system', 'ldap_enabled'): ldap_conf_ldap(client, ldap_conf) elif client.call('notifier.common', 'system', 'activedirectory_enabled'): ldap_conf_activedirectory(client, ldap_conf)
def main(): client = Client() certs = client.call('certificate.query') write_certificates(certs) certs = client.call('certificateauthority.query') write_certificates(certs)
def get_client(self): try: c = Client(self.websocket) except (FileNotFoundError, ConnectionRefusedError): exit('middlewared is not running.') if self.user and self.password: c.call('auth.login', self.user, self.password) return c
def receive_environ(): def callback(*args, **kwargs): environ_update(kwargs['fields']) c = Client('ws+unix:///var/run/middlewared-internal.sock', py_exceptions=True) c.subscribe('core.environ', callback) environ_update(c.call('core.environ'))
class Connection(object): def __enter__(self): self.client = Client() return self.client def __exit__(self, typ, value, traceback): self.client.close() if typ is not None: raise
class Connection(object): def __init__(self): self.conf = ConfigTarget() self.rest = Client( f'http://{self.conf.target_hostname()}', self.conf.target_api(), self.conf.target_username(), self.conf.target_password(), ) self.ws = WSClient(f'ws://{self.conf.target_hostname()}/websocket') self.ws.call('auth.login', self.conf.target_username(), self.conf.target_password())
def get_db_values(): conf = {} conf['ad'] = Client().call('datastore.query', 'directoryservice.ActiveDirectory', None, {'get': True}) conf['ldap'] = Client().call('datastore.query', 'directoryservice.LDAP', None, {'get': True}) conf['cifs'] = Client().call('datastore.query', 'services.cifs', None, {'get': True}) conf['cifs_srv'] = Client().call('datastore.query', 'services.services', [['srv_service', '=', 'cifs']], {'get': True}) return conf
def __call__(self): setproctitle.setproctitle('middlewared (zettarepl)') osc.die_with_parent() if logging.getLevelName(self.debug_level) == logging.TRACE: # If we want TRACE then we want all debug from zettarepl default_level = logging.DEBUG elif logging.getLevelName(self.debug_level) == logging.DEBUG: # Regular development level. We don't need verbose debug from zettarepl default_level = logging.INFO else: default_level = logging.getLevelName(self.debug_level) setup_logging("", "DEBUG", self.log_handler) oqlh = ObserverQueueLoggingHandler(self.observer_queue) oqlh.setFormatter( logging.Formatter( '[%(asctime)s] %(levelname)-8s [%(threadName)s] [%(name)s] %(message)s', '%Y/%m/%d %H:%M:%S')) logging.getLogger("zettarepl").addHandler(oqlh) for handler in logging.getLogger("zettarepl").handlers: handler.addFilter(LongStringsFilter()) handler.addFilter(ReplicationTaskLoggingLevelFilter(default_level)) c = Client('ws+unix:///var/run/middlewared-internal.sock', py_exceptions=True) c.subscribe( 'core.reconfigure_logging', lambda *args, **kwargs: reconfigure_logging('zettarepl_file')) definition = Definition.from_data(self.definition, raise_on_error=False) self.observer_queue.put(DefinitionErrors(definition.errors)) clock = Clock() tz_clock = TzClock(definition.timezone, clock.now) scheduler = Scheduler(clock, tz_clock) local_shell = LocalShell() self.zettarepl = Zettarepl(scheduler, local_shell) self.zettarepl.set_observer(self._observer) self.zettarepl.set_tasks(definition.tasks) start_daemon_thread(target=self._process_command_queue) while True: try: self.zettarepl.run() except Exception: logging.getLogger("zettarepl").error("Unhandled exception", exc_info=True) time.sleep(10)
def enumerate_host_interfaces(): """Get all addresses of all installed interfaces except loopbacks""" libc = ctypes.CDLL(ctypes.util.find_library('c'), use_errno=True) addr = ctypes.POINTER(if_addrs)() retval = libc.getifaddrs(ctypes.byref(addr)) if retval: raise OSError(ctypes.get_errno()) IFF_LOOPBACK = 0x8 # common value for Linux, Free/OpenBSD addrs = [] bind_ips = Client().call('smb.config')['bindip'] if not bind_ips: bind_ips = [x['address'] for x in Client().call('interface.ip_in_use')] ptr = addr while ptr: deref = ptr[0] family = deref.addr[0].family if deref.addr else None dev_name = deref.name.decode() if deref.flags & IFF_LOOPBACK != 0: logger.debug('ignoring loop-back interface {}'.format(dev_name)) elif family == socket.AF_INET: addrs.append((dev_name, family, socket.inet_ntop(family, bytes(deref.addr[0].data[2:6])))) elif family == socket.AF_INET6: if bytes(deref.addr[0].data[6:8]) == b'\xfe\x80': addrs.append( (dev_name, family, socket.inet_ntop(family, bytes(deref.addr[0].data[6:22])))) ptr = deref.next libc.freeifaddrs(addr) # filter detected addresses by command line arguments, if args.ipv4only: addrs = [x for x in addrs if x[1] == socket.AF_INET] if args.ipv6only: addrs = [x for x in addrs if x[1] == socket.AF_INET6] addrs = [x for x in addrs if x[2] in bind_ips] addrs = [x for x in addrs if not x[0].startswith('lo')] return addrs
def create_test_group(): with Client() as c: c.call("group.create", { "name": "test", }) return c.call("group.query", [["group", "=", "test"]], {"get": True})["gid"]
def main(): parse_args() permitted_clockskew = datetime.timedelta(minutes=3) ad = Client().call('datastore.query', 'directoryservice.activedirectory', [], { 'get': True, 'prefix': 'ad_' }) output = {} with Pool(processes=8) as pool: if args.online: output['server_data'] = check_servers_exist(ad, pool) if args.dump: output['connectable_servers'] = check_servers_exist(ad, pool, -1) if args.records: output['srv_records'] = get_srv_records(ad, pool) if args.time: output['time'] = check_clockskew(ad) if args.ssl: output['ssl'] = check_supports_ssl(ad) if args.json: print(json.dumps(output, sort_keys=True, indent=2)) else: outputtotext(output)
def connect_and_wait(self): try: with Client(f'ws://{self.remote_ip}:6000/websocket', reserved_ports=True) as c: self.client = c self.connected.set() # Subscribe to all events on connection with self._subscribe_lock: for name in self._subscriptions: self.client.subscribe( name, partial(self._sub_callback, name)) self._on_connect() c._closed.wait() except OSError as e: if e.errno in ( errno. EPIPE, # Happens when failover is configured on cxl device that has no link errno.ENETDOWN, errno.EHOSTDOWN, errno.ENETUNREACH, errno.EHOSTUNREACH, errno.ECONNREFUSED, ) or isinstance(e, socket.timeout): raise ConnectionRefusedError() raise finally: if self.connected.is_set(): # Only happens if we have successfully connected once self._on_disconnect() self.client = None self.connected.clear()
def read(self): if not self.initialized: self.init() if not self.initialized: return if not self.disks: return try: with Client() as c: temperatures = c.call('disk.temperatures', self.disks, self.powermode) for disk, temp in temperatures.items(): if temp is not None: self.dispatch_value(disk, 'temperature', temp, data_type='temperature') except CallTimeout: collectd.error("Timeout collecting disk temperatures") except Exception: collectd.error(traceback.format_exc())
def main(): parser = argparse.ArgumentParser() parser.add_argument('job', type=int) args = parser.parse_args() with Client() as c: middleware = FakeMiddleware(c) return middleware._call_job(args.job)
def init(self): collectd.info('Initializing "disktemp" plugin') with Client() as c: self.disks = [ disk['devname'] for disk in c.call('disk.query', [['togglesmart', '=', True]]) ] self.powermode = c.call('smart.config')['powermode'].lower()
def main(): client = Client() try: hostname = socket.gethostname().split(".")[0] except IndexError: hostname = socket.gethostname() ssh_service = client.call('datastore.query', 'services.services', [('srv_service', '=', 'ssh'), ('srv_enable', '=', True)]) if ssh_service: sshport = client.call('datastore.query', 'services.ssh', None, {'get': True})['ssh_tcpport'] t = threading.Thread(target=register, args=(hostname, '_ssh._tcp.', sshport)) t.daemon = False t.start() t = threading.Thread(target=register, args=(hostname, '_sftp-ssh._tcp.', sshport)) t.daemon = False t.start() webui = client.call('datastore.query', 'system.settings') if (webui[0]['stg_guiprotocol'] == 'http' or webui[0]['stg_guiprotocol'] == 'httphttps'): http_port = int(webui[0]['stg_guiport'] or 80) t = threading.Thread(target=register, args=(hostname, '_http._tcp.', http_port)) t.daemon = False t.start() t = threading.Thread(target=register, args=(hostname, '_middlwre-http._tcp.', http_port)) t.daemon = False t.start() if (webui[0]['stg_guiprotocol'] == 'https' or webui[0]['stg_guiprotocol'] == 'httphttps'): https_port = int(webui[0]['stg_guihttpsport'] or 443) t = threading.Thread(target=register, args=(hostname, '_https._tcp.', https_port)) t.daemon = False t.start() t = threading.Thread(target=register, args=(hostname, '_middlwre-https._tcp.', https_port)) t.daemon = False t.start()
def client(py_exceptions=True): if "NODE_A_IP" in os.environ: password = os.environ["APIPASS"] else: password = os.environ["MIDDLEWARE_TEST_PASSWORD"] with Client(f"ws://{host()}/websocket", py_exceptions=py_exceptions) as c: c.call("auth.login", "root", password) yield c
def receive_events(): c = Client('ws+unix:///var/run/middlewared-internal.sock', py_exceptions=True) c.subscribe('core.environ', lambda *args, **kwargs: environ_update(kwargs['fields'])) c.subscribe('core.reconfigure_logging', reconfigure_logging) environ_update(c.call('core.environ'))
def read(self): try: with Client() as c: temperatures = c.call('disk.temperatures', self.disks, self.powermode, self.smartctl_args) for disk, temp in temperatures.items(): if temp is not None: self.dispatch_value(disk, 'temperature', temp, data_type='temperature') except Exception: collectd.error(traceback.format_exc())
def init(self): collectd.info('Initializing "disktemp" plugin') try: with Client() as c: self.disks = c.call('disk.disks_for_temperature_monitoring') self.powermode = c.call('smart.config')['powermode'] except Exception: collectd.error(traceback.format_exc()) else: self.initialized = True
def main(): device = os.environ.get("SMARTD_DEVICE") if device is None: return message = os.environ.get("SMARTD_MESSAGE") if message is None: return with Client() as c: c.call("alert.oneshot_create", "SMART", {"device": device, "message": message})
def __init__(self): conf = ConfigTarget() self.rest = Client( f'http://{conf.target_hostname()}', conf.target_api(), conf.target_username(), conf.target_password(), ) self.ws = WSClient(f'ws://{conf.target_hostname()}/websocket') self.ws.call('auth.login', conf.target_username(), conf.target_password())
def unlock(): with Client() as c: try: c.call('disk.sed_unlock_all') except ClientException as e: if e.errno == errno.EACCES: print('SED disks failed to unlocked') else: raise else: print('All SED disks unlocked')
def _call(self, name, serviceobj, methodobj, params=None, app=None, pipes=None, io_thread=False, job=None): try: with Client('ws+unix:///var/run/middlewared-internal.sock', py_exceptions=True) as c: self.client = c job_options = getattr(methodobj, '_job', None) if job and job_options: params = list(params) if params else [] params.insert(0, FakeJob(job['id'], self.client)) return methodobj(*params) finally: self.client = None
def init(self): collectd.info('Initializing "disktemp" plugin') with Client() as c: self.disks = [disk['devname'] for disk in c.call('disk.query', [['devname', '!=', None], ['togglesmart', '=', True], # Polling for disk temperature does # not allow them to go to sleep # automatically ['hddstandby', '=', 'ALWAYS ON']])] self.smartctl_args = c.call('disk.smartctl_args_for_devices', self.disks) self.powermode = c.call('smart.config')['powermode']
def main(): client = Client() smb_conf_path = "/usr/local/etc/smb4.conf" smb4_tdb = [] smb4_conf = [] smb4_shares = [] backup_secrets_database() smb4_setup(client) old_samba4_datasets = get_old_samba4_datasets(client) if migration_available(old_samba4_datasets): do_migration(client, old_samba4_datasets) role = get_server_role(client) generate_smbusers(client) generate_smb4_tdb(client, smb4_tdb) generate_smb4_conf(client, smb4_conf, role) generate_smb4_system_shares(client, smb4_shares) generate_smb4_shares(client, smb4_shares) if role == 'dc' and not client.call('notifier.samba4', 'domain_provisioned'): provision_smb4(client) with open(smb_conf_path, "w") as f: for line in smb4_conf: f.write(line + '\n') for line in smb4_shares: f.write(line + '\n') smb4_set_SID(client, role) if role == 'member' and smb4_ldap_enabled(client): set_ldap_password(client) backup_secrets_database() if role != 'dc': if not client.call('notifier.samba4', 'users_imported'): smb4_import_users( client, smb_conf_path, smb4_tdb, "/var/db/samba4/private/passdb.tdb" ) smb4_grant_rights() client.call('notifier.samba4', 'user_import_sentinel_file_create') smb4_map_groups(client) if role == 'member' and client.call('notifier.common', 'system', 'activedirectory_enabled') and idmap_backend_rfc2307(client): set_idmap_rfc2307_secret(client) restore_secrets_database()
def main(): """Use the django ORM to generate a config file. We'll build the config file as a series of lines, and once that is done write it out in one go""" map_acls_mode = False afp_config = "/usr/local/etc/afp.conf" cf_contents = [] client = Client() afp = Struct(client.call('datastore.query', 'services.afp', None, {'get': True})) cf_contents.append("[Global]\n") uam_list = ['uams_dhx.so', 'uams_dhx2.so'] if afp.afp_srv_guest: uam_list.append('uams_guest.so') cf_contents.append('\tguest account = %s\n' % afp.afp_srv_guest_user) # uams_gss.so bails out with an error if kerberos isn't configured if client.call('datastore.query', 'directoryservice.kerberoskeytab', None, {'count': True}) > 0: uam_list.append('uams_gss.so') cf_contents.append('\tuam list = %s\n' % (" ").join(uam_list)) if afp.afp_srv_bindip: cf_contents.append("\tafp listen = %s\n" % ' '.join(afp.afp_srv_bindip)) ifaces = get_interface(afp.afp_srv_bindip) cf_contents.append("\tafp interfaces = %s\n" % ' '.join(ifaces)) cf_contents.append("\tmax connections = %s\n" % afp.afp_srv_connections_limit) cf_contents.append("\tmimic model = RackMac\n") cf_contents.append("\tafpstats = yes\n") if afp.afp_srv_dbpath: cf_contents.append("\tvol dbnest = no\n") cf_contents.append("\tvol dbpath = %s\n" % afp.afp_srv_dbpath) else: cf_contents.append("\tvol dbnest = yes\n") if afp.afp_srv_global_aux: cf_contents.append("\t%s\n" % afp.afp_srv_global_aux) if afp.afp_srv_map_acls: cf_contents.append("\tmap acls = %s\n" % afp.afp_srv_map_acls) if afp.afp_srv_chmod_request: cf_contents.append("\tchmod request = %s\n" % afp.afp_srv_chmod_request) if afp.afp_srv_map_acls == 'mode' and client.call('notifier.common', 'system', 'activedirectory_enabled'): map_acls_mode = True if map_acls_mode: ad = Struct(client.call('notifier.directoryservice', 'AD')) cf_contents.append("\tldap auth method = %s\n" % "simple") cf_contents.append("\tldap auth dn = %s\n" % ad.binddn) cf_contents.append("\tldap auth pw = %s\n" % ad.bindpw) cf_contents.append("\tldap server = %s\n" % ad.domainname) # This should be configured when using this option if ad.userdn: cf_contents.append("\tldap userbase = %s\n" % ad.userdn) cf_contents.append("\tldap userscope = %s\n" % "sub") # This should be configured when using this option if ad.groupdn: cf_contents.append("\tldap groupbase = %s\n" % ad.groupdn) cf_contents.append("\tldap groupscope = %s\n" % "sub") cf_contents.append("\tldap user filter = %s\n" % "objectclass=user") cf_contents.append("\tldap group filter = %s\n" % "objectclass=group") cf_contents.append("\tldap uuid attr = %s\n" % "objectGUID") cf_contents.append("\tldap uuid encoding = %s\n" % "ms-guid") cf_contents.append("\tldap name attr = %s\n" % "sAMAccountName") cf_contents.append("\tldap group attr = %s\n" % "sAMAccountName") cf_contents.append("\tlog file = %s\n" % "/var/log/afp.log") cf_contents.append("\tlog level = %s\n" % "default:info") cf_contents.append("\n") for share in client.call('datastore.query', 'sharing.afp_share'): share = Struct(share) if share.afp_home: cf_contents.append("[Homes]\n") cf_contents.append("\tbasedir regex = %s\n" % share.afp_path) if share.afp_name and share.afp_name != "Homes": cf_contents.append("\thome name = %s\n" % share.afp_name) else: cf_contents.append("[%s]\n" % share.afp_name) cf_contents.append("\tpath = %s\n" % share.afp_path) if share.afp_allow: cf_contents.append("\tvalid users = %s\n" % share.afp_allow) if share.afp_deny: cf_contents.append("\tinvalid users = %s\n" % share.afp_deny) if share.afp_hostsallow: cf_contents.append("\thosts allow = %s\n" % share.afp_hostsallow) if share.afp_hostsdeny: cf_contents.append("\thosts deny = %s\n" % share.afp_hostsdeny) if share.afp_ro: cf_contents.append("\trolist = %s\n" % share.afp_ro) if share.afp_rw: cf_contents.append("\trwlist = %s\n" % share.afp_rw) if share.afp_timemachine: cf_contents.append("\ttime machine = yes\n") if not share.afp_nodev: cf_contents.append("\tcnid dev = no\n") if share.afp_nostat: cf_contents.append("\tstat vol = no\n") if not share.afp_upriv: cf_contents.append("\tunix priv = no\n") else: if share.afp_fperm and not map_acls_mode: cf_contents.append("\tfile perm = %s\n" % share.afp_fperm) if share.afp_dperm and not map_acls_mode: cf_contents.append("\tdirectory perm = %s\n" % share.afp_dperm) if share.afp_umask and not map_acls_mode: cf_contents.append("\tumask = %s\n" % share.afp_umask) cf_contents.append("\tveto files = .windows/.mac/\n") if map_acls_mode: cf_contents.append("\tacls = yes\n") # Do not fail if aux params are not properly entered by the user try: aux_params = ["\t{0}\n".format(p) for p in share.afp_auxparams.split("\n")] except: pass else: cf_contents += aux_params # Update TimeMachine special files timemachine_supported_path = os.path.join(share.afp_path, ".com.apple.timemachine.supported") timemachine_quota_plist_path = os.path.join(share.afp_path, ".com.apple.TimeMachine.quota.plist") timemachine_quota_plist_managed_flag = os.path.join(share.afp_path, ".com.apple.TimeMachine.quota.plist.FreeNAS-managed") if share.afp_timemachine and share.afp_timemachine_quota: try: with open(timemachine_supported_path, "w"): pass except IOError: pass try: with open(timemachine_quota_plist_path, "w") as f: f.write(textwrap.dedent("""\ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>GlobalQuota</key> <integer>%d</integer> </dict> </plist> """ % (share.afp_timemachine_quota * 1024 * 1024 * 1024))) except IOError: pass try: with open(timemachine_quota_plist_managed_flag, "w") as f: pass except IOError: pass try: stat = os.stat(share.afp_path) os.chmod(timemachine_supported_path, 0o644) os.chown(timemachine_supported_path, stat.st_uid, stat.st_gid) os.chmod(timemachine_quota_plist_path, 0o644) os.chown(timemachine_quota_plist_path, stat.st_uid, stat.st_gid) os.chmod(timemachine_quota_plist_managed_flag, 0o644) os.chown(timemachine_quota_plist_managed_flag, stat.st_uid, stat.st_gid) except IOError: pass else: if os.path.exists(timemachine_quota_plist_managed_flag): try: os.unlink(timemachine_supported_path) except IOError: pass try: os.unlink(timemachine_quota_plist_path) except IOError: pass with open(afp_config, "w") as fh: for line in cf_contents: fh.write(line)
def main(): client = Client() ldap_conf = "/usr/local/etc/nss_ldap.conf" if client.call('notifier.common', 'system', 'ldap_enabled'): ldap_conf_ldap(client, ldap_conf)
def main(): nsswitch_conf = { 'group': ['files'], 'hosts': ['files', 'mdns', 'dns'], 'networks': ['files'], 'passwd': ['files'], 'shells': ['files'], 'services': ['files'], 'protocols': ['files'], 'rpc': ['files'], 'sudoers': ['files'] } verb = "start" if len(sys.argv) > 1: verb = sys.argv[1].lower() client = Client() activedirectory_enabled = client.call('notifier.common', 'system', 'activedirectory_enabled') domaincontroller_enabled = client.call('notifier.common', 'system', 'domaincontroller_enabled') ldap_enabled = client.call('notifier.common', 'system', 'ldap_enabled') nis_enabled = client.call('notifier.common', 'system', 'nis_enabled') nt4_enabled = client.call('notifier.common', 'system', 'nt4_enabled') if verb == 'start': if activedirectory_enabled and \ client.call('notifier.common', 'system', 'activedirectory_has_unix_extensions') and \ client.call('notifier.common', 'system', 'activedirectory_has_principal'): nsswitch_conf['passwd'].append('sss') nsswitch_conf['group'].append('sss') elif activedirectory_enabled or \ domaincontroller_enabled or nt4_enabled: nsswitch_conf['passwd'].append('winbind') nsswitch_conf['group'].append('winbind') #if nt4_enabled(): # nsswitch_conf['hosts'].append('wins') if ldap_enabled and client.call('notifier.common', 'system', 'ldap_anonymous_bind'): nsswitch_conf['passwd'].append('ldap') nsswitch_conf['group'].append('ldap') elif ldap_enabled: nsswitch_conf['passwd'].append('sss') nsswitch_conf['group'].append('sss') if client.call('notifier.common', 'system', 'ldap_sudo_configured'): nsswitch_conf['sudoers'].append('sss') if nis_enabled: nsswitch_conf['passwd'].append('nis') nsswitch_conf['group'].append('nis') nsswitch_conf['hosts'].append('nis') try: fd = os.open(NSSWITCH_CONF_PATH, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0644) for key in nsswitch_conf: line = "%s: %s\n" % ( key.strip(), string.join(map(lambda x: x.strip(), nsswitch_conf[key]), ' ') ) os.write(fd, line) os.close(fd) except Exception as e: print >> sys.stderr, "can't create %s: %s" % (NSSWITCH_CONF_PATH, e) sys.exit(1)
def __enter__(self): self.client = Client() return self.client
def main(): """Use the django ORM to generate a config file. We'll build the config file as a series of lines, and once that is done write it out in one go""" map_acls_mode = False afp_config = "/usr/local/etc/afp.conf" cf_contents = [] client = Client() afp = Struct(client.call("datastore.query", "services.afp", None, {"get": True})) cf_contents.append("[Global]\n") uam_list = ["uams_dhx.so", "uams_dhx2.so"] if afp.afp_srv_guest: uam_list.append("uams_guest.so") cf_contents.append("\tguest account = %s\n" % afp.afp_srv_guest_user) # uams_gss.so bails out with an error if kerberos isn't configured if client.call("datastore.query", "directoryservice.kerberoskeytab", None, {"count": True}) > 0: uam_list.append("uams_gss.so") cf_contents.append("\tuam list = %s\n" % (" ").join(uam_list)) if afp.afp_srv_bindip: cf_contents.append("\tafp listen = %s\n" % " ".join(afp.afp_srv_bindip)) cf_contents.append("\tmax connections = %s\n" % afp.afp_srv_connections_limit) cf_contents.append("\tmimic model = RackMac\n") if afp.afp_srv_dbpath: cf_contents.append("\tvol dbnest = no\n") cf_contents.append("\tvol dbpath = %s\n" % afp.afp_srv_dbpath) else: cf_contents.append("\tvol dbnest = yes\n") if afp.afp_srv_global_aux: cf_contents.append("\t%s" % afp.afp_srv_global_aux.encode("utf8")) if afp.afp_srv_map_acls: cf_contents.append("\tmap acls = %s\n" % afp.afp_srv_map_acls) if afp.afp_srv_map_acls == "mode" and client.call("notifier.common", "system", "activedirectory_enabled"): map_acls_mode = True if map_acls_mode: ad = Struct(client.call("notifier.directoryservice", "AD")) cf_contents.append("\tldap auth method = %s\n" % "simple") cf_contents.append("\tldap auth dn = %s\n" % ad.binddn) cf_contents.append("\tldap auth pw = %s\n" % ad.bindpw) cf_contents.append("\tldap server = %s\n" % ad.domainname) # This should be configured when using this option if ad.userdn: cf_contents.append("\tldap userbase = %s\n" % ad.userdn) cf_contents.append("\tldap userscope = %s\n" % "sub") # This should be configured when using this option if ad.groupdn: cf_contents.append("\tldap groupbase = %s\n" % ad.groupdn) cf_contents.append("\tldap groupscope = %s\n" % "sub") cf_contents.append("\tldap user filter = %s\n" % "objectclass=user") cf_contents.append("\tldap group filter = %s\n" % "objectclass=group") cf_contents.append("\tldap uuid attr = %s\n" % "objectGUID") cf_contents.append("\tldap uuid encoding = %s\n" % "ms-guid") cf_contents.append("\tldap name attr = %s\n" % "sAMAccountName") cf_contents.append("\tldap group attr = %s\n" % "sAMAccountName") cf_contents.append("\n") if afp.afp_srv_homedir_enable: cf_contents.append("[Homes]\n") cf_contents.append("\tbasedir regex = %s\n" % afp.afp_srv_homedir) if afp.afp_srv_homename: cf_contents.append("\thome name = %s\n" % afp.afp_srv_homename) cf_contents.append("\n") for share in client.call("datastore.query", "sharing.afp_share"): share = Struct(share) cf_contents.append("[%s]\n" % share.afp_name) cf_contents.append("\tpath = %s\n" % share.afp_path) if share.afp_allow: cf_contents.append("\tvalid users = %s\n" % share.afp_allow) if share.afp_deny: cf_contents.append("\tinvalid users = %s\n" % share.afp_deny) if share.afp_hostsallow: cf_contents.append("\thosts allow = %s\n" % share.afp_hostsallow) if share.afp_hostsdeny: cf_contents.append("\thosts deny = %s\n" % share.afp_hostsdeny) if share.afp_ro: cf_contents.append("\trolist = %s\n" % share.afp_ro) if share.afp_rw: cf_contents.append("\trwlist = %s\n" % share.afp_rw) if share.afp_timemachine: cf_contents.append("\ttime machine = yes\n") if not share.afp_nodev: cf_contents.append("\tcnid dev = no\n") if share.afp_nostat: cf_contents.append("\tstat vol = no\n") if not share.afp_upriv: cf_contents.append("\tunix priv = no\n") else: if share.afp_fperm and not map_acls_mode: cf_contents.append("\tfile perm = %s\n" % share.afp_fperm) if share.afp_dperm and not map_acls_mode: cf_contents.append("\tdirectory perm = %s\n" % share.afp_dperm) if share.afp_umask and not map_acls_mode: cf_contents.append("\tumask = %s\n" % share.afp_umask) cf_contents.append("\tveto files = .windows/.mac/\n") if map_acls_mode: cf_contents.append("\tacls = yes\n") with open(afp_config, "w") as fh: for line in cf_contents: fh.write(line)
def main(): """Use middleware client to generate a config file.""" client = Client() # Obtain the various webdav configuration details from services object webby = Struct(client.call('datastore.query', 'services.WebDAV', None, {'get': True})) dav_tcpport = webby.webdav_tcpport dav_tcpportssl = webby.webdav_tcpportssl dav_protocol = webby.webdav_protocol dav_auth_type = webby.webdav_htauth dav_passwd = webby.webdav_password if dav_protocol != 'http': dav_ssl_certfile = '/etc/certificates/%s.crt' % webby.webdav_certssl.cert_name dav_ssl_keyfile = '/etc/certificates/%s.key' % webby.webdav_certssl.cert_name # Declaring the config file locations as well as making some # generic config-text blocks dav_config_file = '/etc/local/apache24/Includes/webdav.conf' davssl_config_file = '/etc/local/apache24/Includes/webdav-ssl.conf' dav_auth_text = "" if dav_auth_type == 'digest': dav_auth_text = "AuthDigestProvider file" dav_config_pretext = """ DavLockDB "/etc/local/apache24/var/DavLock" AssignUserId webdav webdav <Directory /> AuthType %s AuthName webdav AuthUserFile "/etc/local/apache24/webdavht%s" %s Require valid-user Dav On IndexOptions Charset=utf-8 AddDefaultCharset UTF-8 AllowOverride None Order allow,deny Allow from all Options Indexes FollowSymLinks </Directory>\n""" % (dav_auth_type, dav_auth_type, dav_auth_text) dav_config_posttext = """ # The following directives disable redirects on non-GET requests for # a directory that does not include the trailing slash. This fixes a # problem with several clients that do not appropriately handle # redirects for folders with DAV methods. BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully BrowserMatch "MS FrontPage" redirect-carefully BrowserMatch "^WebDrive" redirect-carefully BrowserMatch "^WebDAVFS/1.[01234]" redirect-carefully BrowserMatch "^gnome-vfs/1.0" redirect-carefully BrowserMatch "^XML Spy" redirect-carefully BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully BrowserMatch " Konqueror/4" redirect-carefully </VirtualHost>""" # Generate the webdav password files dav_passwd_change(dav_passwd, dav_auth_type) # Check to see if there is a webdav lock databse directory, if not create # one. Take care of necessary permissions whilst creating it! oscmd = "/etc/local/apache24/var" if not os.path.isdir(oscmd): os.mkdir(oscmd, 0o774) _chownrecur(oscmd, pwd.getpwnam("webdav").pw_uid, grp.getgrnam("webdav").gr_gid) # Now getting to the actual webdav share details and all webshares = [Struct(i) for i in client.call('datastore.query', 'sharing.WebDAV_Share')] if dav_protocol in ['http', 'httphttps']: if dav_protocol == 'http': with open(davssl_config_file, 'w') as f2: f2.write("") with open(dav_config_file, 'w') as f: f.write(" Listen " + str(dav_tcpport) + "\n") f.write("\t <VirtualHost *:" + str(dav_tcpport) + ">\n") f.write(dav_config_pretext) for share in webshares: temp_path = """ "%s" """ % share.webdav_path f.write("\t Alias /" + share.webdav_name + temp_path + "\n") f.write("\t <Directory " + temp_path + ">\n") f.write("\t </Directory>\n") if share.webdav_ro == 1: f.write( "\t <Location /" + share.webdav_name + ">\n\t\t AllowMethods GET OPTIONS PROPFIND\n\t </Location>\n" ) if share.webdav_perm: _pipeopen("chown -R webdav:webdav %s" % share.webdav_path) f.write(dav_config_posttext) if dav_protocol in ['https', 'httphttps']: if dav_protocol == 'https': with open(dav_config_file, 'w') as f: f.write("") with open(davssl_config_file, 'w') as f2: f2.write(" Listen " + str(dav_tcpportssl) + "\n") f2.write("\t <VirtualHost *:" + str(dav_tcpportssl) + ">\n") f2.write("\t SSLEngine on\n") f2.write("""\t SSLCertificateFile "%s"\n""" % dav_ssl_certfile) f2.write("""\t SSLCertificateKeyFile "%s"\n""" % dav_ssl_keyfile) f2.write("\t SSLProtocol +TLSv1 +TLSv1.1 +TLSv1.2\n\t SSLCipherSuite HIGH:MEDIUM\n") f2.write(dav_config_pretext) # Note: The for loop below is essentially code duplication, # but since two different files are being written to I could # not at the moment find a more efficient way of doing this. # (if you can fix it, please do so) for share in webshares: temp_path = """ "%s" """ % share.webdav_path f2.write("\t Alias /" + share.webdav_name + temp_path + "\n") f2.write("\t <Directory " + temp_path + ">\n") f2.write("\t </Directory>\n") if share.webdav_ro == 1: f2.write( "\t <Location /" + share.webdav_name + ">\n\t\t AllowMethods GET OPTIONS PROPFIND\n\t </Location>\n" ) # Note: the 'and' in the if statement below is to ensure # that we do not waste time in changin permisions twice # (once while in http block) if (share.webdav_perm and dav_protocol != "httphttps"): _pipeopen("chown -R webdav:webdav %s" % share.webdav_path) f2.write(dav_config_posttext)
def main(): client = Client() realms = client.call('datastore.query', 'directoryservice.KerberosRealm') try: settings = client.call('datastore.query', 'directoryservice.KerberosSettings') if settings: settings = Struct(settings[0]) else: settings = None except: settings = None default_realm = None if len(sys.argv) == 3 and sys.argv[1].lower() == 'default': default_realm = sys.argv[2].upper() kc = KerberosConfig(settings=settings, default_realm=default_realm) kc.create_default_config() ad = ldap = None ldap_objects = client.call('datastore.query', 'directoryservice.LDAP') if ldap_objects and ldap_objects[0]['ldap_enable']: ldap = Struct(client.call('notifier.directoryservice', 'LDAP', timeout=fs().directoryservice.kerberos.timeout.start)) ad_objects = client.call('datastore.query', 'directoryservice.ActiveDirectory') if ad_objects and ad_objects[0]['ad_enable']: ad = Struct(client.call('notifier.directoryservice', 'AD', timeout=fs().directoryservice.kerberos.timeout.start)) for kr in realms: kr = Struct(kr) if not kr.krb_realm: continue krb_kdc, krb_admin_server, krb_kpasswd_server = get_kerberos_servers( kr, ad, ldap ) bc = KerberosConfigBindingCollection(name=kr.krb_realm) if krb_kdc: bc.append( KerberosConfigBinding( name="kdc", value=krb_kdc ) ) if krb_admin_server: bc.append( KerberosConfigBinding( name="admin_server", value=krb_admin_server ) ) if krb_kpasswd_server: bc.append( KerberosConfigBinding( name="kpasswd_server", value=krb_kpasswd_server ) ) bc.append( KerberosConfigBinding( name="default_domain", value=kr.krb_realm ) ) kc.add_bindings(['realms'], bc) bc = KerberosConfigBindingCollection() bc.append( KerberosConfigBinding( name=kr.krb_realm.lower(), value=kr.krb_realm.upper() ) ) bc.append( KerberosConfigBinding( name=".%s" % kr.krb_realm.lower(), value=kr.krb_realm.upper() ) ) bc.append( KerberosConfigBinding( name=kr.krb_realm.upper(), value=kr.krb_realm.upper() ) ) bc.append( KerberosConfigBinding( name=".%s" % kr.krb_realm.upper(), value=kr.krb_realm.upper() ) ) kc.add_bindings(['domain_realm'], bc) fp = open("/etc/krb5.conf", "w+") kc.generate_krb5_conf(stdout=fp) fp.close()
def main(): """Use the middleware client to generate a config file. We'll build the config file as a series of lines, and once that is done write it out in one go""" client = Client() gconf = Struct(client.call('datastore.query', 'services.iSCSITargetGlobalConfiguration', None, {'get': True})) if gconf.iscsi_isns_servers: for server in gconf.iscsi_isns_servers.split(' '): addline('isns-server %s\n\n' % server) # Generate the portal-group section addline('portal-group default {\n}\n\n') for portal in client.call('datastore.query', 'services.iSCSITargetPortal'): portal = Struct(portal) # Prepare auth group for the portal group if portal.iscsi_target_portal_discoveryauthgroup: auth_list = [ Struct(i) for i in client.call('datastore.query', 'services.iSCSITargetAuthCredential', [('iscsi_target_auth_tag', '=', portal.iscsi_target_portal_discoveryauthgroup)]) ] else: auth_list = [] agname = '4pg%d' % portal.iscsi_target_portal_tag auth = auth_group_config(auth_tag=agname, auth_list=auth_list, auth_type=portal.iscsi_target_portal_discoveryauthmethod) addline("portal-group pg%s {\n" % portal.iscsi_target_portal_tag) addline("\tdiscovery-filter portal-name\n") if auth: addline("\tdiscovery-auth-group ag%s\n" % agname) else: addline("\tdiscovery-auth-group no-authentication\n") listen = [ Struct(i) for i in client.call('datastore.query', 'services.iSCSITargetPortalIP', [('iscsi_target_portalip_portal', '=', portal.id)]) ] for obj in listen: if ':' in obj.iscsi_target_portalip_ip: address = '[%s]' % obj.iscsi_target_portalip_ip else: address = obj.iscsi_target_portalip_ip addline("\tlisten %s:%s\n" % (address, obj.iscsi_target_portalip_port)) addline("\toption ha_shared on\n") addline("}\n\n") # Cache zpool threshold poolthreshold = {} zpoollist = client.call('notifier.zpool_list') # Generate the LUN section for extent in client.call('datastore.query', 'services.iSCSITargetExtent'): extent = Struct(extent) path = extent.iscsi_target_extent_path poolname = None lunthreshold = None if extent.iscsi_target_extent_type == 'Disk': disk = client.call('datastore.query', 'storage.Disk', [('disk_identifier', '=', path)], {'order_by': ['disk_enabled']}) if not disk: continue disk = Struct(disk[0]) if disk.disk_multipath_name: path = "/dev/multipath/%s" % disk.disk_multipath_name else: path = "/dev/%s" % client.call('notifier.identifier_to_device', disk.disk_identifier) else: if not path.startswith("/mnt"): poolname = path.split('/', 2)[1] if gconf.iscsi_pool_avail_threshold: if poolname in zpoollist: poolthreshold[poolname] = int( zpoollist.get(poolname).get('size') * ( gconf.iscsi_pool_avail_threshold / 100.0 ) ) if extent.iscsi_target_extent_avail_threshold: zvolname = path.split('/', 1)[1] zfslist = client.call('notifier.zfs_list', zvolname, False, False, False, ['volume']) if zfslist: lunthreshold = int(zfslist[zvolname]['volsize'] * (extent.iscsi_target_extent_avail_threshold / 100.0)) path = "/dev/" + path else: if extent.iscsi_target_extent_avail_threshold and os.path.exists(path): try: stat = os.stat(path) lunthreshold = int(stat.st_size * (extent.iscsi_target_extent_avail_threshold / 100.0)) except OSError: pass addline("lun \"%s\" {\n" % extent.iscsi_target_extent_name) size = extent.iscsi_target_extent_filesize addline("\tpath \"%s\"\n" % path) addline("\tblocksize %s\n" % extent.iscsi_target_extent_blocksize) if extent.iscsi_target_extent_pblocksize: addline("\toption pblocksize 0\n") addline("\tserial \"%s\"\n" % (extent.iscsi_target_extent_serial, )) padded_serial = extent.iscsi_target_extent_serial if not extent.iscsi_target_extent_xen: for i in xrange(31 - len(extent.iscsi_target_extent_serial)): padded_serial += " " addline('\tdevice-id "iSCSI Disk %s"\n' % padded_serial) if size != "0": if size.endswith('B'): size = size.strip('B') addline("\t\tsize %s\n" % size) # We can't change the vendor name of existing # LUNs without angering VMWare, but we can # use the right names going forward. if extent.iscsi_target_extent_legacy is True: addline('\toption vendor "FreeBSD"\n') else: if client.call('notifier.is_freenas'): addline('\toption vendor "FreeNAS"\n') else: addline('\toption vendor "TrueNAS"\n') addline('\toption product "iSCSI Disk"\n') addline('\toption revision "0123"\n') addline('\toption naa %s\n' % extent.iscsi_target_extent_naa) if extent.iscsi_target_extent_insecure_tpc: addline('\toption insecure_tpc on\n') if lunthreshold: addline('\toption avail-threshold %s\n' % lunthreshold) if poolname is not None and poolname in poolthreshold: addline('\toption pool-avail-threshold %s\n' % poolthreshold[poolname]) if extent.iscsi_target_extent_rpm == "Unknown": addline('\toption rpm 0\n') elif extent.iscsi_target_extent_rpm == "SSD": addline('\toption rpm 1\n') else: addline('\toption rpm %s\n' % extent.iscsi_target_extent_rpm) if extent.iscsi_target_extent_ro: addline('\toption readonly on\n') addline("}\n") addline("\n") # Generate the target section target_basename = gconf.iscsi_basename for target in client.call('datastore.query', 'services.iSCSITarget'): target = Struct(target) authgroups = {} for grp in client.call('datastore.query', 'services.iscsitargetgroups', [('iscsi_target', '=', target.id)]): grp = Struct(grp) if grp.iscsi_target_authgroup: auth_list = [ Struct(i) for i in client.call('datastore.query', 'services.iSCSITargetAuthCredential', [('iscsi_target_auth_tag', '=', grp.iscsi_target_authgroup)]) ] else: auth_list = [] agname = '4tg%d_%d' % (target.id, grp.id) if auth_group_config(auth_tag=agname, auth_list=auth_list, auth_type=grp.iscsi_target_authtype, initiator=grp.iscsi_target_initiatorgroup): authgroups[grp.id] = agname if (target.iscsi_target_name.startswith("iqn.") or target.iscsi_target_name.startswith("eui.") or target.iscsi_target_name.startswith("naa.")): addline("target %s {\n" % target.iscsi_target_name) else: addline("target %s:%s {\n" % (target_basename, target.iscsi_target_name)) if target.iscsi_target_alias: addline("\talias \"%s\"\n" % target.iscsi_target_alias) elif target.iscsi_target_name: addline("\talias \"%s\"\n" % target.iscsi_target_name) for fctt in client.call('datastore.query', 'services.fibrechanneltotarget', [('fc_target', '=', target.id)]): fctt = Struct(fctt) addline("\tport %s\n" % fctt.fc_port) for grp in client.call('datastore.query', 'services.iscsitargetgroups', [('iscsi_target', '=', target.id)]): grp = Struct(grp) agname = authgroups.get(grp.id) or None addline("\tportal-group pg%d %s\n" % ( grp.iscsi_target_portalgroup.iscsi_target_portal_tag, 'ag' + agname if agname else 'no-authentication', )) addline("\n") used_lunids = [ o['iscsi_lunid'] for o in client.call('datastore.query', 'services.iscsitargettoextent', [('iscsi_target', '=', target.id), ('iscsi_lunid', '!=', None)]) ] cur_lunid = 0 for t2e in client.call('datastore.query', 'services.iscsitargettoextent', [('iscsi_target', '=', target.id)], {'extra': {'select': {'null_first': 'iscsi_lunid IS NULL'}}, 'order_by': ['null_first', 'iscsi_lunid']}): t2e = Struct(t2e) if t2e.iscsi_lunid is None: while cur_lunid in used_lunids: cur_lunid += 1 addline("\tlun %s \"%s\"\n" % (cur_lunid, t2e.iscsi_extent.iscsi_target_extent_name)) cur_lunid += 1 else: addline("\tlun %s \"%s\"\n" % (t2e.iscsi_lunid, t2e.iscsi_extent.iscsi_target_extent_name)) addline("}\n\n") os.umask(077) # Write out the CTL config file fh = open(ctl_config, "w") for line in cf_contents: fh.write(line) fh.close() # Write out the CTL config file with redacted CHAP passwords fh = open(ctl_config_shadow, "w") for line in cf_contents_shadow: fh.write(line) fh.close()
def main(): """Use the django ORM to generate a config file. We'll build the config file as a series of lines, and once that is done write it out in one go""" map_acls_mode = False afp_config = "/usr/local/etc/afp.conf" cf_contents = [] client = Client() afp = Struct(client.call('datastore.query', 'services.afp', None, {'get': True})) cf_contents.append("[Global]\n") uam_list = ['uams_dhx.so', 'uams_dhx2.so'] if afp.afp_srv_guest: uam_list.append('uams_guest.so') cf_contents.append('\tguest account = %s\n' % afp.afp_srv_guest_user) # uams_gss.so bails out with an error if kerberos isn't configured if client.call('datastore.query', 'directoryservice.kerberoskeytab', None, {'count': True}) > 0: uam_list.append('uams_gss.so') cf_contents.append('\tuam list = %s\n' % (" ").join(uam_list)) if afp.afp_srv_bindip: cf_contents.append("\tafp listen = %s\n" % ' '.join(afp.afp_srv_bindip)) ifaces = get_interface(afp.afp_srv_bindip) cf_contents.append("\tafp interfaces = %s\n" % ' '.join(ifaces)) cf_contents.append("\tmax connections = %s\n" % afp.afp_srv_connections_limit) cf_contents.append("\tmimic model = RackMac\n") if afp.afp_srv_dbpath: cf_contents.append("\tvol dbnest = no\n") cf_contents.append("\tvol dbpath = %s\n" % afp.afp_srv_dbpath) else: cf_contents.append("\tvol dbnest = yes\n") if afp.afp_srv_global_aux: cf_contents.append("\t%s\n" % afp.afp_srv_global_aux) if afp.afp_srv_map_acls: cf_contents.append("\tmap acls = %s\n" % afp.afp_srv_map_acls) if afp.afp_srv_chmod_request: cf_contents.append("\tchmod request = %s\n" % afp.afp_srv_chmod_request) if afp.afp_srv_map_acls == 'mode' and client.call('notifier.common', 'system', 'activedirectory_enabled'): map_acls_mode = True if map_acls_mode: ad = Struct(client.call('notifier.directoryservice', 'AD')) cf_contents.append("\tldap auth method = %s\n" % "simple") cf_contents.append("\tldap auth dn = %s\n" % ad.binddn) cf_contents.append("\tldap auth pw = %s\n" % ad.bindpw) cf_contents.append("\tldap server = %s\n" % ad.domainname) # This should be configured when using this option if ad.userdn: cf_contents.append("\tldap userbase = %s\n" % ad.userdn) cf_contents.append("\tldap userscope = %s\n" % "sub") # This should be configured when using this option if ad.groupdn: cf_contents.append("\tldap groupbase = %s\n" % ad.groupdn) cf_contents.append("\tldap groupscope = %s\n" % "sub") cf_contents.append("\tldap user filter = %s\n" % "objectclass=user") cf_contents.append("\tldap group filter = %s\n" % "objectclass=group") cf_contents.append("\tldap uuid attr = %s\n" % "objectGUID") cf_contents.append("\tldap uuid encoding = %s\n" % "ms-guid") cf_contents.append("\tldap name attr = %s\n" % "sAMAccountName") cf_contents.append("\tldap group attr = %s\n" % "sAMAccountName") cf_contents.append("\n") if afp.afp_srv_homedir_enable: cf_contents.append("[Homes]\n") cf_contents.append("\tbasedir regex = %s\n" % afp.afp_srv_homedir) if afp.afp_srv_homename: cf_contents.append("\thome name = %s\n" % afp.afp_srv_homename) if afp.afp_srv_hometimemachine: cf_contents.append(f"\ttime machine = yes\n") cf_contents.append("\n") for share in client.call('datastore.query', 'sharing.afp_share'): share = Struct(share) cf_contents.append("[%s]\n" % share.afp_name) cf_contents.append("\tpath = %s\n" % share.afp_path) if share.afp_allow: cf_contents.append("\tvalid users = %s\n" % share.afp_allow) if share.afp_deny: cf_contents.append("\tinvalid users = %s\n" % share.afp_deny) if share.afp_hostsallow: cf_contents.append("\thosts allow = %s\n" % share.afp_hostsallow) if share.afp_hostsdeny: cf_contents.append("\thosts deny = %s\n" % share.afp_hostsdeny) if share.afp_ro: cf_contents.append("\trolist = %s\n" % share.afp_ro) if share.afp_rw: cf_contents.append("\trwlist = %s\n" % share.afp_rw) if share.afp_timemachine: cf_contents.append("\ttime machine = yes\n") if not share.afp_nodev: cf_contents.append("\tcnid dev = no\n") if share.afp_nostat: cf_contents.append("\tstat vol = no\n") if not share.afp_upriv: cf_contents.append("\tunix priv = no\n") else: if share.afp_fperm and not map_acls_mode: cf_contents.append("\tfile perm = %s\n" % share.afp_fperm) if share.afp_dperm and not map_acls_mode: cf_contents.append("\tdirectory perm = %s\n" % share.afp_dperm) if share.afp_umask and not map_acls_mode: cf_contents.append("\tumask = %s\n" % share.afp_umask) cf_contents.append("\tveto files = .windows/.mac/\n") if map_acls_mode: cf_contents.append("\tacls = yes\n") # Do not fail if aux params are not properly entered by the user try: aux_params = ["\t{0}\n".format(p) for p in share.afp_auxparams.split("\n")] except: pass else: cf_contents += aux_params with open(afp_config, "w") as fh: for line in cf_contents: fh.write(line)