开发者

Python - Check network map

I'm looking for some help on logic, the code is not very Pythonic I'm still learning. We map the Z: drive to different locations all the time. Here is what I'm trying to accomplish

1: Check for an old map on Z: say \192.168.1.100\old

2: Map the new location to Z: say \192.168.1.200\new

3: Make sure the new Z: mapping exists and is still connected

4: If it gets disconnected or unmapped reconnect it and log it

90% of the code works, if I run it as is, it unmaps the old drive and maps the new drive but the name of the old drive stays the same even though it's mapped to the new location and I can browse it. The other problem is I only want to run checkOldDrive one time and just let checkDrive run. Any advice is appreciated.

#!/usr/bin/python
import pywintypes
import win32com.client
import os.path
import sys
import string
import fileinput
import time
import win32net
##################################################################
# Check for old Z: map and remove it
# Map the new instance of Z:
# Check if the Z: drive exists
# if the drive exists report to status.log we are working
# if the drive DOES NOT exist map it and report errors to the log
###################################################################
def checkDrive():
    if os.path.exists('z:'):
        saveout = sys.stdout
        fsock = open('status.log', 'a')
        sys.stdout = fsock
        print os.getenv("COMPUTERNAME"), " - ", time.ctime(), " - Connected"
        sys.stdout = saveout
        fsock.close()
    else:
        ivvinetwork = win32com.client.Dispatch('Wscript.Network')
        network_drives = ivvinetwork.EnumNetworkDrives()
        for mapped_drive in [network_drives.Item(i)
                             for i in range(0, network_drives.Count() -1 , 2)
                             if network_drives.Item(i)]:
            ivvinetwork.RemoveNetworkDrive(mapped_drive, True, True)
  开发者_Python百科      drive_mapping = [
            ('z:', '\\\\192.168.1.100\\newmap', 'someuser', 'somepass')]
        for drive_letter, network_path, user_name, user_pass in drive_mapping:
            try:
                ivvinetwork.MapNetworkDrive(drive_letter, network_path, True, user_name, user_pass)
                saveout = sys.stdout
                fsock = open('status.log', 'a')
                sys.stdout = fsock
                print os.getenv("COMPUTERNAME"), " - ", time.ctime(), " - ", drive_mapping, "Drive Has Been Mapped"
                sys.stdout = saveout
                fsock.close()
            except Exception, err:
                saveout = sys.stdout
                fsock = open('status.log', 'a')
                sys.stdout = fsock
                print os.getenv("COMPUTERNAME"), " - ", time.ctime(), " - ", err
                sys.stdout = saveout
                fsock.close()

def checkOldDrive():
    if os.path.exists('z:'):
        ivvinetwork = win32com.client.Dispatch('Wscript.Network')
        network_drives = ivvinetwork.EnumNetworkDrives()
        for mapped_drive in [network_drives.Item(i)
                             for i in range(0, network_drives.Count() -1 , 2)
                             if network_drives.Item(i)]:
            ivvinetwork.RemoveNetworkDrive(mapped_drive, True, True)

checkOldDrive()
checkDrive()


I've put together a script based on the one you laid out which I believe accomplishes what you have described.

I've tried to do it in a way that's both Pythonic and follows good programming principles.

In particular, I've done the following:

  • modularize much of the functionality into reusable functions
  • avoided repetition as much as possible. I did not factor out the hard-coded 'Z:' drive. I leave that to you as an exercise (as you see fit).
  • factored the logging definition into one location (so the format, etc are consistent and not repeated). The logging module made this easy.
  • moved all code out of the top level scope (except for some global constants). This allows the script to be run directly or imported by another script as a module.
  • Added some documentation strings to help document what each function does.
  • Kept each function short an succinct - so it can be read more easily on a single screen and in an isolated context.

Surely, there is still room for some improvement, but I have tested this script and it is functional. It should provide some good lessons while also helping you accomplish your task. Enjoy.

#!/usr/bin/env python
import os
import time
import win32com.client
import logging

old_mappings = [
    r'\\192.168.1.100\old',
    ]
new_mapping = r'\\192.168.1.200\new'
LOG_FILENAME = 'status.log'

def main():
    """
    Check to see if Z: is mapped to the old server; if so remove it and
    map the Z: to the new server.

    Then, repeatedly monitor the Z: mapping. If the Z: drive exists,
    report to status.log that we are working. Otherwise, re-map it and
    report errors to the log.
    """
    setupLogging()
    replaceMapping()
    monitorMapping()

def replaceMapping():
    if removeMapping():
        createNewMapping()

def setupLogging():
    format = os.environ['COMPUTERNAME'] + " - %(asctime)s - %(message)s"
    logging.basicConfig(filename=LOG_FILENAME, level=logging.DEBUG, format=format)

def getCredentials():
    """
    Return one of three things:
    - an empty tuple
    - a tuple containing just a username (if a password is not required)
    - a tuple containing username and password
    """
    return ('someuser', 'somepass')

def createNewMapping():
    network = win32com.client.Dispatch('WScript.Network')
    params = (
        'Z:', # drive letter
        new_mapping, # UNC path
        True, # update profile
        )
    params += getCredentials()
    try:
        network.MapNetworkDrive(*params)
        msg = '{params} - Drive has been mapped'
        logging.getLogger().info(msg.format(**vars()))
    except Exception as e:
        msg = 'error mapping {params}'
        logging.getLogger().exception(msg.format(**vars()))

def monitorMapping():
    while True:
        # only check once a minute
        time.sleep(60)
        checkMapping()

def checkMapping():
    if getDriveMappings()['Z:'] == new_mapping:
        msg = 'Drive is still mapped'
        logging.getLogger().info(msg.format(**vars()))
    else:
        replaceMapping()

# From Python 2.6.4 docs
from itertools import izip_longest
def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

def getDriveMappings():
    """
    Return a dictionary of drive letter to UNC paths as mapped on the
    system.
    """
    network = win32com.client.Dispatch('WScript.Network')
    # http://msdn.microsoft.com/en-us/library/t9zt39at%28VS.85%29.aspx
    drives = network.EnumNetworkDrives()
    # EnumNetworkDrives returns an even-length array of drive/unc pairs.
    # Use grouper to convert this to a dictionary.
    result = dict(grouper(2, drives))
    # Potentially several UNC paths will be connected but not assigned
    # to any drive letter. Since only the last will be in the
    # dictionary, remove it.
    if '' in result: del result['']
    return result

def getUNCForDrive(drive):
    """
    Get the UNC path for a mapped drive.
    Throws a KeyError if no mapping exists.
    """
    return getDriveMappings()[drive.upper()]

def removeMapping():
    """
    Remove the old drive mapping. If it is removed, or was not present,
    return True.
    Otherwise, return False or None.
    """
    mapped_drives = getDriveMappings()
    drive_letter = 'Z:'
    if not drive_letter in mapped_drives:
        return True
    if mapped_drives[drive_letter] in old_mappings:
        network = win32com.client.Dispatch('WScript.Network')
        force = True
        update_profile = True
        network.RemoveNetworkDrive(drive_letter, force, update_profile)
        return True
    # return None

if __name__ == '__main__':
    main()
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜