CIFS Mount External Share - Code for Lua start up.

Hi @akbooer

Just looking at your code for mounting an external CIFS share and I was wondering what to add to have it check for the mount e.g every 30mins and then if the mount (or target share is not there) it should try to mount it again.

(Example of how this may be of use… The NAS is off when the Vera restarts/reloads.

[code]-- cifs mount for use during startup
@akbooer 2014-04-23

local function df ()
local info
local p = io.popen (“df”,‘r’)
if p then info = p:read “*a”; p:close () end
return info
end

local function cifsmount (x)
local function log (msg) luup.log ((“‘%s’ %s”): format (x.device or ‘’, msg), ‘mount’) end
local df = df ()
if df: find (x.device, 1, true) then
log “already mounted”
else
local cmd = table.concat {“mount -t cifs -o user=”, x.user, “,pass=”, x.pass, ",nounix,noserverino " , x.device, ’ ', x.directory}
local ok = os.execute (cmd)
if ok
then log “mounted OK”
else log “failed to mount”
end
end
end

cifsmount {user=user, pass=pass, device=device, directory=directory}[/code]

Also if I wanted to add a prowl notification to this to confirm it is mounted, where is the best place to put it?

luup.inet.wget("http://www.prowlapp.com/publicapi/add?apikey=Myapikey&application=Vera+StartUp+Notification&event=Alert&description=Vera+has+restarted.+The+external+NAS+share+was+" .. Status .. "+mapped&priority=1")

…Status… would be either ‘successfully’ or ‘unsuccessfully’.

Well, you’d do something like:

[ul][li]make the [tt]cifsmount[/tt] function global[/li]
[li]use luup.call_delay to set up a call back if the mount failed[/li]
[li]put the alert status value into the appropriate branch of the return code conditional[/li][/ul]

…or something along those lines.

Thanks

How’s this?

[code]-- cifs mount for use during startup
@akbooer 2014-04-23

local function df ()
local info
local p = io.popen (“df”,‘r’)
if p then info = p:read “*a”; p:close () end
return info
end

local function cifsmount (x)
local function log (msg) luup.log ((“‘%s’ %s”): format (x.device or ‘’, msg), ‘mount’) end
local df = df ()
if df: find (x.device, 1, true) then
log “already mounted”
else
local cmd = table.concat {“mount -t cifs -o user=”, x.user, “,pass=”, x.pass, ",nounix,noserverino " , x.device, ’ ', x.directory}
local ok = os.execute (cmd)
if ok
then log “mounted OK”
luup.inet.wget(“http://www.prowlapp.com/publicapi/add?apikey=Myapikey&application=Vera+StartUp+Notification&event=Alert&description=Vera+has+restarted.+The+external+NAS+share+was+mounted+successfully&priority=1”)
else log “failed to mount, Vera will try again in 10 mins”
luup.inet.wget(“http://www.prowlapp.com/publicapi/add?apikey=Myapikey&application=Vera+StartUp+Notification&event=Alert&description=Vera+has+restarted.+The+external+NAS+share+was+unable+to+be+mounted&priority=1”)
luup.call_delay(“cifsmount”,600)
end
end
end[/code]

Can you remind me of the benefits of global to local, I seem to recall global means the call/function is always available.

It’s a good start. You do need to remove the [tt]local[/tt] in front of the procedure in order to make it global. It’s a requirement of [tt]luup.call_delay[/tt] that the callback handler is global.

Looking again at this code, I’m not convinced that checking the return status of the [tt]os.execute[/tt] function is adequate to check the mount success. I think you may need to look at the third return parameter, which is actually the exit code of the command.

There’s little to no harm in actually running the callback every, say, 10 minutes regardless of the return status, since the mount command won’t be executed if the previous [tt]df[/tt] call indicates that the device is indeed mounted.

I coded a version which has the retry time as an optional parameter, just for generality, but I haven’t tested it.

Hi ParkerC and Akbooer,

was there any progress on this - i too can see a good use for this feature and would be interested to use if either of you got it up and running?

Thank you in advance.

Yes, I have the code somewhere, but it will have to wait until tomorrow.

Okay thank you relay appreciate that :slight_smile:

I’m not sure that this is significantly different from the @parkerc version, and I haven’t been able to test the retry mode (since it always works first time!)

-- cifs mount for use during startup
-- @akbooer 2014-04-23
--

local function df ()
  local info
  local p = io.popen ("df",'r')
  if p then info = p:read "*a"; p:close () end
  return info
end

function cifsmount (x)
  local function log (msg) luup.log (("cifsmount: '%s' %s"): format (x.device or '?', msg)) end
  local df = df ()
  if df: find (x.device, 1, true) then
    log "already mounted"
  else
    local cmd = ("mount -t cifs -o user=%s,pass=%s,nounix,noserverino %s %s"): format (x.user, x.pass, x.device, x.directory)
    local ok, term, status = os.execute (cmd)
    log ("mounted status: "..tostring(status)) 
    if ok 
      then log ("mounted OK: "..tostring(ok)) 
      elseif x.retry then luup.call_delay ("cifsmount", 60 * x.retry)
      else log "failed to mount" 
    end
  end
end


local device = "//172.16.42.100/DATAMINE"
local directory = "/dataMine"
local user = "XXX"
local pass = "xxxxxxxxxxx"

-- optional retry gives interval in minutes to retry failed mount attempt
cifsmount {user=user, pass=pass, device=device, directory=directory, retry=30} 

Thanks akbooer. Will update my startup lua.

HI,
i know this is an old thread but i have just managed to get my edge to map to my nas but it lost the mapping so i am trying to get it automated … i added this code to my start up Lua but i am getting ERROR : Error in lua for scenes and events
i ssh’ed in and tried to run the code as a file but get :

lua test1.lua lua: test1.lua:13: attempt to index global 'luup' (a nil value) stack traceback: test1.lua:13: in function 'log' test1.lua:16: in function 'cifsmount' test1.lua:35: in main chunk [C]: ?
any ideas ?

added :

opkg install cifsmount gives me
Unknown package ‘cifsmount’.
Collected errors:

  • opkg_install_cmd: Cannot install package cifsmount.

Have you seen the recent discussions here?
[url=http://forum.micasaverde.com/index.php/topic,16452.msg223636.html#msg223636]http://forum.micasaverde.com/index.php/topic,16452.msg223636.html#msg223636[/url]

Hello guys,

I have this code to mount my nas on my ui7 vera 3 but it seems that every luup restart, and I have several each day, create an extra mount. Is my code in error?

[code]local function df ()
local info
local p = io.popen (“df”,‘r’)
if p then info = p:read “*a”; p:close () end
return info
end

function cifsmount (x)
local function log (msg) luup.log ((“cifsmount: ‘%s’ %s”): format (x.device or ‘?’, msg)) end
local df = df ()
if df: find (x.device, 1, true) then
log “already mounted”
else
local cmd = (“mount -t cifs -o user=%s,pass=%s,nounix,noserverino %s %s”): format (x.user, x.pass, x.device, x.directory)
local ok, term, status = os.execute (cmd)
log ("mounted status: "…tostring(status))
if ok
then log ("mounted OK: "…tostring(ok))
elseif x.retry then luup.call_delay (“cifsmount”, 60 * x.retry)
else log “failed to mount”
end
end
end

local device = “//192.168.1.16/Vera
local directory = “/qnap”
local user = “Vera”
local pass = “xxx”

– optional retry gives interval in minutes to retry failed mount attempt
cifsmount {user=user, pass=pass, device=device, directory=directory, retry=30}
[/code]

Thanks for any pointers.

Hans

What does [tt]df[/tt] output look like for your multiple mounts?

That section of the code should catch previous mounts, but it seems that it isn’t.

Hello Akbooer,

I had the same thought but how do I catch that variable, need to change the code I guess to put it in the log?

Hans

I was really asking what it looks like if you ssh into Vera and type df at the Unix command prompt.

Aha, well:

Filesystem 1K-blocks Used Available Use% Mounted on /dev/root 4608 4608 0 100% /rom tmpfs 63728 884 62844 1% /tmp tmpfs 512 0 512 0% /dev /dev/mtdblock7 11264 2928 8336 26% /overlay overlayfs:/overlay 11264 2928 8336 26% / /dev/sda1 61481 20743 37563 36% /tmp/log/cmh /dev/mtdblock8 6528 6528 0 100% /mios df: /qnap: Value too large for defined data type df: /qnap: Value too large for defined data type df: /qnap: Value too large for defined data type df: /qnap: Value too large for defined data type df: /qnap: Value too large for defined data type df: /qnap: Value too large for defined data type df: /qnap: Value too large for defined data type df: /qnap: Value too large for defined data type

Well, no wonder the code is having a problem… df is too!

Wonder what all those “Value too large…” things are?

Can you reboot the system and retry? Particularly comparing df after a couple of Luup restarts too.

Well, I googled it and found:

[code]It means that your version of the utilities were not compiled with large file support enabled. The GNU utilities do support large files if they are compiled to do so. You may want to compile them again and make sure that large file support is enabled. This support is automatically configured by autoconf on most systems. But it is possible that on your particular system it could not determine how to do that and therefore autoconf concluded that your system did not support large files.

The message “Value too large for defined data type” is a system error message reported when an operation on a large file is attempted using a non-large file data type. Large files are defined as anything larger than a signed 32-bit integer, or stated differently, larger than 2GB.

Many system calls that deal with files return values in a “long int” data type. On 32-bit hardware a long int is 32-bits and therefore this imposes a 2GB limit on the size of files. When this was invented that was HUGE and it was hard to conceive of needing anything that large. Time has passed and files can be much larger today. On native 64-bit systems the file size limit is usually 2GB * 2GB. Which we will again think is huge.

On a 32-bit system with a 32-bit “long int” you find that you can?t make it any bigger and also maintain compatibility with previous programs. Changing that would break many things! But many systems make it possible to switch into a new program mode which rewrites all of the file operations into a 64-bit program model. Instead of “long” they use a new data type called “off_t” which is constructed to be 64-bits in size. Program source code must be written to use the off_t data type instead of the long data type. This is typically done by defining -D_FILE_OFFSET_BITS=64 or some such. It is system dependent. Once done and once switched into this new mode most programs will support large files just fine.

[/code]

And then looking for a solution to detect wether a mount exists I found:

if grep -qs '/mnt/foo' /proc/mounts; then echo "It's mounted." else echo "It's not mounted." fi

But not sure if these add up to a better solution and how to correctly syntax that…

Hans

The [tt]nounix,noserverino[/tt] options in the mount command were supposed to take care of the “Value too large” error, IIRC.

The code uses the output of the “df” command, rather than peeking into [tt]/proc/mounts[/tt], to find whether it’s already installed. Although I suppose that would be another way to do it.

The publish code seems to work for most people. I’d suggest that there’s something else wrong. Can you try the “df” command after rebooting and a reload as suggested, and see if that brings us some good s=diagnostic information?

[quote=“akbooer, post:8, topic:181206”]I’m not sure that this is significantly different from the @parkerc version, and I haven’t been able to test the retry mode (since it always works first time!)

[code]
– cifs mount for use during startup
@akbooer 2014-04-23

local function df ()
local info
local p = io.popen (“df”,‘r’)
if p then info = p:read “*a”; p:close () end
return info
end

function cifsmount (x)
local function log (msg) luup.log ((“cifsmount: ‘%s’ %s”): format (x.device or ‘?’, msg)) end
local df = df ()
if df: find (x.device, 1, true) then
log “already mounted”
else
local cmd = (“mount -t cifs -o user=%s,pass=%s,nounix,noserverino %s %s”): format (x.user, x.pass, x.device, x.directory)
local ok, term, status = os.execute (cmd)
log ("mounted status: "…tostring(status))
if ok
then log ("mounted OK: "…tostring(ok))
elseif x.retry then luup.call_delay (“cifsmount”, 60 * x.retry)
else log “failed to mount”
end
end
end

local device = “//172.16.42.100/DATAMINE
local directory = “/dataMine”
local user = “XXX”
local pass = “xxxxxxxxxxx”

– optional retry gives interval in minutes to retry failed mount attempt
cifsmount {user=user, pass=pass, device=device, directory=directory, retry=30}
[/code][/quote]

Is it possible to use this startup Lua to mount TWO paths? I want to mount both a path for datamine and datayours.

Tried to just add another block of text in the end but after a reboot only one path was remounted (datamine):

[code]-- cifs mount for use during startup
@akbooer 2014-04-23

local function df ()
local info
local p = io.popen (“df”,‘r’)
if p then info = p:read “*a”; p:close () end
return info
end

function cifsmount (x)
local function log (msg) luup.log ((“cifsmount: ‘%s’ %s”): format (x.device or ‘?’, msg)) end
local df = df ()
if df: find (x.device, 1, true) then
log “already mounted”
else
local cmd = (“mount -t cifs -o user=%s,pass=%s,pass=,sec=ntlm,nounix,noserverino %s %s”): format (x.user, x.pass, x.device, x.directory)
local ok, term, status = os.execute (cmd)
log ("mounted status: "…tostring(status))
if ok
then log ("mounted OK: "…tostring(ok))
elseif x.retry then luup.call_delay (“cifsmount”, 60 * x.retry)
else log “failed to mount”
end
end
end

local device = “//192.168.1.1/16gbusb/datayours
local directory = “/datayours”
local user = “”
local pass = “”

local device = “//192.168.1.1/16gbusb/datamine
local directory = “/datamine”
local user = “”
local pass = “”

– optional retry gives interval in minutes to retry failed mount attempt
cifsmount {user=user, pass=pass, device=device, directory=directory, retry=30} [/code]