From cfde3c6592848621d5d6dca1aef124ddef9ae6bd Mon Sep 17 00:00:00 2001 From: Synology Date: Mon, 6 Jul 2020 22:15:19 +1000 Subject: [PATCH] Finished editing --- README.md | 55 +- .../NFS_Overview/NFS Overview and Gotchas.htm | 1161 ++++ .../console.html | 4 + .../console_data/console.js | 5281 +++++++++++++++++ .../monthfea.css | 24 + .../monthfea.js | 11 + 6 files changed, 6535 insertions(+), 1 deletion(-) create mode 100644 sources/NFS_Overview/NFS Overview and Gotchas.htm create mode 100644 sources/NFS_Overview/NFS Overview and Gotchas_files/console.html create mode 100644 sources/NFS_Overview/NFS Overview and Gotchas_files/console_data/console.js create mode 100644 sources/NFS_Overview/NFS Overview and Gotchas_files/monthfea.css create mode 100644 sources/NFS_Overview/NFS Overview and Gotchas_files/monthfea.js diff --git a/README.md b/README.md index c4356cd..e4ad8bb 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,56 @@ # synology-nfs-mount-tools -This is a repo that contains tools/documentations to help nfs mounting configuration in Synology \ No newline at end of file +This is a repo that contains tools/documentations to help nfs mounting configuration in Synology + +## How to config Synology for NFS + +Synology's DSM WebGUI has capability to set NFS configuration to allow Linux to access files on Synology NAS, follow [tutorial: How to access files on Synology NAS within the local network (NFS)](https://www.synology.com/en-us/knowledgebase/DSM/tutorial/File_Sharing/How_to_access_files_on_Synology_NAS_within_the_local_network_NFS) + +But the GUI's feature is limited. We need more fine tuning. Following [NFS: Overview and Gotchas](http://www.troubleshooters.com/linux/nfs.htm), we can set Synology properly. (If the URL is broken, we can refer to [NFS: Overview and Gotchas in repo](/source/NFS_Overview/NFS\ Overview\ and\ Gotchas.htm) + +### Summary of how to configure NFS server + +Configuring an NFS server is just placing a line in `/etc/exports` file. The line's general syntax is: + +``` +directory_being_shared subnet_allowed_to_access(options) +``` + +There are 2 kinds of options: + +* General options (ignored here) +* User ID Mapping options (need to be mentioned here) + +We want to make directories accessible as if the incoming request was from that user or that group, which is done by combining `all_squash` option with `anonuid` and `anongid` options. + +e.g. + +``` +/volume1/homes 192.168.1.85(rw,sync,no_wdelay,crossmnt,all_squash,insecure_locks,sec=sys,anonuid=1025,anongid=100) +``` + +where: + +* `/volume1/homes` is the directory to be shared +* `192.168.1.85` is the ip address of client +* `rw` is Read/Write +* `async` is for fast access. `sync` is for safer access +* `no_wdelay` is "Write disk as soon as possible" +* `anonuid=1025` is uid of "guest" +* `anongid=100` is gid of "guest/user" + +### Summary of how to configure client + +``` +mount -t nfs -o rw 192.168.100.85:/data/altamonte /mnt/test +``` + +## Current solution + +Due to limitation of NFS4.0, idmapping is too hard (mismatch between server and client's uid/gid), and kerberos authentication is too hard to setup. The only solution is NFS+`chown` + +1. Setup NFS permission of shared folder on Synology +2. mount volume to client +3. When writing files, remember to chown afterward + +For plex server, I need to align LXC's uid and gid with Synology diff --git a/sources/NFS_Overview/NFS Overview and Gotchas.htm b/sources/NFS_Overview/NFS Overview and Gotchas.htm new file mode 100644 index 0000000..606fdb4 --- /dev/null +++ b/sources/NFS_Overview/NFS Overview and Gotchas.htm @@ -0,0 +1,1161 @@ + + + + + + + + + + + + + + NFS: Overview and Gotchas + + +
+

Troubleshooters.Com and T.C Linux Library Present

+
+
NFS: Overview and Gotchas +

Copyright (C) 2003 by Steve Litt, All rights +reserved. Material provided as-is, use at your own risk.

+
+ + + + + +

May 2020 featured book:

Troubleshooting Techniques of the successful technologist

+ + + + + + +Contents:
+

+ +

Executive Summary:

+NFS is the best thing since sliced bread. It stands for Network File System. +NFS is a file and directory sharing mechanism native to Unix and Linux.
+
+NFS is conceptually simple. On the server (the box that is allowing others +to use its disk space), you place a line in /etc/exports to enable +its use by clients. This is called sharing. For instance, to share +/home/myself for both read and write on subnet 192.168.100, netmask +255.255.255.0, place the following line in /etc/exports on the server:
+
/home/myself 192.168.100.0/24(rw)
+To share it read only, change the (rw)to (ro).
+
+On the client wanting to access the shared directory, use the mount +command to access the share:
+
mkdir /mnt/test
mount -t nfs -o rw 192.168.100.85:/home/myself /mnt/test
+The preceding must be performed by user root, or else as a sudo command. +Another alternative is to place the mount in /etc/fstab. That will +be discussed later in this document.
+
+As mentioned, NFS is conceptually simple, but in practice you'll encounter +some truly nasty gotchas:
+ +To minimize troubleshooting time, quickcheck for each of these problems. +Each of these gotchas is explained in detail in this document.
+

Directories and IP addresses +used in these examples

+The following settings are used in examples on this page:
+ +Please make note of these settings so that you're not confused in the examples.
+

Get the Daemons Running

+You can't run NFS without the server's portmap and NFS daemons running. This +article discusses how to set them to run at boot, and how to check that they're +currently running. First you'll use the chkconfig program to set +the portmap, nfs and mountd daemons to run at boot. Then you'll check whether +these daemons are running. Finally, whether they're running or not, you'll +restart these daemons.
+

Checking the portmap Daemon

+In order to run NFS, the portmap daemon must run. Check for automatic running +at boot with the following command:
+
+ + + + + + + +
+ +
[root@myserver root]# chkconfig --list portmap
portmap 0:off 1:off 2:off 3:on 4:on 5:on 6:off
[root@myserver root]#
+
+
+Note that in the preceding example, runlevels 3, 4, and 5 say "on". That +means that at boot, for runlevels 3, 4 and 5, the portmap daemon is started +automatically. If either 3, 4 or 5 say "off", turn them on with the following +command:
+
chkconfig portmap on
+Now check that the portmapper is really running, using the ps and +grep commands:
+
+ + + + + + + +
+ +
[root@myserver root]# ps ax | grep portmap
3171 ? S 0:00 portmap
4255 pts/0 S 0:00 grep portmap
You have new mail in /var/spool/mail/root
[root@myserver root]#
+
+
+The preceding shows the portmap daemon running at process number 3171.
+

Checking the NFS Daemon

+Next perform the exact same steps for the NFS daemon. Check for automatic +run at boot:
+
+ + + + + + + +
+ +
[root@myserver root]# chkconfig --list nfs
nfs 0:off 1:off 2:on 3:on 4:on 5:on 6:off
[root@myserver root]#
+
+
+If either of runlevels 3, 4 or 5 say "off", turn all 3 on with the following +command:
+
chkconfig nfs on
+And check that the NFS and the mountd daemons are running as follows:
+
ps ax | grep nfs
ps ax | grep mountd
+You might get several different different nfs daemons -- that's OK.
+

Restarting the Daemons

+When learning or troubleshooting, there's nothing so wonderful as a known +state. On that theory, restart the daemons before proceeding. Or if you want +a truly known state, reboot. Always restart the portmap daemon BEFORE restarting +the NFS daemon. Here's how you restart the two daemons:
+
service portmap restart
service nfs restart
+You'll see messages on the screen indicating if the startups were successful. +If they are not, troubleshoot. If they are, continue.
+
+Note that the mountd daemon is started by restarting nfs.
+
+You don't need to restart these daemons every time. Now that you've enabled +the daemons on reboot, you can safely assume they're running (unless there's +an NFS problem -- then don't make this assumption). From now on the only +time you need to restart the NFS daemon is when you change /etc/exports. +Theoretically you should never need to restart the portmap daemon unless +there's a problem.
+

Summary

+NFS requires a running portmap daemon and NFS daemon. Use chkconfig +to make sure these daemons run at boot, make sure they're running, and the +first time, restart the portmap daemon and then the NFS daemon just to be +sure you've achieved a known state.
+

Configure the NFS Server

+Configuring an NFS server is as simple as placing a line in the /etc/exports +file. That line has three pieces of information:
+
    +
  1. The directory to be shared (exported)
  2. +
  3. The computer, NIS group, hostname, domain name or subnet allowed to +access that directory
  4. +
  5. Any options, such as ro or rw, or several other options
    +
  6. +
+There's one line for each directory being shared. The general syntax is:
+
directory_being_shared subnet_allowed_to_access(options)
+Here's an example:
+
/home/myself 192.168.100.0/24(ro)
+In the preceding example, the directory being shared is /home/myself, +the subnet is 192.168.100.0/24, and the options are ro(read +only). The subnet can also be a single host, in which case there would be +an IP address with no bitmask (the /24 in the preceding example). +Or it can be an NIS netgroup, in which case the IP address is replaced with +@groupname. You can use a wildcard such as ? or * to replace part +of a Fully Qualified Domain Name (FQDN). An example would be *.accounting.domain.cxm. +Do not use wildcards in IP addresses, as they are intermittent in IP addresses.
+
+There are two kinds of options: General options and User ID Mapping options. +Read on...
+

General Options

+Many options can go in the parentheses. If more than one, they are delimited +by commas. Here are the common options:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Option
+
What it does
+
Comment
+
ro
+
Read Only
+
The share cannot be written. This is the default.
+
rw
+
Read Write
+
The share can be written.
+
secure
+
Ports under 1024
+
Requires that requests originate on a port less  +than IPPORT_RESERVED (1024). This is the default.
+
insecure
+
Negation of secure
+

+
async
+
Reply before disk write
+
Replies to requests before the data is written to +disk. This improves performance, but results in lost data if the server goes +down.
syncReply only after disk writeReplies to the NFS request only after all data has +been written to disk. This is much safer than async, and is the default in +all nfs-utils versions after 1.0.0.
no_wdelay
+
Write disk as soon as possible
+
NFS has an optimization algorithm that delays disk +writes if NFS deduces a likelihood of a related write request soon arriving. +This saves disk writes and can speed performance.
+ BUT...
+If NFS deduced wrongly, this behavior causes delay in every request, in which +case this delay should be eliminated. That's what the no_wdelay option does +-- it eliminates the delay. In general, no_wdelay is recommended when most +NFS requests are small and unrelated.
+
wdelayNegation of no_wdelay
+
This is the default.
+
nohide
+
Reveal nested directories
+
Normally, if a server exports two filesystems one of +which is mounted on the other, then  the  client  will  +have  to mount  both filesystems explicitly to get access to them.  +If it just mounts the parent, it will see an empty  directory  at  +the place where the other filesystem is mounted.  That filesystem is +"hidden".
+
+Setting the nohide option on a filesystem causes it  not  to  +be hidden,  and  an appropriately authorised client will be able +to move from the parent to that  filesystem  without  noticing  +the change.
+
+However,  some  NFS clients do not cope well with this situation +as, for instance, it is then possible for two files in  the  one +apparent filesystem to have the same inode number.
+
+The  nohide  option  is  currently only effective on single +host exports.  It does not work reliably with  netgroup,  subnet,  +or wildcard exports.
+
+This option can be very useful in some situations, but it should be used with +due care, and only after confirming that the client system copes with the +situation effectively.
+
hide
+
Negation of nohide
+
This is the default
+
subtree_check
+
Verify requested file is in exported tree
+
This is the default. Every file request is checked +to make sure that the requested file is in an exported subdirectory. If this +option is turned off, the only verification is that the file is in an exported +filesystem.
+
no_subtree_check Negation of subtree_check
+
Occasionally, subtree checking can produce problems +when a requested file is renamed while the client has the file open. If many +such situations are anticipated, it might be better to set no_subtree_check. +One such situation might be the export of the /home filesystem. Most +other situations are best handed with subtree_check.
secure_locks
+
Require authorization for lock requests
+
This is the default. Require authorization of all locking +requests.
+
insecure_locks
+
Negation of secure_locks
+
Some NFS clients don't send credentials with lock requests, +and hence work incorrectly with secure_locks., in which case you +can only lock world-readable files. If you have such clients, either replace +them with better ones, or use the insecure_locks option.
+
auth_nlm
+
Synonym for secure_locks
+

+
no_auth_nlm
+
Synonym for secure_locks
+

+
+

User ID Mapping Options

+In an ideal world, the user and group of the requesting client would determine +the permissions of the data returned. We don't live in an ideal world. Two +real-world problems intervene:
+
    +
  1. You might not trust the root user of a client with root access to the +server's files.
  2. +
  3. The same username on client and server might have different numerical +ID's
  4. +
+Problem 1 is conceptually simple. John Q. Programmer is given a test machine +for which he has root access. In no way does that mean that John Q. Programmer +should be able to alter root owned files on the server. Therefore NFS offers +root squashing, a feature that maps uid 0 (root) to the anonymous +(nfsnobody) uid, which defaults to -2 (65534 on 16 bit numbers).
+
+So when John Q. Programmer mounts the share, he can access only what the +anonymous user and group can access. That means files that are world readable +or writeable, or files that belong to either user nfsnobody or group +nfsnobodyand allow access by the user or group. One way to do this +is to export a chmod 777 directory (booooooo). A better way is to export +a directory belonging to user nfsnobody or group nfsnobody, +and permissioning accordingly. Now root users from other boxes can write +files in that directory, and read the files they write, but they can't read +or write files created by root on the server itself.
+
+Now that you know what root squashing is, how do you enable or disable it +on a per-share basis? If you want to enable root squashing, that's simple, +because it's the default. If you want to disable it, so that root on any +box operates as root within the mounted share, disable it with the no_root_squash +option as follows:
+
/data/foxwood 192.168.100.0/24(rw,no_root_squash)
+If, for documentation purposes or to guard against a future change in the +default, you'd like to explicitly specify root squashing, use the root_squash +option.
+
+Perhaps you'd like to change the default anonymous user or group on a per-share +basis. That way the client's root user can access files within the share +as a specific user, let's say user myself. No problem. Use the anonuid +or anongid option. The following example uses the anongid +option to access the share as group myself., assuming that on the +server group myself has gid 655:
+
/data/wekiva 192.168.100.0/24(rw,anongid=655)
+The preceding makes the client's root user group 655 (which happens to be +group myself on share /data/wekiva. Files created by the +client's root user are user and group 655, but files modified by +the client's root are group 655, and a different user.
+
+Now imagine that instead of mapping incoming client root requests to the +anonymous user or group, you want ALL incoming NFS requests to be mapped +to the anonomous user or the anonymous group. To accomplish that you use +the all_squashoption, as follows:
+
/data/altamonte 192.168.100.0/24(rw,all_squash)
+You can combine the all_squash option with the anonuidandanongid +options to make directories accessible as if the incoming request was from +that user or that group. The one problem with that is that, for NFS purposes, +it makes the share world readable and/or world writeable, at least to the +extent of which hosts are allowed to mount the share.
+
+We'll get into this subject a little bit more when discussing the Gotcha +concerning different user and group id numbers.
+
+The following table lists the User ID Mapping Options:
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Option
+
What it does
+
Comment
+
+
root_squash
+
Convert incoming requests from user root to the anonymous +uid and gid.
+
This is the default.
+
+
no_root_squash
+
Negation of root_squash
+

+
anonuid Set anonymous user id to a specific id
+
The id is a number, not a name. This number can be +obtained by this command on the server:
+ +
grep myself /etc/passwd
+Where myself is the username whose uid you want to find.
+
anongid Set anonymous group id to a specific id The id is a number, not a name. This number can be +obtained by this command on the server:
+ +
grep myself /etc/group
+Where myself is the name of the group whose uid you want to find. +
all_squash
+
Convert incoming requests, from ALL users, to the +anonymous uid and gid. Remember that this gives all incoming users the same +set of rights to the share. This may not be what you want.
+
+
+

Mounting an NFS Share +on a Client

+Mounting an NFS share on a client can be simple. At its simplest it might +look like this:
+
mount -t nfs -o ro 192.168.100.85:/data/altamonte /mnt/test
+The English translation of the preceding is this: mount type (-t) +nfs with options (-o) read only (ro) server 192.168.100.85's +directory /data/altamonteat mount point /mnt/test. What +usually changes is the comma delimited list of options (-o). For +instance, NFS typically performs better with rsize=8192and wsize=8192. +These are the read and write buffer sizes, and it's been found that in general +8192 performs better than the default 4096. Thehard option keeps +the request alive even if the server goes down, whereas the softoption +enables the mount to time out if the server goes down. The hardoption +has the advantage that whenever the server comes back up, the file activity +continues where it left off.
+
+Besides these and a few other NFS specific options, there are filesystem +independent options such as async/sync/dirsync, atime/noatime, auto/noauto, +defaults,dev/nodev, exec/noexec, _netdev, remount, ro, rw, suid/nosuid, user/nouser.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Option
+
Action
+
Default?
+
Comment
+
Negation
+option
+
asyncAll I/O done asynchronously
+
Y
+
Better performance, more possiblity of corruption +when things crash. Do not use when the same file is being modified by different +users.
+
sync
syncAll I/O done synchronouslyN
+
Less likelihood of corruption, less likelihood of +overwrite by other users.
+
async
dirsyncAll I/O to directories done synchronously
+
N
+

+

+
atimeUpdate inode access time for each  access.
+
Y
+

+
noatime
autoAutomatic mounting.
+
Y
+
Can be mounted with the -a option. Mounted at boot +time.noauto
defaultsShorthand for default options.
+

+
rw,suid,dev,exec,auto,nouser,async.
+

+
devDevice
+
Y
+
Interpret character or block special devices on the  +file system.
+
nodev
execPermit execution of binaries.
+
Y
+

+
noexec
_netdevDevice requires network.
+

+
The  device holding the filesystem requires network +access. Do not mount until the network has been enabled.
+

+
remountRemount a mounted system.
+

+
Used to change the mount flags, especially to toggle +between rw and ro.
+

+
roAllow only read access.
+
N
+
Used to protect the mounted filesystem from writes. +Even if the filesystem is writeable by the user, and is exported writeable, +this still protects it.
+
rw
rwAllow both read and write.
+
Y
+
Allow writing to the filesystem, assuming that the +system is writeable by the user and has been exported writeable.
+
ro
suidAllow set-user-identifier and/or set-group-identifier +bits to take effect.
+
Y
+

+
nosuid
userAllow mounting by ordinary user.
+
N
+
When used in /etc/fstab, this allows mounting +by an ordinary user. Only the user performing the mount can unmount it.
+
nouser
users
+
Allow mounting and dismounting by arbitrary user.N
+
When used in /etc/fstab, this allows mounting +by an ordinary user. Any user can unmount it at any time, regardless of who +initially mounted it.
+
+
+

/etc/fstab syntax

+Like any other mount, NFS mounting can be done in /etc/fstab. The +advantages to placing it in /etc/fstab are:
+ +The disadvantages to placing a mount in /etc/fstab are:
+ +The following example shows an NFS mount:
+
192.168.100.85:/home/myself   /mnt/test  nfs  users,noauto,rw   0   0
+The preceding is a typical example. Just like other /etc/fstab mounts, +NFS mounts in /etc/fstab have 6 columns, listed in order as follows:
+
    +
  1. The filesystem to be mounted (192.168.100.85:/home/myself)
  2. +
  3. The mountpoint (/mnt/test)
  4. +
  5. The type of the filesystem (nfs)
  6. +
  7. The options (users,noauto,rw)
  8. +
  9. Frequency to be dumped (a backup method)  (0)
  10. +
  11. Order in which to be fsck'ed at boot time.  (0). The +root filesystem should have a value of 1 so it gets fsck'ed first. Others +should have 2 or more so they get fsck'ed later. A value of 0 means don't +perform the fsck at all.
  12. +
+

Summary

+The server exports a share, but to use it the client must mount that share. +The mount is performed with a mount command, like this:
+
mount -t nfs -o rw 192.168.100.85:/data/altamonte /mnt/test
+That same mount can be performed in /etc/fstab with the following +syntax:
+
192.168.100.85:/data/altamonte   /mnt/test   nfs   rw   0   0
+There are many mount options that can be used, and those are listed in this +article.
+

Gotchas

+If you've worked with NFS, you know it's not that simple. Often times the +mount fails, times out, or takes so long as to discourage use. Sometimes +the mount succeeds but the data is inaccessible. These problems can be a +bear to troubleshoot.
+
+To make troubleshooting easier this article lists the usual causes of NFS +failure, ways to quickly check whether these problems are the cause, and +methods to overcome these problems. Here are the typical causes of NFS problems:
+ + + + + + + +
+
!! WARNING !!
+
+
+Always restart the nfs service after making a change to /etc/exports. +Otherwise your changes will not be recognized, leading you down a long and +winding dead end.
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Cause category
+
Symptom
+
The portmap or nfs daemons are not +runningTypically, failure to mount
Syntax error on client mount command or server's /etc/exports
+
Typically, failure to mount or failure to write enable. +A space between the mount point and the (rw) causes the share to +be read-only -- a frustrating and hard to diagnose problem.
Problems with permissions, uid's and gid'sMounts OK, but access to the data is impossible or +not as specified
+
Firewalls filtering packets necessary for NFSMount failures, timeouts, excessively slow mounts, +or intermittent mounts
Bad DNS on serverMount failures, timeouts, excessively slow mounts, +or intermittent mounts
+
+Here's your predefined diagnostic:
+
    +
  1. Check the daemons on the server
  2. +
  3. Eyeball the syntax of the client mount command and the server /etc/exports. +Pay particular attention that the mountpoint is NOT separated from the parenthasized +options list, because a space between the mountpoint and the opening paren +causes the options to be ignored.
  4. +
  5. Carefully read error messages and develop a symptom description
  6. +
  7. If the symptom involves successful mounts but you can't correctly access +the data, check permissions, gid's and uid's. Correct as necessary.
  8. +
  9. If there are still problems, disable firewalls or log firewalls. 
  10. +
  11. If there are still problems, investigate the server's DNS, host name +resolution, etc.
    +
  12. +
+For maximum diagnostic speed, quickly check that the portmap and nfs daemons +are running on the server. If not, investigate why not. Next, eyeball the +syntax on the client's mount command and the server's /etc/exports +file. Look for not only bad syntax, but wrong information such as wrong IP +addresses, wrong filesystem directories, and wrong mountpoints. If you find +bad syntax, correct it. These two steps should take no more than 3 minutes, +and will find the root cause in many cases.
+
+Next, carefully read the error message, and formulate a symptom description. +Try to determine whether the mount has succeeded. If the mount succeeded +but you can't access the data, it's likely a problem with permissions, uid's +or gid's. Investigate that. If the mount succeeds but it's slow, investigate +firewalls and DNS. A healthy NFS system should mount instantaneously. By +the time you lift your finger off the Enter key, the mount should have been +completed. If it takes more than one second, there's a problem that bears +investigation.
+
+The hardest problems are those in which you experience mount failures, timeouts, +excessively slow mounts, or intermittent mounts. In such situations, it's +likely either a firewall problem or a server DNS problem. Investigate those.
+
+Each of these problem categories is discussed in an article later in this +document.
+

1: Check the Daemons on the Server

+This will take you all of a minute. Perform the following 2 commands on the +server:
+
ps ax | grep portmap
ps ax | grep nfs
+If either shows nothing (or if it shows just the grep command), that server +is not running. Investigate why. Start by seeing if it's even set to run +at boot:
+
/sbin/chkconfig --list portmap
/sbin/chkconfig --list nfs
+Each command will output a line showing the run levels at which the command +is on. If either one is not on at any runlevel between 3 and 5 inclusive, +turn it on with one or both of these commands:
+
/sbin/chkconfig portmap on
/sbin/chkconfig nfs on
+The preceding commands set it to fire at boot, but do not run the daemon. +You must run them manually:
+
service portmap restart
service nfs restart
+Always restart the portmap daemon before restarting the nfs daemon, because +NFS needs the portmapper to function. If either of those commands fails or +produces an error message, investigate.
+
+IMPORTANT NOTE: Even if the daemons were both running +when you investigated, restart them both anyway. First, you might see an +error message. Second, it's always nice to achieve a known state. Restarting +these two daemons should take a minute. That one minute is a tiny price to +pay for the peace of mind you achieve knowing that there's no undiscovered +problem with the daemons.
+
+If NFS fails to start, investigate the syntax in /etc/exports, and +possibly comment out everything in that file, and try another restart. If +that changes the symptom, divide and conquer. If restarting NFS takes a huge +amount of time, investigate the server's DNS.
+

2: Eyeball the Syntax

+If the daemons work, eyeball the syntax of the mount command on the client +and the /etc/exports file on the server. Obviously, if you use the +wrong syntax (or wrong IP addresses or directories) in your mount command, +the mount fails. You needn't take a great deal of time -- just verify that +the syntax is correct and you're using the correct IP addresses, directories +and mount points. Correct as necessary, and retest.
+
+Pay SPECIAL attention to make sure there is no space between the mountpoint +and the opening paren of the options list. A space between them causes the +options to be ignored -- clearly not what you want. If you can't figure out +why a mount is read-only, even though the client mount command specifies +read-write and the server's directory is clearly read-write with the correct +user and group (not a number, but an actual name), suspect this intervening +space.
+ + + + + + + +
+
!! WARNING !!
+
+
+Always restart the nfs service after making a change to /etc/exports. +Otherwise your changes will not be recognized, leading you down a long and +winding dead end.
+
+

3: Carefully +read error messages and develop a symptom description

+The first two steps were general maintenance -- educated guesses designed +to yield quick solutions. If they didn't work, it's time to buckle down and +troubleshoot. The first step is to read the error message, and learn more +about it. You might want to check the system logs (start with /var/log/messages) +in case relevent messages were written.
+
+Try several mounts and umounts, and note exactly what the malfunction looks +like:
+ +The more you learn and record about the symptom, the better your chances +of quickly and accurately solving the problem.
+

4: If it mounts but can't +access, check permissions, gid's and uid's

+Generally speaking, the permissions on the server don't affect the mounting +or unmounting of the NFS share. But they very much affect whether such a +share can be seen, executed, read or written. Often the cause is obvious. +If the directory is owned by root, permissioned 700, it obviously can't be +read and written by user myself.  This type of problem is easy +to diagnose and fix.
+
+Tougher are root squashing problems. You access an NFS share as user root, +and yet you can't see the mounted share or its contents. You need to remember +this is probably happening because on the server you're operating not as root, +but as the anonomous user. A quick test can be done by changing the server's +export to export to a no_root_squash and single IP address (for +security). If the problem goes away, it's a root squashing problem. Either +access it as non-root, or change the ownership of the directory and contents +to the anonomous gid or uid.
+
+By far the toughest problems are caused by non-matching uid's and gid's. Let's +say you share your home directory on the server, and you log in as yourself +on the client and mount that share. It mounts ok (we'll assume you used su +-c or sudo to mount it), but you can't read the data -- permission +denied!
+
+That's crazy. The directory you're sharing is owned by myself, and +you're logged into the client as myself, and yet you don't have permission +to read. What's up?
+
+It turns out that under the hood, NFS requests contain numeric uid's and gid's, +but not actual usernames or groupnames. What that means is that if user myself +is uid 555 on the server, but uid 600 on the client, you're trying to access +files owned by uid 555 when you're uid 600. That means your only rights to +the mounted material are permissions granted to "other" -- not to "user" +or "group".
+
+The best solution to this problem is to create a system in which all boxes +on your network have the same uid for each username and the same gid for each +groupname. This can be accomplished either by attention to detail, by using +NIS to assign users and groups, or by using some other authentication scheme +yielding global users and groups.
+
+If you cannot have a single uid for all instances of a username, suboptimal +steps must be taken. In some instances you could make the directory and files +world-readable, thereby enabling all users to read it. It could also be made +world-writeable, but that's always a bad idea. It could be mounted all_squash +with a specific anonuid and/or a specific anongid to cure +the problem, but once again, at least from the NFS viewpoint, that's equivalent +to making it world readable or writeable.
+
+If you have problems accessing mounts, always check the gid's and uid's on +both sides and make sure they match. If they don't, find a way of fixing it. +Sometimes it's as simple as editing /etc/passwd and /etc/group +to change the numeric ID's on one or both sides. Remember that if you do that, +you need to perform the proper chown command on any files that were +owned or grouped by the owner and/or group that you renumbered. A dead giveaway +are files that are listed with numbers rather than names for group and user.
+

5: If there are still problems, disable +firewalls or log firewalls

+Many supposed NFS problems are really problems with the firewall. In order +for your NFS server to successfully serve NFS shares, its firewall must enable +the following:
+ +The easiest way to see whether your problem resides in the firewall is to +completely open up the client and server firewalls and anything in between. +For details on how to manipulate iptables see the May 2003 Linux Productivity Magazine.
+
+Note that opening up firewalls is appropriate only if you're disconnected +from the Internet, or if you're in a very un-hostile environment. Even so, +you should open up the firewalls for a very short time (less than 5 minutes). +If in doubt, instead of opening the firewalls, insert logging statements +in IPTables to show what packets are being rejected during NFS mounts, and +take action to enable those ports. For details on IPTables diagnostic logging, +see the May 2003 +Linux Productivity Magazine.
+
+The mountd daemon ports are especially problematic, because they're normally +assigned by the portmap daemon, and vary from NFS restart to NFS restart. +The /etc/rc.d/init.d/nfs script can be changed to nail down the +mountd daemon to a specific port, which then enables you to pinhole a specific +port. The A Somewhat +Practical Server Firewall article in the May 2003 Linux Productivity +Magazine. explains how to do this.
+
+If for some reason you don't want to nail down the port, your only other alternatives +are to create a firewall enabling a huge range of ports in the 30000's, or +to create a master NFS restart script which does the following:
+
    +
  1. Use the rcpinfo program to find all ports used by mountd.
  2. +
  3. Issue iptables commands to find the rule numbers for those +ports.
  4. +
  5. Issue iptables commands to delete all rules on those +ports.
  6. +
  7. Restart NFS
  8. +
  9. Use the rcpinfo program to find all ports used by mountd.
  10. +
  11. Issue iptables commands to insert rules for those ports where +the rules for those ports used to be.
  12. +
+One technique that might make that easier is to create a user defined chain +just to hold mountd rules. In that case you'd simply empty that chain, restart +NFS, use rpcinfo to find the port numbers, and add the proper rules +using the iptables -A command.
+
+It bears repeating that the May 2003 Linux Productivity +Magazine details how to create an NFS friendly firewall. +

6: If there are still problems, investigate +the server's DNS, host name resolution, etc

+Bad forward and reverse name resolution can mess up any server app, including +NFS. Like other apps, bad DNS most often results in very slow performance +or timeouts. Be sure to check your /etc/resolv.conf and make sure +you're querying the correct DNS server. Check your DNS server with DNSwalk +or DNS lint or another suitable utility.
+

Summary

+NFS is wonderful. It's a convenient and lightning fast way to use a network. +Although it's not particularly secure, its security can be beefed up with +firewalls. Its security can also be strengthened by authentication schemes.
+
+Although conceptually simple, NFS often requires overcoming troubleshooting +challenges before a working system is achieved. Here's a handy predefined +diagnostic:
+
    +
  1. Check the daemons on the server
  2. +
  3. Eyeball the syntax of the client mount command and the server /etc/exports
  4. +
  5. Carefully read error messages and develop a symptom description
  6. +
  7. If the symptom involves successful mounts but you can't correctly access +the data, check permissions, gid's and uid's. Correct as necessary.
  8. +
  9. If there are still problems, disable firewalls or log firewalls. 
  10. +
  11. If there are still problems, investigate the server's DNS, host name +resolution, etc.
  12. +
+If you suspect firewall problems are stopping your NFS, see the May 2003 Linux Productivity +Magazine , which details IPTables and how to create an NFS-friendly firewall.
+

+
+

Back to Troubleshooters.Com * Back to Linux Library

+
+
+
+ + + \ No newline at end of file diff --git a/sources/NFS_Overview/NFS Overview and Gotchas_files/console.html b/sources/NFS_Overview/NFS Overview and Gotchas_files/console.html new file mode 100644 index 0000000..e4385eb --- /dev/null +++ b/sources/NFS_Overview/NFS Overview and Gotchas_files/console.html @@ -0,0 +1,4 @@ + + +VimVixen console
\ No newline at end of file diff --git a/sources/NFS_Overview/NFS Overview and Gotchas_files/console_data/console.js b/sources/NFS_Overview/NFS Overview and Gotchas_files/console_data/console.js new file mode 100644 index 0000000..2a8bab4 --- /dev/null +++ b/sources/NFS_Overview/NFS Overview and Gotchas_files/console_data/console.js @@ -0,0 +1,5281 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 206); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__extends", function() { return __extends; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__assign", function() { return __assign; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__rest", function() { return __rest; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__decorate", function() { return __decorate; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__param", function() { return __param; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__metadata", function() { return __metadata; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__awaiter", function() { return __awaiter; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__generator", function() { return __generator; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__exportStar", function() { return __exportStar; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__values", function() { return __values; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__read", function() { return __read; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__spread", function() { return __spread; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__await", function() { return __await; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__asyncGenerator", function() { return __asyncGenerator; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__asyncDelegator", function() { return __asyncDelegator; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__asyncValues", function() { return __asyncValues; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__makeTemplateObject", function() { return __makeTemplateObject; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__importStar", function() { return __importStar; }); +/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__importDefault", function() { return __importDefault; }); +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + } + return __assign.apply(this, arguments); +} + +function __rest(s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) + t[p[i]] = s[p[i]]; + return t; +} + +function __decorate(decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +} + +function __param(paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +} + +function __metadata(metadataKey, metadataValue) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); +} + +function __awaiter(thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +} + +function __generator(thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +} + +function __exportStar(m, exports) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} + +function __values(o) { + var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; + if (m) return m.call(o); + return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; +} + +function __read(o, n) { + var m = typeof Symbol === "function" && o[Symbol.iterator]; + if (!m) return o; + var i = m.call(o), r, ar = [], e; + try { + while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); + } + catch (error) { e = { error: error }; } + finally { + try { + if (r && !r.done && (m = i["return"])) m.call(i); + } + finally { if (e) throw e.error; } + } + return ar; +} + +function __spread() { + for (var ar = [], i = 0; i < arguments.length; i++) + ar = ar.concat(__read(arguments[i])); + return ar; +} + +function __await(v) { + return this instanceof __await ? (this.v = v, this) : new __await(v); +} + +function __asyncGenerator(thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; + function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } +} + +function __asyncDelegator(o) { + var i, p; + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; } +} + +function __asyncValues(o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } +} + +function __makeTemplateObject(cooked, raw) { + if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } + return cooked; +}; + +function __importStar(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result.default = mod; + return result; +} + +function __importDefault(mod) { + return (mod && mod.__esModule) ? mod : { default: mod }; +} + + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +if (true) { + module.exports = __webpack_require__(37); +} else {} + + +/***/ }), +/* 2 */, +/* 3 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +exports.BACKGROUND_OPERATION = "background.operation"; +exports.CONSOLE_UNFOCUS = "console.unfocus"; +exports.CONSOLE_ENTER_COMMAND = "console.enter.command"; +exports.CONSOLE_ENTER_FIND = "console.enter.find"; +exports.CONSOLE_SHOW_COMMAND = "console.show.command"; +exports.CONSOLE_SHOW_ERROR = "console.show.error"; +exports.CONSOLE_SHOW_INFO = "console.show.info"; +exports.CONSOLE_SHOW_FIND = "console.show.find"; +exports.CONSOLE_HIDE = "console.hide"; +exports.CONSOLE_GET_COMPLETION_TYPES = "console.get.completion.types"; +exports.CONSOLE_REQUEST_SEARCH_ENGINES_MESSAGE = "console.qresut.searchEngines"; +exports.CONSOLE_REQUEST_BOOKMARKS = "console.request.bookmarks"; +exports.CONSOLE_REQUEST_HISTORY = "console.request.history"; +exports.CONSOLE_REQUEST_TABS = "console.request.tabs"; +exports.CONSOLE_GET_PROPERTIES = "console.get.properties"; +exports.FOLLOW_START = "follow.start"; +exports.FOLLOW_REQUEST_COUNT_TARGETS = "follow.request.count.targets"; +exports.FOLLOW_RESPONSE_COUNT_TARGETS = "follow.response.count.targets"; +exports.FOLLOW_CREATE_HINTS = "follow.create.hints"; +exports.FOLLOW_SHOW_HINTS = "follow.update.hints"; +exports.FOLLOW_REMOVE_HINTS = "follow.remove.hints"; +exports.FOLLOW_ACTIVATE = "follow.activate"; +exports.FOLLOW_KEY_PRESS = "follow.key.press"; +exports.MARK_SET_GLOBAL = "mark.set.global"; +exports.MARK_JUMP_GLOBAL = "mark.jump.global"; +exports.TAB_SCROLL_TO = "tab.scroll.to"; +exports.FIND_NEXT = "find.next"; +exports.FIND_PREV = "find.prev"; +exports.FIND_GET_KEYWORD = "find.get.keyword"; +exports.FIND_SET_KEYWORD = "find.set.keyword"; +exports.ADDON_ENABLED_QUERY = "addon.enabled.query"; +exports.ADDON_ENABLED_RESPONSE = "addon.enabled.response"; +exports.ADDON_TOGGLE_ENABLED = "addon.toggle.enabled"; +exports.OPEN_URL = "open.url"; +exports.SETTINGS_CHANGED = "settings.changed"; +exports.SETTINGS_QUERY = "settings.query"; +exports.CONSOLE_FRAME_MESSAGE = "console.frame.message"; +exports.NAVIGATE_HISTORY_NEXT = "navigate.history.next"; +exports.NAVIGATE_HISTORY_PREV = "navigate.history.prev"; +exports.NAVIGATE_LINK_NEXT = "navigate.link.next"; +exports.NAVIGATE_LINK_PREV = "navigate.link.prev"; +exports.valueOf = (o) => { + switch (o.type) { + case exports.CONSOLE_UNFOCUS: + case exports.CONSOLE_ENTER_COMMAND: + case exports.CONSOLE_ENTER_FIND: + case exports.CONSOLE_SHOW_COMMAND: + case exports.CONSOLE_SHOW_ERROR: + case exports.CONSOLE_SHOW_INFO: + case exports.CONSOLE_SHOW_FIND: + case exports.CONSOLE_HIDE: + case exports.FOLLOW_START: + case exports.FOLLOW_REQUEST_COUNT_TARGETS: + case exports.FOLLOW_RESPONSE_COUNT_TARGETS: + case exports.FOLLOW_CREATE_HINTS: + case exports.FOLLOW_SHOW_HINTS: + case exports.FOLLOW_REMOVE_HINTS: + case exports.FOLLOW_ACTIVATE: + case exports.FOLLOW_KEY_PRESS: + case exports.MARK_SET_GLOBAL: + case exports.MARK_JUMP_GLOBAL: + case exports.TAB_SCROLL_TO: + case exports.FIND_NEXT: + case exports.FIND_PREV: + case exports.FIND_GET_KEYWORD: + case exports.FIND_SET_KEYWORD: + case exports.ADDON_ENABLED_QUERY: + case exports.ADDON_ENABLED_RESPONSE: + case exports.ADDON_TOGGLE_ENABLED: + case exports.OPEN_URL: + case exports.SETTINGS_CHANGED: + case exports.SETTINGS_QUERY: + case exports.CONSOLE_FRAME_MESSAGE: + case exports.NAVIGATE_HISTORY_NEXT: + case exports.NAVIGATE_HISTORY_PREV: + case exports.NAVIGATE_LINK_NEXT: + case exports.NAVIGATE_LINK_PREV: + return o; + } + throw new Error("unknown operation type: " + o.type); +}; + + +/***/ }), +/* 4 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + + + +/** + * Use invariant() to assert state which your program assumes to be true. + * + * Provide sprintf-style format (only %s is supported) and arguments + * to provide information about what broke and what you were + * expecting. + * + * The invariant message will be stripped in production, but the invariant + * will remain to ensure logic does not differ in production. + */ + +var invariant = function(condition, format, a, b, c, d, e, f) { + if (false) {} + + if (!condition) { + var error; + if (format === undefined) { + error = new Error( + 'Minified exception occurred; use the non-minified dev environment ' + + 'for the full error message and additional helpful warnings.' + ); + } else { + var args = [a, b, c, d, e, f]; + var argIndex = 0; + error = new Error( + format.replace(/%s/g, function() { return args[argIndex++]; }) + ); + error.name = 'Invariant Violation'; + } + + error.framesToPop = 1; // we don't care about invariant's own frame + throw error; + } +}; + +module.exports = invariant; + + +/***/ }), +/* 5 */ +/***/ (function(module, exports, __webpack_require__) { + +/** + * Copyright (c) 2013-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +if (false) { var throwOnDirectAccess, ReactIs; } else { + // By explicitly using `prop-types` you are opting into new production behavior. + // http://fb.me/prop-types-in-prod + module.exports = __webpack_require__(41)(); +} + + +/***/ }), +/* 6 */, +/* 7 */, +/* 8 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +var isOldIE = function isOldIE() { + var memo; + return function memorize() { + if (typeof memo === 'undefined') { + // Test for IE <= 9 as proposed by Browserhacks + // @see http://browserhacks.com/#hack-e71d8692f65334173fee715c222cb805 + // Tests for existence of standard globals is to allow style-loader + // to operate correctly into non-standard environments + // @see https://github.com/webpack-contrib/style-loader/issues/177 + memo = Boolean(window && document && document.all && !window.atob); + } + + return memo; + }; +}(); + +var getTarget = function getTarget() { + var memo = {}; + return function memorize(target) { + if (typeof memo[target] === 'undefined') { + var styleTarget = document.querySelector(target); // Special case to return head of iframe instead of iframe itself + + if (window.HTMLIFrameElement && styleTarget instanceof window.HTMLIFrameElement) { + try { + // This will throw an exception if access to iframe is blocked + // due to cross-origin restrictions + styleTarget = styleTarget.contentDocument.head; + } catch (e) { + // istanbul ignore next + styleTarget = null; + } + } + + memo[target] = styleTarget; + } + + return memo[target]; + }; +}(); + +var stylesInDom = []; + +function getIndexByIdentifier(identifier) { + var result = -1; + + for (var i = 0; i < stylesInDom.length; i++) { + if (stylesInDom[i].identifier === identifier) { + result = i; + break; + } + } + + return result; +} + +function modulesToDom(list, options) { + var idCountMap = {}; + var identifiers = []; + + for (var i = 0; i < list.length; i++) { + var item = list[i]; + var id = options.base ? item[0] + options.base : item[0]; + var count = idCountMap[id] || 0; + var identifier = "".concat(id, " ").concat(count); + idCountMap[id] = count + 1; + var index = getIndexByIdentifier(identifier); + var obj = { + css: item[1], + media: item[2], + sourceMap: item[3] + }; + + if (index !== -1) { + stylesInDom[index].references++; + stylesInDom[index].updater(obj); + } else { + stylesInDom.push({ + identifier: identifier, + updater: addStyle(obj, options), + references: 1 + }); + } + + identifiers.push(identifier); + } + + return identifiers; +} + +function insertStyleElement(options) { + var style = document.createElement('style'); + var attributes = options.attributes || {}; + + if (typeof attributes.nonce === 'undefined') { + var nonce = true ? __webpack_require__.nc : undefined; + + if (nonce) { + attributes.nonce = nonce; + } + } + + Object.keys(attributes).forEach(function (key) { + style.setAttribute(key, attributes[key]); + }); + + if (typeof options.insert === 'function') { + options.insert(style); + } else { + var target = getTarget(options.insert || 'head'); + + if (!target) { + throw new Error("Couldn't find a style target. This probably means that the value for the 'insert' parameter is invalid."); + } + + target.appendChild(style); + } + + return style; +} + +function removeStyleElement(style) { + // istanbul ignore if + if (style.parentNode === null) { + return false; + } + + style.parentNode.removeChild(style); +} +/* istanbul ignore next */ + + +var replaceText = function replaceText() { + var textStore = []; + return function replace(index, replacement) { + textStore[index] = replacement; + return textStore.filter(Boolean).join('\n'); + }; +}(); + +function applyToSingletonTag(style, index, remove, obj) { + var css = remove ? '' : obj.media ? "@media ".concat(obj.media, " {").concat(obj.css, "}") : obj.css; // For old IE + + /* istanbul ignore if */ + + if (style.styleSheet) { + style.styleSheet.cssText = replaceText(index, css); + } else { + var cssNode = document.createTextNode(css); + var childNodes = style.childNodes; + + if (childNodes[index]) { + style.removeChild(childNodes[index]); + } + + if (childNodes.length) { + style.insertBefore(cssNode, childNodes[index]); + } else { + style.appendChild(cssNode); + } + } +} + +function applyToTag(style, options, obj) { + var css = obj.css; + var media = obj.media; + var sourceMap = obj.sourceMap; + + if (media) { + style.setAttribute('media', media); + } else { + style.removeAttribute('media'); + } + + if (sourceMap && btoa) { + css += "\n/*# sourceMappingURL=data:application/json;base64,".concat(btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))), " */"); + } // For old IE + + /* istanbul ignore if */ + + + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + while (style.firstChild) { + style.removeChild(style.firstChild); + } + + style.appendChild(document.createTextNode(css)); + } +} + +var singleton = null; +var singletonCounter = 0; + +function addStyle(obj, options) { + var style; + var update; + var remove; + + if (options.singleton) { + var styleIndex = singletonCounter++; + style = singleton || (singleton = insertStyleElement(options)); + update = applyToSingletonTag.bind(null, style, styleIndex, false); + remove = applyToSingletonTag.bind(null, style, styleIndex, true); + } else { + style = insertStyleElement(options); + update = applyToTag.bind(null, style, options); + + remove = function remove() { + removeStyleElement(style); + }; + } + + update(obj); + return function updateStyle(newObj) { + if (newObj) { + if (newObj.css === obj.css && newObj.media === obj.media && newObj.sourceMap === obj.sourceMap) { + return; + } + + update(obj = newObj); + } else { + remove(); + } + }; +} + +module.exports = function (list, options) { + options = options || {}; // Force single-tag solution on IE6-9, which has a hard limit on the # of diff --git a/sources/NFS_Overview/NFS Overview and Gotchas_files/monthfea.js b/sources/NFS_Overview/NFS Overview and Gotchas_files/monthfea.js new file mode 100644 index 0000000..3981b0c --- /dev/null +++ b/sources/NFS_Overview/NFS Overview and Gotchas_files/monthfea.js @@ -0,0 +1,11 @@ +