Rebuild PerfMon Counters

Sometimes your PerfMon counters will become corrupted. The way to fix this is to reset their definitions back to default by having the system rebuild them. Use the following command to do so.

lodctr /R

OPSView and adding hosts through REST API

This is something I’ve decided to share after a couple of days tinkering with the REST API and wanting to automate adding of hosts.

My environment:

99.99% Windows based

My need:

Automate adding of new hosts as they are deployed on the network.

My plan:

Leverage PowerShell

Leverage WSUS

Leverage the OPSView REST API

My Skills:

I am in no way share or form a developer or someone who could tell you what JSON stands for or how it works. Just a plain old SYS Admin.

Prerequisites:

1. Version of OPSView that has the REST API. I’m using the latest Community Edition.

2. An OPSView contact/login that ha the correct permissions/roles to add new hosts and read data.

3. An OPSView top level host group you will use to host your auto added hosts.

4. A host to clone for your template that new hosts will look like.

5. You should already have WSUS

6. You should know how/what WSUS is.

7. You should know how to create custom WSUS packages and deploy them via WSUS. (Custom Update Publisher)

8. If not read up on them and decide if WSUS is something you want to be using in your org going forward and think about implementing it.

9. It’s simply my environment and thus it is what I want to be working with.

The Details:

So in essence what I want to do is a simple process every time a new Windows Server box is brought up on my domain.

1. Install OPSView agent.

2. Deploy custom .ini config file for agent and restart agent.

3. Add host to monitoring server into a predefined group so I know that this is a new server that needs further setup.

Steps 1 and 2 are easily accomplished with custom WSUS packages and rules to make sure the agent is only deployed when it needs to be and I’m not going to go into that at all. It’s pretty straight forward. If you’ve never done it before you should have the hang of Custom Packages within a day of playing around with it (on your test network of course). Those skills can then be used in the future for other Custom Packages.

This is about accessing the REST API through PowerShell which was something new to me.

I ended up with 2 different raw scripts. Many refinements could be made and I’m sure I’ll tweak them but as of right now these work for what I wanted them to do.

Script 1.

opsview-get-host-config.ps1

This script accesses the API to get the config of a host on the server. I use the output of this script to base my template for adding new hosts. I got the return data and then stripped out information like host ID (can’t duplicate that) and then I insert my own host name and IP when creating the new host later on. I inserted that data into the 2nd script.

Why use that as a template instead of building a host string completely dynamically in the script. This way is easier for me. Of course you can make the script more complex and thus more flexible but again this is a starting point for me (and maybe you) not a universal solution.

Script 2.

opsview-add-host.ps1

This script adds a host with the current IPv4 address and machine name it is running on to the placeholder group. Yes it’s that simple. But it works.

So a simple and useful solution for me. It could be more elegant but it does what I need it to. And once you have your prereqs set up you’d only be using script 2 for adding new hosts and since this can be automated via WSUS hosts will add themselves as your regulated patch cycles happen..

The 2 scripts are attached below.

Thanks for reading and for any comments.


##### opsview-get-host-config.ps1
##### Get OPSview Host Config


$urlauth = "http://opsview.host.org/rest/login"

#The host we will use to pull our data from
$urlconfigget = "http://opsview.host.org/rest/config/host/132"

$user="host-add-contact"
$pass="password"


$creds = '{"username":"' + $user + '","password":"' + $pass + '"}'

#Write-Host $creds



###Generate Auth Token

$bytes1 = [System.Text.Encoding]::ASCII.GetBytes($creds)
$web1 = [System.Net.WebRequest]::Create($urlauth)
$web1.Method = "POST"
$web1.ContentLength = $bytes1.Length
$web1.ContentType = "application/json"
$stream1 = $web1.GetRequestStream()
$stream1.Write($bytes1,0,$bytes1.Length)
$stream1.Close()


$reader1 = New-Object System.IO.Streamreader -ArgumentList $web1.GetResponse().GetResponseStream()
$token1 = $reader1.ReadToEnd()
$reader1.Close()

#Parse Token for follwoing sessions
#Write-Host $token1
$token1=$token1.Replace("{`"token`":`"", "")
$token1=$token1.Replace("`"}", "")
#Write-Host $token1


$web2 = [System.Net.WebRequest]::Create($urlconfigget)
$web2.Method = "GET"
$web2.ContentType = "application/json"
$web2.Headers.Add("X-Opsview-Username","$user")
$web2.Headers.Add("X-Opsview-Token",$token1);

$response2 = $web2.getResponse()

$reader2 = New-Object System.IO.Streamreader -ArgumentList $web2.GetResponse().GetResponseStream()
$result2 = $reader2.ReadToEnd()
Write-Host $result2
$reader2.Close()


##### opsview-add-host.ps1
##### Get OPSview Host Config


$urlauth = "http://opsview.host.org/rest/login"
$urlconfig = "http://opsview.host.org/rest/config/host"

$user="host-add-contact"
$pass="password"

$creds = '{"username":"' + $user + '","password":"' + $pass + '"}'

#Write-Host $creds



###Generate Auth Token

$bytes1 = [System.Text.Encoding]::ASCII.GetBytes($creds)
$web1 = [System.Net.WebRequest]::Create($urlauth)
$web1.Method = "POST"
$web1.ContentLength = $bytes1.Length
$web1.ContentType = "application/json"
$stream1 = $web1.GetRequestStream()
$stream1.Write($bytes1,0,$bytes1.Length)
$stream1.Close()


$reader1 = New-Object System.IO.Streamreader -ArgumentList $web1.GetResponse().GetResponseStream()
$token1 = $reader1.ReadToEnd()
$reader1.Close()


#Parse Token for follwoing sessions
$token1=$token1.Replace("{`"token`":`"", "")
$token1=$token1.Replace("`"}", "")



$hostname = $env:COMPUTERNAME
$hostip = ((ipconfig | findstr [0-9].\.)[0]).Split()[-1]


### The host data I use here is tailored to my OPSView setup. USe the other script and this line as a guide to building your own
$hostdata = '{"object":{"hosttemplates":[{"ref":"/rest/config/hosttemplate/42","name":"Connectivity - USA"},{"ref":"/rest/config/hosttemplate/36","name":"Server - All Windows Server Base Checks"}],"snmpv3_privprotocol":null,"flap_detection_enabled":"1","keywords":[],"check_period":{"ref":"/rest/config/timeperiod/1","name":"24x7"},"hostattributes":[],"notification_period":{"ref":"/rest/config/timeperiod/1","name":"24x7"},"notification_options":"d,r,f","tidy_ifdescr_level":"0","name":"' + $hostname +'","rancid_vendor":null,"snmp_community":"","hostgroup":{"ref":"/rest/config/hostgroup/42","name":"ZZZ-New Hosts"},"enable_snmp":"0","monitored_by":{"ref":"/rest/config/monitoringserver/1","name":"Master Monitoring Server"},"alias":"","parents":[],"uncommitted":"1","icon":{"name":"SYMBOL - Server","path":"/images/logos/server_small.png"},"retry_check_interval":"3","ip":"' + $hostip + '","use_mrtg":"0","snmp_max_msg_size":"0","servicechecks":[],"use_rancid":"0","snmp_version":"2c","snmpv3_authpassword":"","nmis_node_type":"router","use_nmis":"0","rancid_connection_type":"ssh","snmpv3_authprotocol":null,"rancid_username":null,"check_command":{"ref":"/rest/config/hostcheckcommand/15","name":"ping"},"rancid_password":null,"check_attempts":"5","check_interval":"15","notification_interval":"0","snmp_port":"161","snmpv3_username":"","snmpv3_privpassword":"","other_addresses":""}}'



$bytes2 = [System.Text.Encoding]::ASCII.GetBytes($hostdata)
$web2 = [System.Net.WebRequest]::Create($urlconfig)
$web2.Method = "POST"
$web2.ContentLength = $bytes2.Length
$web2.ContentType = "application/json"
$web2.Headers.Add("X-Opsview-Username","$user")
$web2.Headers.Add("X-Opsview-Token",$token1);
$stream2 = $web2.GetRequestStream()
$stream2.Write($bytes2,0,$bytes2.Length)
$stream2.Close()

$reader2 = New-Object System.IO.Streamreader -ArgumentList $web2.GetResponse().GetResponseStream()
$output2 = $reader2.ReadToEnd()
$reader2.Close()

Write-Host $output2







Using Robocopy

RoboCopy is a command line line tool similar to rsync that is present in Server 2008, ​2008R2, and Windows 7.



There are many switches and capabilities such as copying files with original timestamps, ntfs rights, differential copies, etc etc.



The common one I use when migrating shares from one location to another is for example. This retries, carries over NTFS premissions and does a differnetical copy so you can re run it later to sync the directories.



ROBOCOPY "\\server1\users$" "\\server2\users$" *.* /E /SEC /ZB /R:100000 /W:1 /TBD /XO






See here for more commands about RoboCopy.



http://ss64.com/nt/robocopy.html

Delete user from Sharepoint 2010 Cache

Sometimes you need to delete a user completely due to SharePoint caching data incorrectly and refusing to update. In cases like the is the last resort is to delete the user data for that user and run another user sync to force Share Point into re-syncing that users information.

Warning: This will remove all unique profile information that user has entered.

To delete all data for a user from SharePoint 2010:



​1. Go to Central Admin and delete profile if user has one in the User Profile Management section.

2. Go to http(s)://sitecollection.com/_catalogs/users find the offending user, click on it, and use the delete button.



This should also work for SharePoint 2007

Manually Remove Exchange 2003 Storage Groups/Public Folder

If you've ever done an Exchange 2003 installation you know jut how painful they can be due to Exchange not wanting to remove itself due to safety checks that must be passed first.

These checks are a good thing but sometimes things get screwed up and the checks will never pass so you manually must remove a Storage Group or Public Folders DB but the Exchange Management Console stops you due to these safety checks.

So here is the how to.


WARNING:
ADSI Edit is a very powerful tool and you can easily break all of your Exchange org if you do something stupid. Use this as a last resort to remove a Store or DB after taking care of things like replicas.


Drill down to where you need to to delete the offending Store/DB and then restart the MS Store service on the server. If doing this on a remote DC the changes might take several minutes to replicate.

Once again ADSI Edit can easily destroy your entire AD organization so please be careful and only do this if absolutely necessary.
Configuration
+ CN=Configuration
+ CN=Services
+ CN=Microsoft Exchange
+ CN=YOUR ORGANISATION
+ CN=Administrative Groups
+ CN=First Administrative Group
+ CN=Servers
+ CN=SERVER NAME
+ CN=InformationStore

Refresh Active Directory group memeberships WITHOUT rebooting

A common issue when updating group memberships in AD is that they do not seem to take effect right away. This is due to Kerberos tokens being used that were created before the group memberships were changed.

The standard way to fix this is to start a new session. With a user object this means a log off and log on; inelegant but not terrible. For a computer object there is no log on and off, the authentication happens when the computer authenticates against a domain controller and thus the fix is to restart the machine. This is not an option for production servers where uptime is critical.


So you've just deployed some new group policies based on some new group memberships you've created and you need those settings applied to production servers but a reboot is out of the question. The policy is not applying.

The solution without a reboot? Deleting existing tokens and forcing them to be recreated.


Open a cmd prompt and run the following two commands:

klist purge

klist tgt

This will delete the tokens and then recreate new ones. Your policy will now apply as expected and there was no reboot necessary!

Disable sleep while downloading or uploading through PowerShell.

I have a machine at home that acts as a server hosting several apps and services. It is used a couple of hours a day total usually in succession to stream media, download files and so on.

The server is set to go to sleep and suspend to RAM to save power after 5 minutes of idling. It works great as all of the apps so far have been usage aware and prevent sleep while they are being used.

Recently I installed an application that downloaded and uploaded files that was not usage aware. This meant that in the middle of a download or upload if everything else was idle but that app the server would go to sleep.

The logical solution, in my mind, was to get an application that disabled sleep while network card traffic was above a certain threshold.



I spent an hour googling around and found nothing that suited my needs even remotely, and once I got over my disappointment I decided to create a solution using my novice PowerShell skills.


The script that sets sleep based on network ability is below. It's not as good as it could be but it works for me.

You will need Powershell 2.0 to run it.

Checks NIC activity, if it is less than 50KB/s, sets sleep timeout to 5 min, if more than 50KB/s disables sleep. Checks again 140 seconds later. That's it.


Do a get-counter in powershell and replace my NIC "counter" name with yours or it wont work.

##############################
##### nicsleep.ps1
##############################

function checknicactivity

{

$counter = 1

do
{
$niccounter = Get-Counter -counter "\network interface(realtek rtl8102e_rtl8103e family pci-e fast ethernet nic [ndis 6.20])\bytes total/sec"
$c = $niccounter.countersamples | where {$_.path -match "ndis 6.20"}
$d = $c.cookedvalue

if ($d -gt 51200){powercfg -change -standby-timeout-ac 0}
elseif ($d -lt 51200){powercfg -change -standby-timeout-ac 5}

Start-Sleep -s 140

}
while ($counter -gt 0)


}

checknicactivity


#####################






If you want to run this with no Powershell visible shell one way is to call it through vbscript. This assumes both files are located in C:\Scripts






''''''''''''''''''''''''''''''

Dim objShell
Set objShell=CreateObject("WScript.Shell")

'enter the PowerShell expression
'you need to use short filenames and paths
strExpression="C:\Scripts\nicsleep.ps1"

strCMD="powershell -nologo " & strExpression

'Uncomment next line for debugging
'WScript.Echo strCMD

'use 0 to hide window
objShell.Run strCMD,0


'''''''''''''''''''''''''''''''''''''''''''


One thing I struggled with was deciding if I wanted to run the script one off as a scheduled task every x seconds or just run it once and have the loop keep it open forever (it autostarts with windows for me).

To me it seemed more logical to keep the PS process open rather than keep launching a new one every 2 minutes.


It's quick and dirty and it works for me, there is probably better ways to do it. If you have a suggestion let me know.