Commit 8572f66b authored by Jondy Zhao's avatar Jondy Zhao

netreport: fix the problem that domain-user can't see net-drives

parent f53fc13f
...@@ -18,7 +18,7 @@ Here are example of src/Makefile: ...@@ -18,7 +18,7 @@ Here are example of src/Makefile:
PYTHON = /opt/slapos/bin/python PYTHON = /opt/slapos/bin/python
.PHONY : test .PHONY : test
build: netuse.c build: netuse.c
(cd ..; $(PYTHON) setup.py build) (cd ..; $(PYTHON) setup.py build)
...@@ -32,7 +32,7 @@ Then run test: ...@@ -32,7 +32,7 @@ Then run test:
$ cd src $ cd src
$ make test $ make test
Before test netreport.py, Before test netreport.py,
$ easy_install lxml $ easy_install lxml
$ ln -s /opt/git/slapos.core $ ln -s /opt/git/slapos.core
...@@ -43,6 +43,46 @@ Use Cases ...@@ -43,6 +43,46 @@ Use Cases
Slave Node Slave Node
---------- ----------
Copy file "slapos-monitor", "netuse.dll" to /usr/sbin, then add a startup item for the domain user:
* Logon as local administrator, run the following command in the cygwin terminal:
username="The domain user name, it could be seen in the C:/Documents and Seetings"
target=$(cygpath -w "/cygdrive/c/Documents and Settings/${username}/Start Menu/Programs/Startup/netdrive monitor.lnk")
cat <<EOF > create_shortcut.vbs
Set WshShell = WScript.CreateObject("WScript.Shell")
strStartup = WshShell.SpecialFolders("Startup")
Set oShellLink = WshShell.CreateShortcut("${target}")
oShellLink.TargetPath = "$(cygpath -w /bin/mintty.exe)"
oShellLink.Arguments = "-l /var/log/slap-monitor.log -w hide --exec /usr/sbin/slapos-monitor"
oShellLink.WindowStyle = 1
oShellLink.Description = "netdrive monitor"
oShellLink.WorkingDirectory = "$(cygpath -w /usr/sbin)"
oShellLink.Save
EOF
cscript //B create_shortcut.vbs
rm create_shortcut.vbs
If you don't want to add a shortcut, the second way is to add a startup item in the registry:
* Login as domain user, and run the following command in the cygwin terminal:
regtool set \\HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\slap-monitor \
"$(cygpath -w /bin/mintty.exe) -l /var/log/slap-monitor.log -w hide --exec /usr/sbin/slapos-monitor"
You want to remove the entry by
regtool unset \\HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\slap-monitor
* In case the domain user have no right to change registry, then get sid first:
mkpasswd -d
It will list all the users in the current domain, find the expected sid, suppose it is "S-1-5-21-117609710-920026266-725345543-500", login as local administrator:
regtool set \\HKU\\S-1-5-21-117609710-920026266-725345543-500\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\slap-monitor \
"$(cygpath -w /bin/mintty.exe) -l /var/log/slap-monitor.log -w hide --exec /usr/sbin/slapos-monitor"
Master Node Master Node
----------- -----------
...@@ -53,4 +93,3 @@ Issues ...@@ -53,4 +93,3 @@ Issues
====== ======
1. Some records may be lost if the computer is shutdown in unnormal way. 1. Some records may be lost if the computer is shutdown in unnormal way.
...@@ -27,13 +27,14 @@ ...@@ -27,13 +27,14 @@
# #
############################################################################## ##############################################################################
import argparse import argparse
from datetime import datetime, date
from lxml import etree
import netuse
import os.path import os.path
import slapos.slap.slap import slapos.slap.slap
import sqlite3 import sqlite3
import sys import sys
import xmlrpclib
from datetime import datetime, date
from lxml import etree
from time import sleep from time import sleep
def parseArgumentTuple(): def parseArgumentTuple():
...@@ -59,9 +60,13 @@ def parseArgumentTuple(): ...@@ -59,9 +60,13 @@ def parseArgumentTuple():
parser.add_argument("--data-file", parser.add_argument("--data-file",
help="File used to save report data.", help="File used to save report data.",
default="net_drive_usage_report.data") default="net_drive_usage_report.data")
parser.add_argument("--server-name", parser.add_argument("--port",
help="Interval in seconds to send report to master.", help="RPC Port of SlapMonitor.",
default="") default=8008)
parser.add_argument("--batch",
help="If True, send report per day at mid-night. "
"Otherwise send report instantly.",
default=False)
option = parser.parse_args() option = parser.parse_args()
# Build option_dict # Build option_dict
...@@ -85,7 +90,8 @@ class NetDriveUsageReporter(object): ...@@ -85,7 +90,8 @@ class NetDriveUsageReporter(object):
self._report_date = None self._report_date = None
self.report_interval = float(self.report_interval) self.report_interval = float(self.report_interval)
self.initializeDatabase(self.data_file) self.initializeDatabase(self.data_file)
self.slap_monitor_uri = 'http://localhost:%d' % option_dict['port']
def initializeConnection(self): def initializeConnection(self):
connection_dict = {} connection_dict = {}
connection_dict['key_file'] = self.key_file connection_dict['key_file'] = self.key_file
...@@ -96,8 +102,7 @@ class NetDriveUsageReporter(object): ...@@ -96,8 +102,7 @@ class NetDriveUsageReporter(object):
self._slap_computer = slap.registerComputer(self.computer_id) self._slap_computer = slap.registerComputer(self.computer_id)
def initializeConfigData(self): def initializeConfigData(self):
user_info = netuse.userInfo() self._domain_account = "SlapMonitor"
self._domain_account = "%s\\%s" % user_info[1:3]
q = self._db.execute q = self._db.execute
s = "SELECT _rowid_, report_date FROM config " \ s = "SELECT _rowid_, report_date FROM config " \
...@@ -119,13 +124,14 @@ class NetDriveUsageReporter(object): ...@@ -119,13 +124,14 @@ class NetDriveUsageReporter(object):
last_timestamp = datetime.now() last_timestamp = datetime.now()
interval = 30.0 if self.report_interval > 60 else (self.report_interval / 2) interval = 30.0 if self.report_interval > 60 else (self.report_interval / 2)
try: try:
monitor = xmlrpclib.ServerProxy(self.slap_monitor_uri)
while True: while True:
current_timestamp = datetime.now() current_timestamp = datetime.now()
d = current_timestamp - last_timestamp d = current_timestamp - last_timestamp
if d.seconds < self.report_interval: if d.seconds < self.report_interval:
sleep(interval) sleep(interval)
continue continue
self.insertUsageReport(last_timestamp.isoformat(), d.seconds) self.insertUsageReport(monitor, last_timestamp.isoformat(), d.seconds)
self.sendReport() self.sendReport()
last_timestamp = current_timestamp last_timestamp = current_timestamp
except KeyboardInterrupt: except KeyboardInterrupt:
...@@ -133,20 +139,20 @@ class NetDriveUsageReporter(object): ...@@ -133,20 +139,20 @@ class NetDriveUsageReporter(object):
finally: finally:
self._db.close() self._db.close()
def insertUsageReport(self, start, duration): def insertUsageReport(self, monitor, start, duration):
q = self._db.execute q = self._db.execute
for r in netuse.usageReport(self.server_name): for r in monitor.usageReport():
q( "INSERT INTO net_drive_usage " q( "INSERT INTO net_drive_usage "
"(config_id, drive_letter, remote_folder, " "(config_id, domain_user, drive_letter, remote_folder, "
" start, duration, usage_bytes )" " start, duration, usage_bytes )"
" VALUES (?, ?, ?, ?, ?, ?)", " VALUES (?, ?, ?, ?, ?, ?)",
(self._config_id, r[0], r[1], start, duration, r[3] - r[2])) (self._config_id, r[0], r[1], r[2], start, duration, r[4] - r[3]))
def sendAllReport(self): def sendAllReport(self):
"""Called at startup of this application, send all report """Called at startup of this application, send all report
in the config table.""" in the config table."""
q = self._db.execute q = self._db.execute
for r in q("SELECT _rowid_, domain_account, computer_id, report_date " for r in q("SELECT _rowid_, computer_id, report_date "
"FROM config " "FROM config "
"WHERE report_date < date('now')"): "WHERE report_date < date('now')"):
self._postData(self.generateDailyReport(*r)) self._postData(self.generateDailyReport(*r))
...@@ -160,10 +166,9 @@ class NetDriveUsageReporter(object): ...@@ -160,10 +166,9 @@ class NetDriveUsageReporter(object):
# Change report_date to today # Change report_date to today
# (Optional) Move all the reported data to histroy table # (Optional) Move all the reported data to histroy table
today = date.today().isoformat() today = date.today().isoformat()
if self._report_date < today: if (not self.batch) or self._report_date < today:
self._postData(self.generateDailyReport(self._config_id, self._postData(self.generateDailyReport(self._config_id,
self.computer_id, self.computer_id,
self._domain_account,
self._report_date)) self._report_date))
self._db.execute("UPDATE config SET report_date=? where _rowid_=?", self._db.execute("UPDATE config SET report_date=? where _rowid_=?",
(today, self._config_id)) (today, self._config_id))
...@@ -191,6 +196,7 @@ class NetDriveUsageReporter(object): ...@@ -191,6 +196,7 @@ class NetDriveUsageReporter(object):
config_id INTEGER REFERENCES config ( _rowid_ ), config_id INTEGER REFERENCES config ( _rowid_ ),
drive_letter TEXT NOT NULL, drive_letter TEXT NOT NULL,
remote_folder TEXT NOT NULL, remote_folder TEXT NOT NULL,
domain_user TEXT NOT NULL,
start TEXT DEFAULT CURRENT_TIMESTAMP, start TEXT DEFAULT CURRENT_TIMESTAMP,
duration FLOAT NOT NULL, duration FLOAT NOT NULL,
usage_bytes INTEGER, usage_bytes INTEGER,
...@@ -199,16 +205,17 @@ class NetDriveUsageReporter(object): ...@@ -199,16 +205,17 @@ class NetDriveUsageReporter(object):
config_id INTEGER REFERENCES config ( _rowid_ ), config_id INTEGER REFERENCES config ( _rowid_ ),
drive_letter TEXT NOT NULL, drive_letter TEXT NOT NULL,
remote_folder TEXT NOT NULL, remote_folder TEXT NOT NULL,
domain_user TEXT NOT NULL,
start TEXT NOT NULL, start TEXT NOT NULL,
duration FLOAT NOT NULL, duration FLOAT NOT NULL,
usage_bytes INTEGER, usage_bytes INTEGER,
remark TEXT)""") remark TEXT)""")
def generateDailyReport(self, config_id, computer_id, domain_account, def generateDailyReport(self, config_id, computer_id, report_date, remove=True):
report_date, remove=True):
q = self._db.execute q = self._db.execute
report = etree.Element("consumption") report = etree.Element("consumption")
for r in q("SELECT remote_folder, duration, usage_bytes FROM net_drive_usage " for r in q("SELECT domain_user, remote_folder, duration, usage_bytes "
"FROM net_drive_usage "
"WHERE config_id=? AND strftime('%Y-%m-%d', start)=?", "WHERE config_id=? AND strftime('%Y-%m-%d', start)=?",
(config_id, report_date)): (config_id, report_date)):
movement = etree.Element('movement') movement = etree.Element('movement')
...@@ -222,7 +229,7 @@ class NetDriveUsageReporter(object): ...@@ -222,7 +229,7 @@ class NetDriveUsageReporter(object):
movement.append(element) movement.append(element)
element = etree.Element("reference") element = etree.Element("reference")
element.text = domain_account element.text = etree.Element("domain_user"),
movement.append(element) movement.append(element)
element = etree.Element("reference") element = etree.Element("reference")
......
...@@ -131,18 +131,208 @@ netuse_user_info(PyObject *self, PyObject *args) ...@@ -131,18 +131,208 @@ netuse_user_info(PyObject *self, PyObject *args)
return NULL; return NULL;
} }
static char static int
get_free_drive_letter(void) wnet_enumerate_netdrive(LPNETRESOURCE lpnr)
{ {
DWORD bitmasks = GetLogicalDrives(); DWORD dwResult, dwResultEnum;
char ch = 'A'; HANDLE hEnum;
while (bitmasks) { DWORD cbBuffer = 16384; // 16K is a good size
if ((bitmasks & 1L) == 0) DWORD cEntries = -1; // enumerate all possible entries
return ch; LPNETRESOURCE lpnrLocal; // pointer to enumerated structures
++ ch; DWORD i;
bitmasks >>= 1; dwResult = WNetOpenEnum(RESOURCE_GLOBALNET,
RESOURCETYPE_DISK,
0,
lpnr, // NULL first time the function is called
&hEnum); // handle to the resource
if (dwResult != NO_ERROR) {
printf("WnetOpenEnum failed with error %ld\n", dwResult);
return FALSE;
} }
return (char)0; lpnrLocal = (LPNETRESOURCE) GlobalAlloc(GPTR, cbBuffer);
if (lpnrLocal == NULL) {
printf("WnetOpenEnum failed with error %ld\n", dwResult);
return FALSE;
}
do {
ZeroMemory(lpnrLocal, cbBuffer);
dwResultEnum = WNetEnumResource(hEnum, // resource handle
&cEntries, // defined locally as -1
lpnrLocal, // LPNETRESOURCE
&cbBuffer);
if (dwResultEnum == NO_ERROR) {
for (i = 0; i < cEntries; i++) {
printf("NETRESOURCE[%ld] Usage: 0x%ld = ", i, lpnrLocal[i].dwUsage);
if (lpnrLocal[i].dwUsage & RESOURCEUSAGE_CONNECTABLE)
printf("connectable ");
if (lpnrLocal[i].dwUsage & RESOURCEUSAGE_CONTAINER)
printf("container ");
printf("\n");
printf("NETRESOURCE[%ld] Localname: %s\n", i, lpnrLocal[i].lpLocalName);
printf("NETRESOURCE[%ld] Remotename: %s\n", i, lpnrLocal[i].lpRemoteName);
printf("NETRESOURCE[%ld] Comment: %s\n", i, lpnrLocal[i].lpComment);
printf("NETRESOURCE[%ld] Provider: %s\n", i, lpnrLocal[i].lpProvider);
printf("\n");
if (RESOURCEUSAGE_CONTAINER == (lpnrLocal[i].dwUsage
& RESOURCEUSAGE_CONTAINER))
if (!wnet_enumerate_netdrive(&lpnrLocal[i]))
printf("EnumerateFunc returned FALSE\n");
}
}
else if (dwResultEnum != ERROR_NO_MORE_ITEMS) {
printf("WNetEnumResource failed with error %ld\n", dwResultEnum);
break;
}
} while (dwResultEnum != ERROR_NO_MORE_ITEMS);
GlobalFree((HGLOBAL) lpnrLocal);
dwResult = WNetCloseEnum(hEnum);
if (dwResult != NO_ERROR) {
printf("WNetCloseEnum failed with error %ld\n", dwResult);
return FALSE;
}
return TRUE;
}
static int
reg_enumerate_netdrive(void)
{
/* LsaEnumerateLogonSessions -> LogonId */
/* OpenTokenByLogonId -> TokenHandle */
/* LsaGetLogonSessionData -> Sid */
/* ConvertSidToStringSid */
/* From regkey HKU\SID\NETWORK */
/* ImpersonateLoggedOnUser Or CreateProcessWithTokenW */
/* WNetAddConnection */
return 0;
}
static PyObject *
netuse_list_drive(PyObject *self, PyObject *args)
{
PyObject *retvalue = NULL;
PyObject *pobj = NULL;
char *servername = NULL;
char *username = NULL;
char *password = NULL;
char chdrive = 'A';
char drivepath[] = { 'A', ':', '\\', 0 };
char drivename[] = { 'A', ':', 0 };
char szRemoteName[MAX_PATH];
DWORD dwResult;
DWORD cchBuff = MAX_PATH;
char szUserName[MAX_PATH];
if (! PyArg_ParseTuple(args, "|s", &servername)) {
return NULL;
}
retvalue = PyList_New(0);
if (retvalue == NULL)
return NULL;
while (chdrive <= 'Z') {
drivepath[0] = chdrive;
drivename[0] = chdrive;
dwResult = WNetGetConnection(drivename,
szRemoteName,
&cchBuff
);
if (dwResult == NO_ERROR) {
dwResult = WNetGetUser("z:",
(LPSTR) szUserName,
&cchBuff);
pobj = Py_BuildValue("ssss",
drivename,
szRemoteName,
"OK",
szUserName
);
if (PyList_Append(retvalue, pobj) == -1) {
Py_XDECREF(retvalue);
return NULL;
}
}
else if (dwResult == ERROR_CONNECTION_UNAVAIL) {
}
else if (dwResult == ERROR_NOT_CONNECTED) {
}
else if (dwResult == ERROR_BAD_DEVICE) {
}
else if (dwResult == ERROR_NO_NET_OR_BAD_PATH) {
}
else {
PyErr_Format(PyExc_RuntimeError,
"A system error has occurred in WNetGetConnection: %ld",
GetLastError()
);
Py_XDECREF(retvalue);
return NULL;
}
++ chdrive;
}
return retvalue;
}
static int
connect_net_drive(char *remote, char *drive)
{
DWORD dwRetVal;
NETRESOURCE nr;
DWORD dwFlags;
char *password=NULL;
char *user=NULL;
memset(&nr, 0, sizeof (NETRESOURCE));
nr.dwType = RESOURCETYPE_DISK;
nr.lpLocalName = drive;
nr.lpRemoteName = remote;
nr.lpProvider = NULL;
dwFlags = CONNECT_REDIRECT;
dwRetVal = WNetAddConnection2(&nr, password, user, dwFlags);
if (dwRetVal == NO_ERROR)
return 0;
PyErr_Format(PyExc_RuntimeError,
"WNetAddConnection2 failed with error: %lu\n",
dwRetVal
);
return dwRetVal;
}
static PyObject *
netuse_auto_connect(PyObject *self, PyObject *args)
{
Py_RETURN_NONE;
}
static PyObject *
netuse_remove_drive(PyObject *self, PyObject *args)
{
DWORD dwRetVal;
char *drive = NULL;
int force = 1;
if (! PyArg_ParseTuple(args, "si", &drive, &force))
return NULL;
dwRetVal = WNetCancelConnection2(drive, 0, force);
if (dwRetVal == NO_ERROR)
Py_RETURN_NONE;
PyErr_Format(PyExc_RuntimeError,
"WNetCancelConnection2 failed with error: %lu\n",
dwRetVal
);
return NULL;
} }
static PyObject * static PyObject *
...@@ -153,20 +343,15 @@ netuse_map_drive(PyObject *self, PyObject *args) ...@@ -153,20 +343,15 @@ netuse_map_drive(PyObject *self, PyObject *args)
DWORD dwFlags; DWORD dwFlags;
char *remote = NULL; char *remote = NULL;
char drive[] = { 0, ':', 0 }; char *drive = NULL;
char *user = NULL; char *user = NULL;
char *password = NULL; char *password = NULL;
if (! PyArg_ParseTuple(args, "s", &remote)) { char accessName[MAX_PATH] = {0};
return NULL; DWORD dwBufSize = MAX_PATH;
} DWORD dwResult;
drive[0] = get_free_drive_letter(); if (! PyArg_ParseTuple(args, "ss|ss", &remote, &drive, &user, &password))
if (!drive[0]) {
PyErr_SetString(PyExc_RuntimeError,
"Add net drive failed: no available drive letter."
);
return NULL; return NULL;
}
memset(&nr, 0, sizeof (NETRESOURCE)); memset(&nr, 0, sizeof (NETRESOURCE));
nr.dwType = RESOURCETYPE_DISK; nr.dwType = RESOURCETYPE_DISK;
...@@ -175,15 +360,72 @@ netuse_map_drive(PyObject *self, PyObject *args) ...@@ -175,15 +360,72 @@ netuse_map_drive(PyObject *self, PyObject *args)
nr.lpProvider = NULL; nr.lpProvider = NULL;
dwFlags = CONNECT_UPDATE_PROFILE; dwFlags = CONNECT_UPDATE_PROFILE;
dwRetVal = WNetAddConnection2(&nr, password, user, dwFlags); if (drive == NULL)
dwFlags |= CONNECT_REDIRECT;
dwRetVal = WNetUseConnection(NULL,
&nr,
password,
user,
dwFlags,
accessName,
&dwBufSize,
&dwResult);
if (dwRetVal == NO_ERROR) if (dwRetVal == NO_ERROR)
return PyString_FromString(drive); return PyString_FromString(accessName);
PyErr_Format(PyExc_RuntimeError, PyErr_Format(PyExc_RuntimeError,
"WNetAddConnection2 failed with error: %lu\n", "WNetAddConnection2 failed with error: %lu\n",
dwRetVal dwRetVal
); );
return NULL; return NULL;
} }
static PyObject *
netuse_usage_report(PyObject *self, PyObject *args)
{
char *drive = NULL;
PyObject *pobj = NULL;
ULARGE_INTEGER lFreeBytesAvailable;
ULARGE_INTEGER lTotalNumberOfBytes;
/* ULARGE_INTEGER lTotalNumberOfFreeBytes; */
if (! PyArg_ParseTuple(args, "s", &drive))
return NULL;
if (GetDiskFreeSpaceEx(drive,
&lFreeBytesAvailable,
&lTotalNumberOfBytes,
NULL
)) {
pobj = Py_BuildValue("LL", lFreeBytesAvailable, lTotalNumberOfBytes);
return pobj;
}
PyErr_Format(PyExc_RuntimeError,
"A system error has occurred in GetDiskFreeSpaceEx(%s): %ld",
drive,
GetLastError()
);
return NULL;
}
/* Useless code */
#if 0
static char
get_free_drive_letter(void)
{
DWORD bitmasks = GetLogicalDrives();
char ch = 'A';
while (bitmasks) {
if ((bitmasks & 1L) == 0)
return ch;
++ ch;
bitmasks >>= 1;
}
return (char)0;
}
/* /*
* Travel all the mapped drive to check whether there is duplicated * Travel all the mapped drive to check whether there is duplicated
* shared folder: * shared folder:
...@@ -235,7 +477,7 @@ check_duplicate_shared_folder(PyObject *retvalue, const char *folder) ...@@ -235,7 +477,7 @@ check_duplicate_shared_folder(PyObject *retvalue, const char *folder)
} }
static PyObject * static PyObject *
netuse_usage_report(PyObject *self, PyObject *args) netuse_usage_report_orig(PyObject *self, PyObject *args)
{ {
char * servername = NULL; char * servername = NULL;
PyObject *retvalue = NULL; PyObject *retvalue = NULL;
...@@ -381,26 +623,72 @@ netuse_usage_report(PyObject *self, PyObject *args) ...@@ -381,26 +623,72 @@ netuse_usage_report(PyObject *self, PyObject *args)
} }
return retvalue; return retvalue;
} }
#endif /* #if 0 */
static PyMethodDef NetUseMethods[] = { static PyMethodDef NetUseMethods[] = {
{ {
"userInfo", "autoConnect",
netuse_user_info, netuse_auto_connect,
METH_VARARGS, METH_VARARGS,
( (
"userInfo()\n\n" "autoConnect()\n\n"
"Get the logon user information, return a tuple:\n" "Create mapped drive from shared folder, it uses the default user\n"
"(server, domain, user).\n" "name. (provided by the user context for the process.)\n"
"Raise exception if something is wrong.\n "
) )
}, },
{ {
"mapDrive", "listNetDrive",
netuse_list_drive,
METH_VARARGS,
(
"listNetDrive()\n\n"
"List all the net drives visible by current user. Return a list:\n"
" [ (drive, remote, status, user), ... ] \n"
"Not that if the calling application is running in a different logon\n"
"session than the application that made the connection, it's\n"
"unvisible for the current application. If the current user has\n"
"administrator privilege, these connections could be shown, but\n"
"the status is unavaliable or unconnect.\n"
"\n"
"Refer to http://msdn.microsoft.com/en-us/library/windows/desktop/aa363908(v=vs.85).aspx\n"
"Defining an MS-DOS Device Name\n"
"Refer to http://msdn.microsoft.com/en-us/library/windows/hardware/ff554302(v=vs.85).aspx\n"
"Local and Global MS-DOS Device Names\n"
)
},
{
"mapNetDrive",
netuse_map_drive, netuse_map_drive,
METH_VARARGS, METH_VARARGS,
( (
"mapDrive(sharefolder)\n\n" "mapNetDrive(remote, drive, user=None, password=None)\n\n"
"Create mapped drive from shared folder, it uses the default user\n" "Create net drive from remote folder, and return the assigned\n"
"name. (provided by the user context for the process.) \n" "drive letter. \n"
"It uses the default user which initialize this remote connection\n"
"if user is None. \n"
"When drive is an empty string, the system will automatically\n"
"assigns network drive letters, letters are assigned beginning\n"
"with Z:, then Y:, and ending with C:\n."
"For examples,"
" mapNetDrive(r'\\\\server\\data')\n"
" mapNetDrive(r'\\\\server\\data', 'T:')\n"
" mapNetDrive(r'\\\\server\\data', 'T:', r'\\\\server\\jack', 'abc')\n"
"Raise exception if something is wrong.\n"
)
},
{
"removeNetDrive",
netuse_remove_drive,
METH_VARARGS,
(
"removeNetDrive(drive, force=True)\n\n"
"Remove mapped drive specified by drive, For example,\n"
" removeNetDrive('X:')\n"
"Parameter force specifies whether the disconnection should occur\n"
"if there are open files or jobs on the connection. If this parameter\n"
"is FALSE, the function fails if there are open files or jobs.\n"
"Raise exception if something is wrong, otherwise return None.\n"
) )
}, },
{ {
...@@ -408,11 +696,22 @@ static PyMethodDef NetUseMethods[] = { ...@@ -408,11 +696,22 @@ static PyMethodDef NetUseMethods[] = {
netuse_usage_report, netuse_usage_report,
METH_VARARGS, METH_VARARGS,
( (
"usagereport(servername='')\n\n" "usageReport(drive)\n\n"
"Return a tuple to report all the net drive information:\n" "Return a tuple to report the usage of the net drive:\n"
"[ (drive, remote, available, total), ... ]\n" " (available, total)\n"
"If servername is not empty, then only net drives in the specified server\n" "For examples,\n"
"are returned.\n" " usageReport('Z:')\n"
"Raise exception if something is wrong.\n"
)
},
{
"userInfo",
netuse_user_info,
METH_VARARGS,
(
"userInfo()\n\n"
"Get the logon user information, return a tuple:\n"
"(server, domain, user).\n"
) )
}, },
{NULL, NULL, 0, NULL} {NULL, NULL, 0, NULL}
......
#!/usr/bin/python
import logging
import os
import sys
from SimpleXMLRPCServer import SimpleXMLRPCServer
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
import netuse
# Restrict to a particular path.
class RequestHandler(SimpleXMLRPCRequestHandler):
rpc_paths = ('/RPC2',)
class SlapNodeMonitor(object):
def __init__(self):
super(SlapNodeMonitor, self).__init__()
self.port = 8008
netuse.autoConnect()
self.drivelist = netuse.listNetDrive()
print 'Net drive list:'
print self.drivelist
def cleanup(self):
pass
def netdrive_usage(self):
'''Get net drive usage, return a list as
[ (user, drive, remote, free, total), ... ]
'''
result = []
for k in self.drivelist:
r = netuse.usageReport(k[0])
result.append((k[3], k[0], k[1], r[0], r[1]))
return repr(result)
def run(self):
# Create server
server = SimpleXMLRPCServer(('localhost', self.port),
requestHandler=RequestHandler)
server.register_introspection_functions()
server.register_function(self.netdrive_usage, 'netdrive_usage')
try:
# Run the server's main loop
server.serve_forever()
except KeyboardInterrupt:
pass
finally:
self.cleanup()
if __name__ == '__main__':
SlapNodeMonitor().run()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment