Mario Grunert the Techhead
Montag, 4. Dezember 2023
Dealing with "the authorization policy does not allow saved credentials" in RoyalTS
Dienstag, 18. Januar 2022
Quick-n-dirty function to test a NTP Server per Powershell
.. quite simple - just to test if a ntp server works, if you need more accuracy than +/-9sec just match against ",\ (\+|-)00"
$pinfo=[System.Diagnostics.ProcessStartInfo]::new("$($env:SystemRoot)\system32\w32tm.exe",@("/stripchart","/computer:$ntpserver","/dataonly","/samples:1"))
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$ntptestproc=[System.Diagnostics.Process]::new()
$ntptestproc.StartInfo=$pinfo
$ntptestproc.Start()|Out-Null
$ntptestproc.WaitForExit()
return $ntptestproc.StandardOutput.ReadToEnd() -match ",\ (\+|-)0"
}
Dienstag, 7. September 2021
Loseless Merging Directories with Powershell
I needed a nice little function for merging directories without loosing documents in case of collisions of paths. Because i needed this for tidying up a hell of messed up homedrives i didnt care about any ACL etc.
function MoveCollisionFree([string]$srcdir,[string]$dstdir){
$srcdir = $srcdir.TrimEnd('\')
$dstdir = $dstdir.TrimEnd('\')
$srcRegEx=[regex]::Escape($srcdir)
[System.IO.Directory]::GetDirectories($srcdir).ForEach({
$DestPath=$_ -replace($srcRegEx,$dstdir)
if([System.IO.Directory]::Exists($DestPath)){
MoveCollisionFree -srcdir $_ -dstdir $DestPath
}else{[System.IO.Directory]::Move($_,$DestPath)}
})
[System.IO.DirectoryInfo]::new($srcdir).GetFiles().ForEach({
$DestFile=[System.IO.FileInfo]::new($($_.FullName -replace($srcRegEx,$dstdir)))
if($DestFile.Exists){
if($DestFile.LastWriteTime -ge $_.LastWriteTime){
$_.MoveTo("$($DestFile.Directory.FullName)\$($_.BaseName)_older_from_$($_.LastWriteTime.ToString('yyyy-MM-dd'))$($_.Extension)")
}else{
$NewFileName=$DestFile.FullName
$DestFile.MoveTo("$($DestFile.Directory.FullName)\$($_.BaseName)_older_from_$($DestFile.LastWriteTime.ToString('yyyy-MM-dd'))$($_.Extension)")
$_.MoveTo($NewFileName)
}
}else{$_.MoveTo($DestFile.FullName)}
})
Remove-Item $srcdir -Recurse -Force -Confirm:$false
}
Donnerstag, 22. Oktober 2020
How to extend NABox with Capacity information without having OCUM - my first python
Monitoring a Netapp is important, the "unofficial" Monitoring NAbox is installed like a slice of cake.
If you never heard about it - check it out here .. https://nabox.org/
But it does not collect the "capacity" information of his objects (volumes and aggregates) without the help of a OCUM (or Active IQ Unified Manager) .
Instead of installing another Appliance you can collect the needed data from Netapp Systems running Ontap 9.6+ by NAbox itself per REST-API.
First create a authentification certificate (which is usable for Powershell too, see my next post) :
Log into the NABox with SSH - (root:NetappGrafanaVA are the default login credentials).
mkdir /opt/myontapcol/
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /opt/myontapcol/ontapkey.key -out /opt/myontapcol/ontap.pem -subj "/C=DE/ST=WONDERLAND/L=EMERALDCITY/O=IT/CN=nabox"
BE AWARE OF "CN=nabox" this will be the user which we configure in the next step.
cat /opt/myontapcol/ontap.pem
connect with a 2nd SSH Shell to the Netapp and run this command, take the output from above into clipboard, you need to paste it.
security certificate install -type client-ca -vserver mycluster
it sometimes needs 3 "enter".
security ssl modify -client-enabled true -vserver mycluster
security login create -user-or-group-name nabox -application http -authentication-method cert -role readonly -vserver mycluster
your netapp answers now REST API requests,
You can test it on the nabox shell with
curl -s --key /opt/myontapcol/ontap.key --cert /opt/myontapcol/ontap.pem -k https://ontap-a.acme.corp/api/storage/aggregates
Now lets a script feed the NABox with data, except the python extension jsonpickle the nabox have all neccesary things allready installed.
pip install -U jsonpickle
I uploaded the script here .. naboxcapacol unzip the file open up the naboxcapacol.py file with notepad.
[UPDATE - Newer NA Boxes do not use the port 2004 and use 2013 for pickles counter - find the config file with ps -au|grep carbon and grep -A 5 ^.pick /etc/go-carbon/go-carbon.conf ]
Copy the script into the file and save it.
nano /opt/myontapcol/ontapcapacol.py
#make it executable
chmod +x /opt/myontapcol/ontapcapacol.py
#and let it run every 5min
crontab -e
*/5 * * * * /opt/myontapcol/ontapcapacol.py >> ~/cron.log 2>&1
# after 1h take a look for some of the data
https://nabox/graphite/?width=800&lineMode=connected&showTarget=mgtechhead.*.*.aggregates.*.volumes.*.used&height=600&target=mgtechhead.*.*.aggregates.*.volumes.*.used
You can now import my "simple" capacity dashboard ontapcapacol.json from the zip or just create your own. I created this for a customer who is not using so much qtrees.
The dashboards which came with harvest are not connecting volume and aggregate together, if you want to have the data here you have to alter the script in a way that it pumps the data to this paths.
netapp/capacity/$Group/$Cluster/svm/$SVM/vol/$Volume/afs_total
netapp/capacity/$Group/$Cluster/svm/$SVM/vol/$Volume/snapshot_reserve_total
netapp/capacity/$Group/$Cluster/svm/$SVM/vol/$Volume/snapshot_used_percent
netapp/capacity/$Group/$Cluster/svm/$SVM/vol/$Volume/afs_avail
netapp/capacity/$Group/$Cluster/svm/$SVM/vol/$Volume/afs_daily_growth_rate
netapp/capacity/$Group/$Cluster/svm/$SVM/vol/$Volume/overwrite_reserve_total
netapp/capacity/$Group/$Cluster/svm/$SVM/vol/$Volume/snapshot_reserve_avail
netapp/capacity/$Group/$Cluster/svm/$SVM/vol/$Volume/afs_used_percent
netapp/capacity/$Group/$Cluster/svm/$SVM/vol/$Volume/overwrite_reserve_used
netapp/capacity/$Group/$Cluster/svm/$SVM/vol/$Volume/overwrite_reserve_avail
netapp/capacity/$Group/$Cluster/svm/$SVM/vol/$Volume/actual_volume_size
netapp/capacity/$Group/$Cluster/svm/$SVM/vol/$Volume/afs_used_per_day
netapp/capacity/$Group/$Cluster/svm/$SVM/vol/$Volume/snapshot_reserve_used
netapp/capacity/$Group/$Cluster/svm/$SVM/vol/$Volume/total
netapp/capacity/$Group/$Cluster/svm/$SVM/vol/$Volume/afs_used
netapp/capacity/$Group/$Cluster/svm/$SVM/vol/$Volume/quota_committed_space
netapp/capacity/$Group/$Cluster/node/$Node/aggr/aggr_$Aggregate
netapp/capacity/$Group/$Cluster/node/$Node/aggr/aggr_$Aggregate/compression_space_savings
netapp/capacity/$Group/$Cluster/node/$Node/aggr/aggr_$Aggregate/dedupe_space_savings
netapp/capacity/$Group/$Cluster/node/$Node/aggr/aggr_$Aggregate/snapshot_reserve_total
netapp/capacity/$Group/$Cluster/node/$Node/aggr/aggr_$Aggregate/size_used
netapp/capacity/$Group/$Cluster/node/$Node/aggr/aggr_$Aggregate/size_used_per_day
netapp/capacity/$Group/$Cluster/node/$Node/aggr/aggr_$Aggregate/size_total
netapp/capacity/$Group/$Cluster/node/$Node/aggr/aggr_$Aggregate/size_available
netapp/capacity/$Group/$Cluster/node/$Node/aggr/aggr_$Aggregate/daily_growth_rate
netapp/capacity/$Group/$Cluster/node/$Node/aggr/aggr_$Aggregate/snapshot_reserve_avail
netapp/capacity/$Group/$Cluster/node/$Node/aggr/aggr_$Aggregate/compression_space_savings_percent
netapp/capacity/$Group/$Cluster/node/$Node/aggr/aggr_$Aggregate/dedupe_space_savings_percent
netapp/capacity/$Group/$Cluster/node/$Node/aggr/aggr_$Aggregate/space_total_committed
netapp/capacity/$Group/$Cluster/node/$Node/aggr/aggr_$Aggregate/size_used_percent
netapp/capacity/$Group/$Cluster/node/$Node/aggr/aggr_$Aggregate/snapshot_reserve_used
rm /opt/graphite/storage/whisper/mgtechhead/*/*/aggregates.[former_aggregate].volumes.[volume_name]/*
rmdir /opt/graphite/storage/whisper/mgtechhead/*/*/aggregates.[former_aggregate].volumes.[volume_name]
Freitag, 1. November 2019
Add a Netapp LUN as VM Datastore per Powershell
But according this KB from Netapp a LUN NAA is just a prefix + serial ascii to hex converted.
https://kb.netapp.com/app/answers/answer_view/a_id/1033595/~/how-to-match-a-luns-naa-number-to-its-serial-number-
This is "stupid" adding all LUNs as Datastore using the filename of the LUN as Suffix.
Get-NcLun|select Node,Vserver,Path,
@{N='NAA';E={"naa.600a0980$(-join ($_.SerialNumber.ToCharArray()|%{'{0:x}' -f $([byte][char]$_)}))"}}|%{
get-vmhost esxserver|New-Datastore -Vmfs -Name "VMFS_$($_.Path.Split('/')[2])" -Path $_.NAA
}
Maybe better declaring a function to make Code better readable ...
function Convert-ASCIItoHEX_STRING ([string]$inputstring){
return $(-join ($inputstring.ToCharArray()|%{'{0:x}' -f $([byte][char]$_)}))
}
Get-NcLun|select Node,Vserver,Path,
@{N='NAA';E={"naa.600a0980$(Convert-ASCIItoHEX_STRING $_.SerialNumber)"}}|%{
get-vmhost esxserver|New-Datastore -Vmfs -Name "VMFS_$($_.Path.Split('/')[2])" -Path $_.NAA
}
Mittwoch, 4. Juli 2018
How to recover access to a Brocade SAN switch after password dementia.
When the default password 'fibranne' for the root user did not help you, but you have still access to another switch in the fabric, this ist the way to push the password database from one switch you can access to the one you locked yourself out.
distribute -p PWD -d [#SwitchID]
#SwitchID is the decimal number in the first row in fabricshow output.
After this you can logon with the same password you know from switch A.
This is also a fine way to prevent to setup every password for admin, user, factory etc. by hand. Just setup one switch in the fabric properly and "push" the settings to each - or to configure fresh passwords FAST in a environment.
Mittwoch, 7. Februar 2018
Get Fibrechannel WWPNs and alot other HW Info from Fujitsu iRMC4 per Powershell
If you need even the fibrechannel stuff, you won't get it by REST,CIM or WSMAN - i deep-dived some days into all kind of documentations, wasted alot of time in enumerating and finally gave up, the only way seems to be get it from the WebGui - shame on Fujitsu - DELL do it better, see my next post.
This quick-n-dirty shit worked fine for me for PRIMERGY RX2540 M1, PRIMERGY RX2540 M2, PRIMERGY RX4770 M2 and PRIMERGY RX300 S8 - nice for report all MAC, WWPNs, Serials, Firmware etc ... if you use it let me know.
function Get-iRMC_HWInfo($irmcname,$irmcuser,$irmcpw)
{
$rsacred=New-Object System.Management.Automation.PsCredential($irmcuser,$(ConvertTo-SecureString -String $irmcpw -AsPlainText -force))
$body = @{APPLY = 99;P99='Login'}
$irmcwebreq=Invoke-WebRequest "http://$irmcname/login" -SessionVariable irmcsession -Credential $rsacred -Method Post -Body $body
$hwinfo=$($irmcwebreq.AllElements|?{$_.TagName -eq 'TR'}|?{$_.innerText -match '^System Type|^Serial|^System GUID|^System Name|^System\ O/S'}).innerText
$networkinventorylink=$($irmcwebreq.Links|?{$_.innerHTML -eq 'Network Inventory'}).href
$irmcwebreq2=Invoke-WebRequest "http://$irmcname/$networkinventorylink" -WebSession $irmcsession
$tabellen=$irmcwebreq2.ParsedHtml.getElementsByTagName("TABLE")
$nictabelle=$tabellen|?{$_.summary -match 'Ethernet'}
$fctabelle=$tabellen|?{$_.summary -match 'Fibre'}
$nicports=@()
foreach($datarow in $nictabelle.rows){
if($datarow.cells[0].tagName -eq "TD"){
$nicports+=@{Enabled=$datarow.cells[0].innerHTML -match 'ok.gif';
SlotID=$datarow.cells[1].innerText;
FunctionID=$datarow.cells[2].innerText;
PortID=$datarow.cells[3].innerText;
Firmware=$datarow.cells[5].innerText;
OpROM=$datarow.cells[6].innerText;
Interface=$datarow.cells[7].innerText;
VenID=$datarow.cells[9].innerText;
DevID=$datarow.cells[10].innerText;
SubVenID=$datarow.cells[11].innerText;
SubDevID=$datarow.cells[12].innerText;
MAC=$datarow.cells[14].innerText
}
}
}
$fcports=@()
foreach($datarow in $fctabelle.rows){
if($datarow.cells[0].tagName -eq "TD"){
$fcports+=@{Enabled=$datarow.cells[0].innerHTML -match 'ok.gif';
SlotID=$datarow.cells[1].innerText;
FunctionID=$datarow.cells[2].innerText;
PortID=$datarow.cells[3].innerText;
Firmware=$datarow.cells[5].innerText;
OpROM=$datarow.cells[6].innerText;
Interface=$datarow.cells[7].innerText;
VenID=$datarow.cells[9].innerText;
DevID=$datarow.cells[10].innerText;
SubVenID=$datarow.cells[11].innerText;
SubDevID=$datarow.cells[12].innerText;
WWNN=$datarow.cells[14].innerText;
WWPN=$datarow.cells[15].innerText}
}
}
return [pscustomobject]@{
SysType=$hwinfo[0].Split(':')[1];
SysSerial=$hwinfo[1].Split(':')[1];
SysGUID=$hwinfo[2].Split(':')[1];
SysName=$hwinfo[3].Split(':')[1];
SysOS=$hwinfo[4].Split(':')[1];
nicports=$nicports;
fcports=$fcports
}
}
Yeah thats all folks - ugly quick-n-dirty.