At the
start of the month I wrote about 7 to C Gran
Turismo (7CGT). To neatly close off the month, here’s a tool for
translating 7-Mode usermap into (Clustered) ONTAP name-mappings. The
Usermap7toC tool creates a script of Clustershell commands.
Like
7CGT, the Usermap7toC tool is designed to handle multiple consolidations of
pFilers and vFilers down to a single SVM, and detect conflicts (conflicting
name mappings across different filers) where remediation is required.
Like
7CGT, the Usermap7toC tool can be run online (with ONTAPI access to 7-Mode
systems and ONTAP systems), or offline (where you have no ONTAPI access, but
can be provided with config files.) Here I’ll just cover how to run in online
mode.
How to Run Usermap 7 to C
First,
you’ll need to prepare the file U7C.7ModeFilers.TXT.
Example content:
FAS101,vfiler0
FAS101,FAS101_VF1
Then
just run in PowerShell (PS>) as:
.\Usermap7toC.ps1
And
follow the prompts.
Note: It does need the following files to exist
(online mode will create these files unless there’s no content - i.e. no
current ONTAP usermaps - in which case just create blank text files with these
names.)
- U7C.CdotNameMap.TXT
- U7C.CdotUnixGroups.TXT
- U7C.CdotUnixUsers.TXT
Image: Usage Example of Usermap 7 to C (up to
final prompt)
Any
questions, please let me know and I’ll endeavour to reply.
The PowerShell Code
Apologies
the code is a bit clunky. It was basically a lift and shift of the usermap part
from the 7CGT code, hence there’s more code than necessary.
#########################
## U7C: Usermap 7 to C ##
#########################
Param(
# 7-Mode pFiler and any vFilers as lines of
PFILER,{VFILER or "vFiler0"}
[String]$7ModeFilersFile =
"U7C.7ModeFilers.TXT",
# CDOT UNIX USERS file/filepath
[String]$CdotUnixUsersFile =
"U7C.CdotUnixUsers.TXT",
# CDOT UNIX GROUPS file/filepath
[String]$CdotUnixGroupsFile = "U7C.CdotUnixGroups.TXT",
# CDOT NAME MAPPING file/filepath
[String]$CdotNameMappingFile =
"U7C.CdotNameMap.TXT",
# Output File Name
[String]$OutputFileName =
"U7C.Output.TXT"
)
[String]$Version =
"1.0"
<#
(Info for OFFLINE mode)
To obtain the CDOT Unix
Users, Unix Groups, and Name-Mappings ...
... please run via the
Clustershell -
::> row 0; set
-showseparator ","
- followed by the command(s)
below ...
... and save into separate
text files (hash out column headers).
UNIX USERS:
::> unix-user show
-vserver $SVM -fields user,id,primary-gid,full-name
UNIX GROUPS:
::> unix-group show
-vserver $SVM -fields name,id
USERMAP:
::> name-mapping show
-vserver $SVM -fields direction,position,pattern,replacement
#>
## BASIC DISPLAY FUNCTIONS /
GENERIC FUNCTIONS ##
##
=========================================== ##
FUNCTION
Uline{$args[0];("## " + "".PadRight($args[0].length
-6,"=") + " ##");""}
FUNCTION
Wr{Param([String]$P,[String]$C = "WHITE")
IF($P){Write-Host $P -ForegroundColor $C
-NoNewLine}ELSE{Write-Host}}
FUNCTION
PressEnterToContinue{Wr "Press Enter to continue... "
Cyan;[Void](Read-Host)}
FUNCTION EXITING{Wr " -
exiting!" RED;Wr;Wr;PressEnterToContinue;EXIT}
FUNCTION PromptValidator{
Param([Switch]$YesOrNo) # $args is used
WHILE ($TRUE){
$ReadIn = Read-Host
IF($YesOrNo){ # CONDITION 1: Yes or No
IF(($ReadIn -eq "YES") -or
($ReadIn -eq "Y")){RETURN $True }
IF(($ReadIn -eq "NO") -or ($ReadIn -eq "N")){RETURN
$False}
} ELSEIF($args[0]){ # CONDITION 2: Check
input against arguments
FOREACH($argument in $args){IF($ReadIn
-eq $argument){RETURN $ReadIn}}
} ELSE { # CONDITION 3: Make sure input
>= 1 char
IF($ReadIn.length -ge 1){RETURN
$ReadIn}}}
}
FUNCTION PromptSetting{
Param([String]$Prompt,[String]$Setting,[Switch]$AllowEnter)
Wr $Prompt CYAN
# If we have SETTING defined, write to host
SETTING and return SETTING!
IF($Setting){Wr $Setting;Wr;RETURN $Setting}
# If we allow enter (e.g "") to read-host,
we can return "" or the new setting
IF($AllowEnter){$NewSetting =
Read-Host;RETURN $NewSetting}
# Otherwise, don't return until we've got
more than a ""
RETURN (PromptValidator)
}
FUNCTION ProcessYesNoSwitch{
Param([String]$Question,[Boolean]$EnableSwitch,[Boolean]$DisableSwitch)
Wr $Question CYAN
IF($EnableSwitch){Wr
"YES";Wr;RETURN $true}
ELSEIF($DisableSwitch){Wr
"NO";Wr;RETURN $false}
ELSE{PromptValidator -YesOrNo}
}
FUNCTION ProcessArray {
Param([System.Array]$ArrayToProcess,[Switch]$AllowHash)
# AllowHash because some files (like CIFS
share names) use hashes
[System.Array]$ProcessedArray = @()
FOREACH ($ArrayLine in $ArrayToProcess){
# Remove blank lines ""
IF($ArrayLine -ne ""){
# Ignore lines beginning with
"#"
IF($ArrayLine.substring(0,1) -ne
"#"){
IF($AllowHash){$ProcessedArray +=
$ArrayLine}
# Remove comments at the end of line
ELSE{$ProcessedArray +=
$ArrayLine.Split("#")[0].Trim()}}}}
, $ProcessedArray
}
FUNCTION
Process7MMTinputFile {
Param([String]$InputFile,[String]$Description,[Switch]$AllowHash)
IF(!(Test-Path $InputFile)){Wr "Path
test to $InputFile failed" RED;EXITING}
[System.Array]$GetFile = Get-Content
$InputFile
# Allow blank input file
IF(!$GetFile){Wr "$InputFile is
empty!" YELLOW;Wr;Wr }
Wr "Loaded $Description from $InputFile
successfully!" GREEN;Wr
IF($AllowHash){$GetFile = ProcessArray
$GetFile -AllowHash}
ELSE{$GetFile = ProcessArray $GetFile}
, $GetFile
}
## CONNECT TO 7-MODE/CDOT
CLUSTER FUNCTION ##
##
======================================= ##
FUNCTION Get-PsCredential{
Param([String]$User,[String]$Prompt)
Wr $Prompt CYAN;$P = Read-Host
-AsSecureString;Wr
RETURN (New-Object System.Management.Automation.PsCredential($User,$P))
}
FUNCTION Load-DataOntapPSTK{
IF(Get-Module DataONTAP){RETURN}
[Void](Import-Module DataONTAP -ErrorAction
SilentlyContinue)
IF(!(Get-Module DataONTAP)){Wr "Unable
to load the DataONTAP PSTK" RED;EXITING}
Wr "Loaded the DataONTAP PSTK!"
GREEN;Wr;Wr
}
FUNCTION Connect-ToNetApp{
Param([String]$Name,[System.Object]$Cred,[Switch]$SevenMode)
[Void](Load-DataOntapPSTK)
Wr "Checking connection to $Name
..." CYAN;Wr
IF($SevenMode){
$C = Connect-NaController -Name $Name
-Credential $Cred -Timeout 20000 -ErrorAction SilentlyContinue
}ELSE{
$C = Connect-NcController -Name $Name
-Credential $Cred -Timeout 20000 -ErrorAction SilentlyContinue
}
IF($C){Wr "Successfully connected to
$Name" GREEN;Wr;Wr}
ELSE{Wr "Unable to connect to
$Name" RED;EXITING}
}
#############################
## PART 1: DATA COLLECTION
##
#############################
Wr;Wr
"<<<<<<<<<< U7C: Usermap7toC $Version
>>>>>>>>>>" MAGENTA;Wr
Wr;Wr
">>>>>>> PART 1: DATA COLLECTION <<<<<<<"
MAGENTA;Wr;Wr
[System.Array]$Systems7G =
@()
[System.Object]$vFilerList =
@{}
[System.Array]$7MFFcontent =
Process7MMTinputFile $7ModeFilersFile
"7-Mode Filers File"
## PROCESS THE 7-MODE FILERS
FILE ##
Wr;Wr ">>>
PROECESSING 7-MODE FILERS FILE <<<" GREEN;Wr;Wr
FOREACH ($line in
$7MFFcontent){
$lineSplit = $line.split(",")
IF($lineSplit.count -eq 2){
# Valid input has 2 CSV columns
[String]$pFiler = $lineSplit[0]
[String]$vFiler = $lineSplit[1]
}
IF($pFiler -and $vFiler){
# Valid input requires pFiler and vFiler!
IF($Systems7G -contains $pFiler){}
ELSE{
$Systems7G += $pFiler
[System.Object]$vFilerList.$pFiler = @{}
[System.Array]$vFilerList.$pFiler.vFilers
= @()
}
IF($vFilerList.$pFiler.vFilers -contains
$vFiler){}
ELSE{
$vFilerList.$pFiler.vFilers += $vFiler
Wr "pFiler: " CYAN;Wr
$pFiler;Wr " - vFiler: " CYAN;Wr $vFiler;Wr
}
}
}
IF(!$Systems7G){Wr;Wr
"Error processing the 7-Mode Filers File $7ModeFilersFile" RED;
EXITING}
FUNCTION Get-7MConfigFile{
Param([String]$ETCPATH,[String]$7MConfigFile,[String]$ConfigDirectory)
Wr "Reading the file: " GREEN;Wr
$7MConfigFile;Wr
[String]$StringOutput = Read-NaFile ($ETCPATH
+ "/$7MConfigFile")
[System.Array]$ArrayOutput =
$StringOutput.Split("`n")
$ArrayOutput | Set-Content ($ConfigDirectory
+ "/" + $7MConfigFile)
}
## 7-Mode: ONLINE MODE ##
## =================== ##
Wr;[Boolean]$OnlineFor7Mode
= ProcessYesNoSwitch "Online acquisition of 7-Mode Config Files (yes/no)?
";Wr
IF($OnlineFor7Mode){
$UserName7Mode = PromptSetting "7-Mode
Username: "
$Credential7M
= Get-PsCredential $UserName7Mode "7-Mode Password: "
$Systems7G | FOREACH {
[Void](Connect-ToNetApp $_ $Credential7M
-SevenMode)
FOREACH($vFiler in $vFilerList.$_.vFilers){
[String]$GetRootVol = "";
[String]$ETCPATH = ""
[String]$SaveFolder = ($_ + "."
+ $vFiler)
[Void](New-Item -Path $SaveFolder
-ItemType Directory -Force)
IF($vFiler -eq
"vFiler0"){$global:CurrentNaController.vfiler = ""}
ELSE{$global:CurrentNaController.vfiler =
$vFiler}
$GetRootVol = (Get-NaVolRoot -ErrorAction
SilentlyContinue).Name
IF($GetRootVol){$ETCPATH =
"/vol/" + $GetRootVol + "/etc"}
ELSE{$ETCPATH = (Get-NaCifsShare -Share
ETC$).MountPoint }
IF(!$ETCPATH){Wr;Wr "Unable to
determine $_ $vFiler 's /etc path" RED;EXITING}
Wr "ETC path for 7GSystem = $_ &
vFiler = $vFiler is " GREEN;Wr $ETCPATH YELLOW;Wr
[Void](Get-7MConfigFile $ETCPATH
"group" $SaveFolder)
[Void](Get-7MConfigFile $ETCPATH
"passwd" $SaveFolder)
[Void](Get-7MConfigFile $ETCPATH
"usermap.cfg" $SaveFolder);Wr
}
}
}
## PRIMARY CDOT CLUSTER
& SVM ##
##
========================== ##
Wr;Wr ">>>
PRIMARY cDOT CLUSTER & SVM <<<" GREEN;Wr;Wr
$Cluster = PromptSetting
"Enter the Cluster: "
$SVM = PromptSetting "Enter the SVM : ";Wr
[Boolean]$OnlineForCDOT =
ProcessYesNoSwitch "Online cDOT data acquisition (yes/no)? ";Wr
IF($OnlineForCDOT){
$UserNameCdot = PromptSetting "Cluster
User: "
$Credential = Get-PsCredential $UserNameCdot
"Cluster Password: "
[Void](Connect-ToNetApp $Cluster $Credential)
}
## FUNCTION: COLLECT
REQUIRED 7G CONFIG FILES (per vFiler) ##
##
======================================================= ##
FUNCTION GetConfigFile {
Param([String]$7GcfgFile,[String]$7GSystem,[String]$vFilerName)
Wr ("Looking for $7GcfgFile - for
$7Gsystem & $vFilerName - in folder(s):") GREEN;Wr
Wr ($7Gsystem + "." + $vFilerName)
YELLOW
IF($vFilerName -eq "vFiler0"){Wr
" ";Wr ($7Gsystem) YELLOW };Wr
IF(Test-Path ($7Gsystem + "." +
$vFilerName + "\" + $7GcfgFile)){
$ArrayOutput = Get-Content ($7Gsystem +
"." + $vFilerName + "\" + $7GcfgFile)
}ELSEIF(($vFilerName -eq "vFiler0")
-and (Test-Path ($7Gsystem + "\" + $7GcfgFile))){
$ArrayOutput = Get-Content ($7Gsystem +
"\" + $7GcfgFile)
}ELSE{Wr "Unable to find
file"RED;EXITING} # USE BLANK FILES IF NO DATA!
IF(!$ArrayOutput){Wr "$7GcfgFile file at
$cfgFilePath is a blank file!" YELLOW;Wr;Wr}
, $ArrayOutput
}
## INITIALIZE VARIABLES ##
[System.Object]$PasswdFile = @{} # Passwd file in
$PasswdFile.$7GSystem.$vFiler
[System.Object]$GroupFile = @{} # Group file in
$GroupFile.$7GSystem.$vFiler
[System.Object]$UsermapFile = @{} # Usermap file in
$UsermapFile.$7GSystem.$vFiler
[System.Object]$CdotUU = @{} # Init. Cdot Unix Users - OBJECT
[System.Array]$CdotUU.Users = @() # Init. " - Users ARRAY
[System.Array]$CdotUU.UIDs = @() # Init. " - UIDs ARRAY
[System.Object]$CdotUU.User = @{} # Init. " - User OBJECT
[System.Object]$CdotUU.UID = @{} # Init. " - UID OBJECT
[System.Object]$CdotUG = @{} # Init. Cdot Unix Groups - OBJECT
[System.Array]$CdotUG.Groups
= @() # Init. " - Groups ARRAY
[System.Array]$CdotUG.GIDs = @() # Init. " - GIDs ARRAY
[System.Object]$CdotUG.Group
= @{} # Init. " - Group OBJECT
[System.Object]$CdotUG.GID = @{} # Init. " - GID OBJECT
## USERMAP COLLECTION and
PROCESSING ##
##
================================= ##
Wr;Wr ">>>
USERMAP COLLECTION and PROCESSING <<<" GREEN;Wr;Wr
Wr "7-Mode group file
-> CDOT Unix Groups" GREEN;Wr
Wr "7-Mode passwd file
-> CDOT Unix Users" GREEN;Wr
Wr "7-Mode usermap.cfg
file -> CDOT Name Mappings" GREEN;Wr;Wr
Wr; Wr ">>>
COLLECT passwd/group/usermap.cfg FILES <<<" GREEN;Wr;Wr
$Systems7G | FOREACH{
[System.Object]$PasswdFile.$_ = @{}
[System.Object]$GroupFile.$_ = @{}
[System.Object]$UsermapFile.$_ = @{}
FOREACH($vFiler in ($vFilerList.$_.vFilers)){
$PasswdFile.$_.$vFiler = ProcessArray
(GetConfigFile "passwd" $_ $vFiler)
Wr "passwd file for $_ vfiler $vfiler
:" GREEN;Wr;Wr
FOREACH($line in ($PasswdFile.$_.$vFiler)){Wr
$line YELLOW;Wr};Wr
$GroupFile.$_.$vFiler = ProcessArray
(GetConfigFile "group" $_ $vFiler)
Wr "group file for $_ vfiler $vfiler
:" GREEN;Wr;Wr
FOREACH($line in
($GroupFile.$_.$vFiler)){Wr $line YELLOW;Wr};Wr
$UsermapFile.$_.$vFiler = ProcessArray
(GetConfigFile "usermap.cfg" $_ $vFiler)
Wr "usermap.cfg file for $_ vfiler
$vfiler :" GREEN;Wr;Wr
FOREACH($line in
($UsermapFile.$_.$vFiler)){Wr $line YELLOW;Wr};Wr
}
}
## GET
passwd/group/usermap.cfg CONFIGURATIONS FROM CDOT ##
##
====================================================== ##
Wr;Wr ">>> GET
passwd/group/usermap.cfg CONFIGURATIONS FROM CDOT <<<"
GREEN;Wr;Wr
## >> PROCESSING CDOT
UNIX USERS << ##
IF($OnlineForCDOT){
$GetNcNameMappingUU = Get-NcNameMappingUnixUser
-VserverContext $SVM
[System.Array]$CdotUnixUsers = @()
$GetNcNameMappingUU | FOREACH{$CdotUnixUsers
+= ($_.Vserver + "," + $_.UserName + "," + $_.UserId +
"," + $_.GroupID)}
$CdotUnixUsers | Set-Content
$CdotUnixUsersFile
}ELSE{
[System.Array]$CdotUnixUsers =
Process7MMTinputFile $CdotUnixUsersFile "CDOT Unix User file";Wr
}
FOREACH($line in
$CdotUnixUsers){
Wr $line YELLOW;Wr
[System.Array]$CommaSplit =
$line.Split(",")
[String]$User = $CommaSplit[1]
[String]$UID
= $CommaSplit[2]
[String]$GID
= $CommaSplit[3]
[System.Object]$CdotUU.User.$User = @{}
[String]$CdotUU.User.$User.UID = $UID
[String]$CdotUU.User.$User.GID = $GID
[System.Object]$CdotUU.UID.$UID = @{}
[String]$CdotUU.UID.$UID.User = $User
[String]$CdotUU.UID.$UID.GID = $GID
$CdotUU.Users += $User
$CdotUU.UIDs
+= $UID
};Wr
## >> PROCESSING CDOT
UNIX GROUPS << ##
IF($OnlineForCDOT){
$GetNcNameMappingUG =
Get-NcNameMappingUnixGroup -VserverContext $SVM
[System.Array]$CdotUnixGroups = @()
$GetNcNameMappingUG | Foreach{$CdotUnixGroups
+= ($_.Vserver + "," + $_.GroupName + "," + $_.GroupId)}
$CdotUnixGroups | Set-Content
$CdotUnixGroupsFile
}ELSE{
[System.Array]$CdotUnixGroups =
Process7MMTinputFile $CdotUnixGroupsFile "CDOT Unix Group file";Wr
}
FOREACH($line in
$CdotUnixGroups){
Wr $line YELLOW;Wr
[System.Array]$CommaSplit =
$line.Split(",")
[String]$Group = $CommaSplit[1]
[String]$GID
= $CommaSplit[2]
[String]$CdotUG.Group.$Group = $GID
[String]$CdotUG.GID.$GID = $Group
$CdotUG.Groups += $Group
$CdotUG.GIDs
+= $GID
};Wr
## >> PROCESSING CDOT
NAMEMAPPINGS << ##
IF($OnlineForCDOT){
$GetNcNameMap = Get-NcNameMapping
-VserverContext $SVM
[System.Array]$CdotNameMappings = @()
$GetNcNameMap | FOREACH {$CdotNameMappings +=
($_.Vserver + "," +
($_.Direction).replace("_","-") + "," +
$_.Position + "," + $_.Pattern + "," + $_.Replacement +
",")}
$CdotNameMappings | Set-Content
$CdotNameMappingFile
}ELSE{
[System.Array]$CdotNameMappings =
Process7MMTinputFile $CdotNameMappingFile "CDOT Name-Mapping file";Wr
}
FOREACH($line in
$CdotNameMappings){Wr $line YELLOW;Wr};Wr
########################################
## PART 2: GENERATING
COMMANDS OUTPUT ##
########################################
Wr;Wr
">>>>>>> PART 2: GENERATING COMMANDS OUTPUT
<<<<<<<" MAGENTA;Wr
Wr;Wr "Clustershell
Output File = " CYAN;Wr $OutputFileName;Wr;Wr
FUNCTION Cshell{("#
" + $ClusterName + "::>"),("")}
## UNIX: PROCESS UNIX GROUPS
& USERS ##
##
================================= ##
[System.Array]$UnixGroupWarningOutput
= @()
[System.Array]$CdotUG.NewGroups
= @()
[System.Array]$UnixUserWarningOutput = @()
[System.Array]$CdotUU.NewUsers
= @()
$Systems7G | FOREACH{
FOREACH($vFiler in ($vFilerList.$_.vFilers)){
## >> PROCESS group FILE << ##
FOREACH($line in $GroupFile.$_.$vFiler ){
[System.Array]$GroupLine =
$line.Split(":")
[String]$UnixGroup = $GroupLine[0]
[String]$UnixGID = $GroupLine[2]
IF($CdotUG.Groups -Contains $UnixGroup){
IF($CdotUG.Group.$UnixGroup -ne
$UnixGID){
$UnixGroupWarningOutput += ("#
++ WARNING ++ UNIX GROUP CONFLICT: Group $UnixGroup exists in SVM $SVM but has
GID " + $CdotUG.Group.$UnixGroup + " and not $UnixGID as in the group
file for $_ $vFiler !")}
}ELSEIF($CdotUG.GIDs -Contains $UnixGID){
IF($CdotUG.GID.$UnixGID -ne
$UnixGroup){
$UnixGroupWarningOutput += ("#
++ WARNING ++ UNIX GROUP CONFLICT: GID $UnixGID exists in SVM $SVM but with
Group Name " + $CdotUG.GID.$UnixGID + " and not $UnixGroup as in the
group file for $_ $vFiler !")}
}ELSE{
$CdotUG.NewGroups += $UnixGroup
$CdotUG.Groups += $UnixGroup
$CdotUG.GIDs += $UnixGID
$CdotUG.Group.$UnixGroup = $UnixGID
$CdotUG.GID.$UnixGID = $UnixGroup
}
}
## >> PROCESS passwd FILE << ##
FOREACH($line in $PasswdFile.$_.$vFiler){
[System.Array]$PasswdLine =
$line.Split(":")
[String]$UnixUser = $PasswdLine[0]
[String]$UnixUID = $PasswdLine[2]
[String]$UnixGID = $PasswdLine[3]
[String]$UnixFullName = $PasswdLine[4]
IF(($UnixGID -eq "") -and
!($CdotUU.Users -Contains $UnixUser)){
$UnixUserWarningOutput += ("# ++
WARNING ++ UNIX USER HAS NO GID: Unix User $UnixUser with UID $UnixUID has no
GID in the Passwd file for $_ $vFiler !")
}ELSEIF($CdotUU.Users -Contains
$UnixUser){
IF($CdotUU.User.$UnixUser.UID -ne
$UnixUID){
$UnixUserWarningOutput += ("# ++
WARNING ++ UNIX USER CONFLICT: Unix User $UnixUser exists in SVM $SVM but has
UID " + $CdotUU.User.$UnixUser.UID + " and not $UnixUID as in the
Passwd for $_ $vFiler !")}
IF(($CdotUU.User.$UnixUser.GID -ne
$UnixGID) -and ($UnixGID -ne "")){
$UnixUserWarningOutput += ("# ++
WARNING ++ UNIX USER CONFLICT: Unix User $UnixUser exists in SVM $SVM but has
GID " + $CdotUU.User.$UnixUser.GID + " and not $UnixGID as in the
Passwd for $_ $vFiler !")}
}ELSEIF($CdotUU.UIDs -Contains $UnixUID){
IF($CdotUU.UID.$UnixUID.User -ne
$UnixUser){
$UnixUserWarningOutput += ("# ++
WARNING ++ UNIX UID CONFLICT: Unix UID $UnixUID exists in SVM $SVM but has Unix
User " + $CdotUU.UID.$UnixUID.User + " and not $UnixUser as in the
Passwd for $_ $vFiler !")}
IF(($CdotUU.UID.$UnixUID.GID -ne $UnixGID) -and ($UnixGID -ne
"")){
$UnixUserWarningOutput += ("# ++
WARNING ++ UNIX UID CONFLICT: Unix UID $UnixUID exists in SVM $SVM but has GID
" + $CdotUU.UID.$UnixUID.GID + " and not $UnixGID as in the Passwd
for $_ $vFiler !")}
}ELSE{
$CdotUU.NewUsers += $UnixUser
$CdotUU.Users += $UnixUser
$CdotUU.UIDs += $UnixUID
[System.Object]$CdotUU.User.$UnixUser =
@{}
$CdotUU.User.$UnixUser.UID = $UnixUID
$CdotUU.User.$UnixUser.GID = $UnixGID
$CdotUU.User.$UnixUser.FullName =
$UnixFullName
[System.Object]$CdotUU.UID.$UnixUID =
@{}
$CdotUU.UID.$UnixUID.User = $UnixUser
$CdotUU.UID.$UnixUID.GID = $UnixGID
## Fix for Burt 751845 (where a UNIX
group must exist for every Unix User's specified GID) ##
IF(!($CdotUG.GIDs -Contains $UnixGID)){
IF($SVM.length -eq
13){[String]$StdUnixGroupPrefix = $SVM.substring(0,2) + $SVM.substring(5,8)}
ELSE{[String]$StdUnixGroupPrefix =
$SVM}
$UnixGroup = ($StdUnixGroupPrefix +
"_GID" + $UnixGID)
$CdotUG.NewGroups += $UnixGroup
$CdotUG.Groups += $UnixGroup
$CdotUG.GIDs += $UnixGID
$CdotUG.Group.$UnixGroup = $UnixGID
$CdotUG.GID.$UnixGID = $UnixGroup
}
}
}
}
}
FUNCTION
isNumeric($x){$x2=0;$isNum=[System.Int32]::TryParse($x,[ref]$x2);RETURN $isNum}
FUNCTION OUTPUT-UnixGroups{
Param([String]$ClusterName,[String]$SVMname)
Uline ("## UNIX GROUPS
##");$UnixGroupWarningOutput;Cshell
$CdotUG.NewGroups | FOREACH{
IF(!(isNumeric($CdotUG.Group.$_))){
("# ++ WARNING ++ The GID in the next
line not numeric - suspect issues in the passwd file!")
("# unix-group create -vserver
$SVMname -name $_ -id " + $CdotUG.Group.$_)
}ELSE{
("unix-group create -vserver
$SVMname -name $_ -id " + $CdotUG.Group.$_)
}
};("")
}
FUNCTION OUTPUT-UnixUsers{
Param([String]$ClusterName,[String]$SVMname)
Uline ("## UNIX USERS
##");$UnixUserWarningOutput;Cshell
$CdotUU.NewUsers | FOREACH{
If(!(isNumeric($CdotUU.User.$_.GID))){
("# ++ WARNING ++ The GID in the
next line not numeric - suspect issues in the passwd file!")
("# unix-user create -vserver
$SVMname -user $_ -id " + $CdotUU.User.$_.UID + " -primary-gid "
+ $CdotUU.User.$_.GID)
}ELSE{
("unix-user create -vserver $SVMname
-user $_ -id " + $CdotUU.User.$_.UID + " -primary-gid " +
$CdotUU.User.$_.GID + " -full-name " + '"' +
$CdotUU.User.$_.FullName + '"')
}
};("")
}
## UNIX: PROCESS USERMAP ##
## ===================== ##
FUNCTION OUTPUT-UserMap{
Param([String]$ClusterName,[String]$SVMname)
Uline ("## USERMAP
##");Cshell;("set -confirmations off");("")
## GET START NAMEMAP INDEX(s) ##
[Int]$IndexWinUnix = 0
[Int]$IndexUnixWin = 0
FOREACH($NMline in $CdotNameMappings){
$NMline = $NMline.split(",")
IF($NMline[1] -eq "win-unix"){
IF([Int]$NMline[2] -gt
$IndexWinUnix){$IndexWinUnix = [Int]$NMline[2]}}
IF($NMline[1] -eq "unix-win"){
IF([Int]$NMline[2] -gt
$IndexUnixWin){$IndexUnixWin = [Int]$NMline[2]}}
}
## GENERATED NAME MAPS CLUSTERSHELL ##
$Systems7G | FOREACH{
FOREACH($vFiler in
($vFilerList.$_.vFilers)){
FOREACH($line in
$UsermapFile.$_.$vFiler){
[String]$NewLine =
$line.replace("=>","#").replace("<=","#").replace("==","#")
[System.Array]$lineSplit =
$NewLine.Split("#")
IF($LineSplit.Count -eq 1){"# ++
WARNING ++ This line has no =>/<=/==: $line"}
ELSEIF(!$lineSplit[0]){"# ++
WARNING ++ This line has no NT User: $line"}
ELSEIF(!$lineSplit[1]){"# ++
WARNING ++ This line has no UNIX User: $line"}
ELSE{
[String]$NTuser7G =
$lineSplit[0].trim().replace('"','')
[String]$UXuser7G =
$lineSplit[1].trim().replace('"','')
$NTuser7G =
$NTuser7G.replace("\","\\")
IF(!$NTuser7G -or !$UXuser7G){
"# ++ WARNING ++ CDOT does not
support pattern/replacement " + '""' + ": $line"
}ELSE{
[String]$WinUnixErr =
[String]$UnixWinErr = $null
[Boolean]$MatchWinUnix =
[Boolean]$MatchUnixWin = $false
[Boolean]$DirWinUnix =
[Boolean]$DirUnixWin = $false
IF($line -match
"=>"){$DirWinUnix = $true}
IF($line -match
"<="){$DirUnixWin = $true}
IF($line -match
"=="){$DirWinUnix = $DirUnixWin = $true}
IF($line.split(":").count
-gt 1){"# ++ CAUTION ++ IP/Subnet Name Mapping Detected: $line"}
FOREACH($NMline in
$CdotNameMappings){
$NMline =
$NMline.split(",")
IF(!$MatchWinUnix -and
$DirWinUnix -and ($NMline[1] -eq "win-unix")){
IF(($NMline[3] -eq $NTuser7G)){
IF($NMline[4] -eq
$UXuser7G){$MatchWinUnix = $true}
ELSE{$WinUnixErr =
$NMline[4]}
}
}
IF(!$MatchUnixWin -and
$DirUnixWin -and ($NMline[1] -eq "unix-win")){
IF(($NMline[3] -eq $UXuser7G)){
IF($NMline[4] -eq
$NTuser7G){$MatchUnixWin = $true}
ELSE{$UnixWinErr =
$NMline[4]}
}
}
}
#> OUTPUT WIN-UNIX NAME MAPPING
COMMAND <#
IF(!$MatchWinUnix -and
$DirWinUnix){
$IndexWinUnix++;[String]$hash =
""
IF($WinUnixErr){("# ++
WARNING ++ NAME MAPPING CONFLICT: NT User $NTuser7G is already mapped to UNIX
User " + $WinUnixErr + ", but $_ $vFiler wants to map to
$UXuser7G");$hash = "# "}
IF($hash -eq
""){$CdotNameMappings +=
($SVMname + ",win-unix," + $IndexWinUnix + "," + $NTuser7G
+ "," + $UXuser7G + ",")}
# ONTAP 9+ SECTION: START #
# This section handles subnet or
host qualified usermaps.
[String]$IP_SN_HOST =
""
IF($NTuser7G.Split(":").count
-eq 2){
$IP_SN_HOST =
$NTuser7G.split(":")[0]
$NTuser7G = $NTuser7G.split(":")[1]
IF($IP_SN_HOST.Split(".").count -eq 4){$IP_SN_HOST = "
-address $IP_SN_HOST"}
ELSE{$IP_SN_HOST = "
-hostname $IP_SN_HOST"}
}
# ONTAP 9+ SECTION: END
($hash + "vserver
name-mapping create -vserver $SVMname -direction win-unix -position
$IndexWinUnix -pattern " + '"' + $NTuser7G + '"' + "
-replacement " + '"' + $UXuser7G + '"' + $IP_SN_HOST)
}
#> OUTPUT UNIX-WIN NAME MAPPING
COMMAND <#
IF(!$MatchUnixWin -and
$DirUnixWin){
$IndexUnixWin++;[String]$hash =
""
IF($UnixWinErr){("# ++
WARNING ++ NAME MAPPING CONFLICT: UNIX User $UXuser7G is already mapped to NT
User " + $UnixWinErr + ", but $_ $vFiler wants to map to
$NTuser7G");$hash = "# "}
IF($hash -eq
""){$CdotNameMappings +=
($SVMname + ",unix-win," + $IndexUnixWin + "," + $UXuser7G
+ "," + $NTuser7G + ",")}
# ONTAP 9+ SECTION: START #
# This section handles subnet or
host qualified usermaps.
[String]$IP_SN_HOST =
""
IF($UXuser7G.Split(":").count -eq 2){
$IP_SN_HOST =
$UXuser7G.split(":")[0]
$UXuser7G = $UXuser7G.split(":")[1]
IF($IP_SN_HOST.Split(".").count -eq 4){$IP_SN_HOST = "
-address $IP_SN_HOST"}
ELSE{$IP_SN_HOST = "
-hostname $IP_SN_HOST"}
}
# ONTAP 9+ SECTION: END
($hash + "vserver
name-mapping create -vserver $SVMname -direction unix-win -position
$IndexUnixWin -pattern " + '"' + $UXuser7G + '"' + "
-replacement " + '"' + $NTuser7G + '"' + $IP_SN_HOST)
}
}
}
}
}
};("");("set -confirmations
on");("")
}
####################
## PART 3: OUTPUT ##
####################
[System.Array]$Output = @()
$Output += Uline ("##
Usermap 7 to C (U7C): Commands generated on " + (Get-Date -uformat %d%h%G)
+ " ##")
$Output += ("# CAVEAT
UTILITOR! This tool comes with no support and no warranty, please REVIEW,
SANITY CHECK, and UNDERSTAND all commands before application!")
$Output += ("# ++
CAUTION ++ Support for address/hostname vserver name-mappings is
limited!"),("")
$Output += OUTPUT-UnixGroups
$Cluster $SVM
$Output += OUTPUT-UnixUsers
$Cluster $SVM
$Output += OUTPUT-UserMap
$Cluster $SVM
$Output | Set-Content
$OutputFileName;Notepad $OutputFileName
PressEnterToContinue
Comments
Post a Comment