Quantcast
Channel: THWACK: All Content - Orion SDK
Viewing all 2677 articles
Browse latest View live

Problem adding a node

$
0
0

We get the following error when trying to edit nodes in NPM: There was an error retrieving data from SolarWinds Information Service.  We have stopped and restarted the service and rebooted the server.  My coworker also ran the configuration wizard to repair the services and then rebooted a second time, but we still have the same issue.


This issue started after installing WPM and the Engineer's toolkit.  If anyone has any insight, it would be most appreciated.  The error report is attached.


Node created from API never gets polled

$
0
0

When I create a node and add pollers through the API, the node never seems to get polled.  The node status never changes, I don't get get descriptive information like the node's name, vendor, etc. and it doesn't collect cpu, mem, volume, or interface statistics.  If I add the node through the Solarwinds GUI, everything works as it should.

 

I am using the Python SDK and my Orion Platform is 2015.1.2 (NPM 11.5.2).  Here is the relevant code I'm using trying to add a Cisco router.

 

swis = SwisClient(host, user, pass)

request =  swis.create("Orion.Nodes", IPAddress="192.168.1.1", EngineID=1, ObjectSubType="SNMP", SNMPVersion=2, Community="public")

 

At this point, the node has been added.  I can see it in Solarwinds "Manage Nodes" but it has no name or any other information associated with it because it hasn't been polled yet.

 

#In these queries, I'll use a hard coded NodeId just to demonstrate, assume the NodeId is 100

request = swis.create("Orion.Pollers", NetObject="N:100", netObjectType="N", netObjectID=100, PollerType="N.Status.ICMP.Native")

request = swis.create("Orion.Pollers", NetObject="N:100", netObjectType="N", netObjectID=100, PollerType="N.ResponseTime.ICMP.Native")

request = swis.create("Orion.Pollers", NetObject="N:100", netObjectType="N", netObjectID=100, PollerType="N.Details.SNMP.Generic")

request = swis.create("Orion.Pollers", NetObject="N:100", netObjectType="N", netObjectID=100, PollerType="N.Uptime.SNMP.Generic")

 

At this point, the pollers have been successfully added but nothing else has changed, I don't see status or additional node info, etc.  I have tried doing a "Poll Now" from the Solarwinds GUI and also invoking a "PollNow" through the API but I still get nothing.  The node just shows status "Unknown".  Now, if I do a "List Resources" from the Solarwinds GUI on the node, I can see all the routing topology, interfaces, etc. (and if I add these items, I can see these pollers are getting added in the DB.  Though if I add, say an interface now, I still can't get interface statistics because the node never appears to get polled).

 

Does anyone know what I might be doing wrong here?

Getting very odd results with SWQL query when put in a resource on a web page?!

$
0
0

Playing around with an idea to have a simple custom search by user-id from UDT data that I can put on a web page.  The query itself works great in SWQL studio, but when I put it on a webpage I get very odd results compared to what I get when I run it in SWQL studio...

 

The base query is fairly simple:

 

SELECT TOP 100 U2IPAC.User.AccountName, LogonDateTime, IPAddress, ('/Orion/UDT/UserDetails.aspx?NetObject=UU:' + ToString(UserID)) AS [_LinkFor_AccountName]

FROM Orion.UDT.UserToIPAddressCurrent U2IPAC

ORDER BY LogonDateTime DESC

 

I've also put in a "search" query that appears to work fine.  I've included it and how I set up the resource below.  This resource I added to my main UDT page.

 

When I run the query above in SWQL studio it works exactly as I would think it would.  Returns a number of userID's, IP Addresses, etc. etc for users that UDT says has recently logged in.   However, when I put it into the web page as shown below, the results are all 1 username.  I did notice that the "UserID" variable in the Orion.UDT.User happens to have the value of "1" for this user.   The dates and times and IP addresses that are returned on the webpage for that user ID are all valid, but its missing some.

 

By "missing some" I mean exactly that.   If I rewrite the query above to give me the logins of that specific username with a "WHERE U2IPAC.User.AccountName LIKE '%userid%'", I get a list of the last 100 logins of that user.   However, what is returned when I have it on the webpage is missing the first 2 from that list, then it has the next 2, then its missing the next 3, then it has the rest...   I've tried everything I can think of to try and figure out why its doing this.  Any suggestions? 

 

Is something happening to my query that I don't know about?   Is it somehow filtering or restricted on "UserID = 1"?  

 

## Search Query

SELECT TOP 1 U2IPAC.User.AccountName, LogonDateTime, IPAddress, ('/Orion/UDT/UserDetails.aspx?NetObject=UU:' + ToString(UserID)) AS [_LinkFor_AccountName]

FROM Orion.UDT.UserToIPAddressCurrent U2IPAC

WHERE (U2IPAC.User.AccountName LIKE '%${SEARCH_STRING}%')

ORDER BY LogonDateTime DESC

 

UDTUserSearch.jpg

Adding nodes with powershell using CRUD.AddWMINode

$
0
0

I have been working on automating monitoring for our new servers. So far the example script from the Orion SDK - C:\Program Files (x86)\SolarWinds\Orion SDK\Samples\PowerShell\CRUD.AddWMINode.ps1 has been very useful and I have been able to add nodes but I am running into troubles with adding the actual monitoring.

 

Such as - if you go to the node that is added you will not see the disk volumes in the Disk Utilization tab.Node Details - Disk Utilization.png

Also, when I pull info from the SWQL it is missing most of the WMI information that I would expect WMI to grab. So if I do the query below on a server I add manually it will work but not if ran by CRUD.AddWMINode.ps1.

 

SELECT  NodeDescription, Description, Vendor

FROM Orion.Nodes where Caption ="serverName"

 

Anyone attempt to do any of this? I am assuming others have ran into this before.

 

Thanks!!

 

Auto Assign Pollers

$
0
0

Is there a way to auto assign pollers to nodes through power shell?

I would like to create a scheduled task that runs to ensure that my nodes always have the proper pollers enabled on them.

 

-Ken

SWQL Math Rounding By Default?

$
0
0

Is there a way to stop the automatic rounding of the results when doing mathematical operations in SWQL?

 

For example, given the example below:

4.jpg

 

If I take a number of X and divide by a number of Y, the results are being rounded automatically.

 

What I would like to see would be this:

 

989 / 60 = 16.4666

 

Is this expected behavior for SWQL or am I missing something?

 

Thanks in advance.

Orion SWQL, Thwack! Now I got it

$
0
0

Orion SWQL or Solarwinds Query Language is a pseudo SQL type statements. If you know the basic structure of SQL, Select from join where order group by, you will easily pickup SWQL queries.

 

PURPOSE: This is an overly simplified guide for Keep the lights on SQL to Expert SQL users wanting to jump into Solarwinds Query Language as fast as possible.

 

Where is SWQL used?

  • Every Web Resource on the Web Console
  • Alerts
  • Reports
  • SDK/API scripting

 

Why should I use SWQL?

    Solarwinds has designed SWQL to be future proofed for users and development.

 

Note: A lot of this information exists in multiple places, I am just combining the different points to help provide a better picture to start creating queries easily.

 

Common SQL Constructs Supported

SWQL supports the following constructs from SQL:

    Note: If you know MS SQL, this will be exactly the same, except for the table names all start with Orion instead of dbo; however see the that * and Update or Deletes are not possible.

  • SELECT … FROM …
  • WHERE clauses
  • GROUP BY clauses and HAVING clauses
  • ORDER BY clauses
  • INNER JOIN
  • LEFT OUTER JOIN
  • RIGHT OUTER JOIN
  • UNION and UNION ALL
  • SELECT TOP n
  • SELECT DISTINCT
  • Subqueries in the SELECT clause
  • Subqueries in the FROM/JOIN clauses

  SWQL supports the following aggregate functions:

  • SUM
  • MAX
  • MIN
  • AVG
  • COUNT

  SWQL supports the following regular functions:

  • ISNULL
  • ABS

  Wildcards - 

The wildcard character in SWQL syntax is: %

Example: Node.Caption Like 'AX3%'

  Common SQL Constructs Not Supported

SWQL does not support the following common SQL constructs:

Note: You must use CRUD operations to create, read, update, or delete entities.

  • SELECT * FROM … (You must list the actual properties you want to select.)
  • UPDATE, INSERT, DELETE, etc. (You can only use SWQL to read data.)

 

Included in the Excel Spreadsheet

   

  • SWIS Examples.
    • Understand all of the different SWQL Functions. If you want to do more than just join a table, this included converting time, check values, and the more basic SQL type commands min,max, average.
  • SWIS Table Reference.
    • Want to know where to find the Node Data or the Applications, Storage or Virtual etc would be within SWQL? This covers the main key reference tables, the identifier id, and how to reference it up the chain from Component to Application to Node to Engine.
    • Some of this information came from Orion.NetObjectTypes. SWIS Parent and Column Details were added to see the relationship to the next table.
    • This section will be continuously updated. The main Core modules are currently mapped, and others are still being finalized.
  • Filtering by Status
    • Want to know what all of the 20+ Device and other Statuses and how convert from an ID to a human readable status? This tab is just for you. This can be referenced in Orion.StatusInfo

InterfaceDowntime.SWQL


Solarwinds API - Identify Virtual or Physical Server

$
0
0

Is there a field accessible to the API (via SWQL) that can tell me whether a node is a virtual (eg Hyper-v or VMWare) or a physical server?

 

I am currently relying on the node name with a separately maintained server inventory to do this and it is just not reliable enough.

 

Thank you.

 

Mike

Where are the details of an Application stored in the SQL database?

$
0
0

I Need to find what credentials each application component is using, when the component is a SQL User Experience Monitor, and what the setting for "Use windows authentication first then sql authentication" is set to.

We have a number of issues where the poller is generating errors on our SQL servers flooding the logs and making it hard to troubleshoot other issues on the SQL server.

If i could find all applications that have incorrect settings i could target my fix across the hundreds of Application Monitors.

 

Thanks

PIVOT function with SWQL?

$
0
0

Can anyone comment on PIVOT functionality with SWQL?  Perhaps an example of where it's been used previously?

 

I have a web resource for the dashboard view using SWQL perfectly, but I would love to see the row data flipped around into column for easier consumption.

 

I did exactly what I wanted to do on a web report with a custom SQL query --- and of course I can do a custom SQL query report through report writer and display the report on the view.  Works great for me as the admin, but there are known issues with custom SQL reporting and account limitations (it gets broken).

 

The answer seems simple, to write the view Custom Query resource in SWQL with a pivot table, but I can't for the life of me seem to get it functional.

 

Anyone run into the same issues previously?

 

- Matt

Verbs and their parameters for IPAM.IPNode in addition to 'UpdateManyStatus'??

$
0
0

PREFACE:

  1. I'll be referring to the blog: How to use the IPAM API and get "Free IP Address" specifically a post by mtokarz on June 12, 2014 2:35PM in response to jgovednik
  2. I am also aware of and have voted for the feature request: Add SWIS features to IPAM
  3. I have also referred to this question post: Re: Full documentation of Orion SDK verbs? to see if any verbs exist for IPAM.IPNode, but none that I can find.

 

Following the post mentioned in #1, I am able to successfully find the next free ip address and update the status of an IP address in Solarwinds using Powershell:

 

Pre-reqs: Download the Orion SDK: solarwinds/OrionSDK · GitHub

 

Getting a Free IP Address:

# START Connect to SWIS

Add-PSSnapin SwisSnapin

$hostname = "mysolarwinds"

$username = "myuser"

$password = ConvertTo-SecureString -String "mypassword" -asplaintext -force

$creds = New-Object -TypeName System.Management.Automation.PSCredential -Argumentlist $username, $password

$swis = Connect-Swis -host $hostname -Credential $creds

# END Connect to SWIS


Function SWOIPAM-GetFreeIpAddress($subnetAddress)

{

  $ipaddress = Get-SwisData $swis 'SELECT TOP 1 I.DisplayName FROM IPAM.IPNode I WHERE Status=2 AND I.Subnet.Address=@subnetAddress AND I.DnsBackward IS NULL' @{subnetAddress = $subnetAddress}

  return $ipaddress

}


$subnetProvision = 'X.X.X.X'

SWOIPAM-GetFreeIpAddress($subnetProvision)

 

Where:

  • $subnetProvision = Desired subnet to get next available IP Address from

 

Updating the Free IP Address' status from 'Available' to 'Used':

$postParams = @{__EVENTTARGET='ctl00$BodyContent$ctl05';__EVENTARGUMENT='';'ctl00$BodyContent$Username'='admin';'ctl00$BodyContent$Password'='password'}

Invoke-WebRequest -Uri http://mysolarwinds:8787/Orion/Login.aspx?autologin=no -Method POST -SessionVariable s -Body $postParams

$postParams =  @{'entity'='IPAM.IPNode';'verb'='UpdateManyStatus';'ObjectId'='129';'ipstatus'='1';'ids'='4'}

Invoke-WebRequest -Uri http://mysolarwinds:8787/Orion/IPAM/ExtCmdProvider.ashx -Method POST -WebSession $s -Body $postParams

 

Where:

  • ObjectID : type = number => SubnetId from IPAM.IPNode
    • One can obtain the SubnetId with the query: SELECT SubnetId, Address, FriendlyName, VLAN FROM IPAM.Subnet
  • ipstatus : type = number => where 1 (Used), 2 (Available), 4 (Reserved)
  • ids : type = number => the 4th octet of the IP Address you want to update in the specified subnet

 

THE QUESTION:

If the verb 'UpdateManyStatus' (with the params of ObjectID, ipstatus and ids) exist for IPAM.IPNode to update a particular IP address' status,

(@{'entity'='IPAM.IPNode';'verb'='UpdateManyStatus';'ObjectId'='129';'ipstatus'='1';'ids'='4'}),

are there any other verbs or documentation of verbs with necessary parameters for IPAM.IPNode that will update the DnsBackward (hostname), Comments and SkipScan fields for a particular IP Address??


If I can find out the verbs and their necessary parameters, then I would be able to update via the same method used for updating an IP Address' status in Powershell.

 

Thank you

Noob to SDK

$
0
0

Hello all!

 

So what I need is a way to pull availability status for last 12 months every 30 days for systems with "Enterprise Servers" in the custom properties department field, into an Excel spreadsheet and create a pretty graph for the executives. Oh, and this has to go to SharePoint. I was hoping I could pull straight from Excel, but it looks like I cannot?

Anyway, I am hoping someone could give me a jump start with how to get this going.

 

Thanks so much!!

Chad

Perl SDK - Start Discovery - PluginConfigurations

$
0
0

How can I find what is the least amount of XML to pass to PluginConfigurations?

 

Here is what I pass: and I get a bad_request error. Basically what I need to know is the bare min, I want to pass a IP address to StartDiscovery and then point it to an already existing Discovery Profile, do not want to create one.

 

  my $discoveryProfileXml = <<"END";

<CorePluginConfigurationContext xmlns:i='http://www.w3.org/2001/XMLSchema-instance' xmlns='http://schemas.solarwinds.com/2012/Orion/Core'>

         <BulkList>

         <string>$ipAddress</string>

         </BulkList>

        <IpRanges />

        <Subnets />

        <Credentials />

        <WmiRetriesCount>0</WmiRetriesCount>

        <WmiRetryIntervalMiliseconds>0</WmiRetryIntervalMiliseconds>

    </CorePluginConfigurationContext>

END

 

*****************************************

my @pluginConfigurationItems = ({ PluginConfigurationItem => "$discoveryProfileXml" });

 

            my %startDiscoveryConfiguration = (

                    Name => 'Production Profile 1' ,

                    EngineID => $engineID,

                    JobTimeoutSeconds => 3600,

                    SearchTimeoutMiliseconds => 2000,

                    SnmpTimeoutMiliseconds => 3000,

                SnmpRetries => 1,

                RepeatIntervalMiliseconds => 1800,

                SnmpPort => 161,

                HopCount => 0,

                PreferredSnmpVersion => 'SNMP2c',

                DisableIcmp => 0,

                AllowDuplicateNodes => 1,

                IsAutoImport => 1,

                IsHidden => 0,

                PluginConfigurations => \@pluginConfigurationItems

            );

 

            my @verbArguments = (\%startDiscoveryConfiguration);

            my $SWServer = $self->{engineconfig}->{OrionConfig}->{"$Region"};

            my $swhostname = $SWServer->{OrionServer}; # fill in a hostname

            my $swport = $SWServer->{JSONPort};

            my $swprotocol = $SWServer->{Protocol};

            my $SWCredentials = $self->get_credentials($SWServer->{CredentialSetName});

            my $username = $SWCredentials->{username};

            my $password = $self->decrypt_password($SWCredentials->{password});

 

            my $uri = "https://$swhostname:$swport/SolarWinds/InformationService/v3/Json/Invoke/Orion.Discovery/StartDiscovery";

            my $rest = REST::Client->new();

            $rest->getUseragent()->proxy(['https']);

            $rest->getUseragent()->ssl_opts(verify_hostname => 0);

            my $headers = {

                Authorization => 'Basic ' . MIME::Base64::encode_base64($username . ':' . $password),

                'Content-Type' => 'application/json'

            };

            my $json = JSON->new->allow_nonref->utf8;

             my $json_text = $json->space_after->encode(\@verbArguments);

 

            #print "$json_text\n";

            my $response = $rest->POST($uri, $json_text, $headers);

            print Dumper $response;

IPAM - Making the subnet you query for a variable

$
0
0

I am trying to use the information from this post How to use the IPAM API and get "Free IP Address" to build a way to automatically get the next available ip, the gateway, and the subnet mask in a script.  I want this to prompt the user for which subnet they want to use.  I'm also doing this via invoke-command.  Below is an example line from my powershell script:

 

$AvailableIPs = Invoke-Command -ScriptBlock {Get-SwisData $swis 'SELECT DISTINCT TOP 1 I.DisplayName FROM IPAM.IPNode I WHERE Status=2 AND I.Subnet.DisplayName = ''DEV'''} -Session $session

 

I want to change DEV to be $subnet but I cannot just drop in $subnet and have it work (the variable does exist on the remote session).

 

Any help is much appreciated.


Alert clearing via Powershell

$
0
0

I'm trying to clear the triggered instance of alerts using a powershell script using verbs available, but not sure even how to start.... I have the verbs but not sure what all I can do with that verbs or how to query the variables from the alert to get the correct variable there.

 

Can someone help me out here? I know that I have the verb 'Orion.AlertActive' available but not sure on how to use it properly. Is there a verb wise documentation available?

Help with Powershell Script to Bulk Change Polling Method from SNMP/ICMP to WMI

$
0
0

Yes, I know I can bulk edit Node properties in the Mange Nodes section, but since it tests the credentials in the background when you hit submit, I often get website timeouts when trying to do more than 50 nodes at a time.  Its really slow going when you have hundreds of Windows nodes to do, plus you still have to run a discovery afterwards to add in the new polling packages.  I really just wish you could turn off the background test of the credential.  I'd rather just change them all to the new credential and evaluate later which ones don't work with that credential and fix them as needed.  Or, even better, it'd be cool if in the Network Discovery you could choose an option to change polling methods if a node is already in the database but has a different polling method than what you prefer.  Maybe that'd be a good feature request, but I digress.


Looking at the sample code for adding a WMI node here: https://github.com/solarwinds/OrionSDK/blob/master/Samples/PowerShell/CRUD.AddWMINode.ps1 I see all the things I would need to set, and I know I can just use the Set-SwisObject commandlet to modify the ObjectSubType to WMI, but I'm not sure if updating the ObjectSubType field will kick off some of the automated things that happen when you do it in the GUI, like automatically deleting the SNMP volumes (I know the SNMP interfaces don't automatically delete, but I found another script snippet by LadaVarga here that shows me how to do that).  I also don't know if changing it via the SDK will have it automatically delete the historical CPU/Memory data as well as remove the SNMP pollers.


Does anyone know whether its possible to just change the ObjectSubType, delete the SNMP interfaces, and add in the new WMI pollers, or is there something more to this that I'm not seeing or maybe even a better way to do it that I'm overlooking?  I couldn't find any similar posts on Thwack regarding changing nodes through the SDK (there are TONS of posts regarding adding nodes through the SDK though...).


Thanks!

Upgraded server. Python API broken, PowerShell working

$
0
0

Our server admin upgraded Solarwinds from a physical server to virtual server.  He said he did it by the book.  We have alot of python scripts that pull from the solarwinds API that are now broken.  When I download the SDK and try to run the example python script from the solarwinds server, I get the following:

 

PS C:\> python .\SwisClient.py

IP address of NPM Server:

Username:

Password:

Invoke Test:

Traceback (most recent call last):

  File ".\SwisClient.py", line 72, in <module>

    main()

  File ".\SwisClient.py", line 68, in main

    samplecode(npm_server,username,password)

  File ".\SwisClient.py", line 43, in samplecode

    aliases = swis.invoke("Metadata.Entity", "GetAliases", "SELECT B.Caption FROM Orion.Nodes B")

  File ".\SwisClient.py", line 18, in invoke

    return self._req("POST", "Invoke/%s/%s" % (entity, verb), args).json()

  File ".\SwisClient.py", line 37, in _req

    headers={'Content-Type': 'application/json'})

  File "C:\Anaconda\lib\site-packages\requests\api.py", line 50, in request

    response = session.request(method=method, url=url, **kwargs)

  File "C:\Anaconda\lib\site-packages\requests\sessions.py", line 468, in request

    resp = self.send(prep, **send_kwargs)

  File "C:\Anaconda\lib\site-packages\requests\sessions.py", line 576, in send

    r = adapter.send(request, **kwargs)

  File "C:\Anaconda\lib\site-packages\requests\adapters.py", line 412, in send

    raise ConnectionError(err, request=request)

requests.exceptions.ConnectionError: ('Connection aborted.', error(10054, 'An existing connection was forcibly closed by

the remote host'))

 

 

I am attaching the script that I am running.  The only change was to enter a valid node ID on line 47 as requested by the script (changed to "NodeID=6"). 

 

I worked with Solarwinds for a bit before they told me they don't support API.  I think this is more than a mere programing issue and something wrong with the internals of Solarwinds. 

 

The odd thing is that I can create a basic powershell script and it runs fine.  Here is the powershell code I am running:

 

Add-PSSnapinswissnapin

 

$swis=Connect-Swis

 

[array]$Nodes=Get-SwisData$swis'SELECT NodeID, Caption, MachineType FROM Orion.Nodes'

 

 

foreach ($Nodein$Nodes)

{

       if (($Node.Caption) -like"su*" ) {

Write-Host$Node.NodeID $Node.Caption $Node.MachineType

       }

      

}




Working with Solarwinds for a short bit, we have already run the configuration wizard to have it fix any services or database issues.  I have restarted all services and still get the same error.  I have run the Solarwinds Diagnostics and searched for this error in the logs.  I see the same error code and response in the Core.BusinessLayer logs, but that doesn't tell me much. 


Here are the versions we are running:  Orion Platform 2015.1.2, VNQM 4.2.2, IPAM 4.3, SAM 6.2.2, DPA 10.0.0, NCM 7.4, IVIM 2.1.0, QoE 2.0, NPM 11.5.2


Any help is much appreciated.

ClearAlert Verb in Orion.AlertActive Entity

$
0
0

I'm trying to invoke the Orion.AlertActive entity's Clear Alert Verb, but I'm not sure what arguments to pass.

 

Is there a document which I can refer to check which arguments to pass or can somebody tell me which arguments to pass?

I tried the following invoke and in place of xxxx I passed the alert object ID:

Invoke-SwisVerb $swis Orion.AlertStatus ClearAlert @(xxxx)

 

But I get the following error:

Invoke-SwisVerb : Verb Orion.AlertStatus.ClearAlert: Not found

At line:7 char:1

+ Invoke-SwisVerb $swis Orion.AlertStatus ClearAlert @("33105")

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : InvalidOperation: (:) [Invoke-SwisVerb], FaultException`1

    + FullyQualifiedErrorId : SwisError,SwisPowerShell.InvokeSwisVerb

 

It says verb not found but its there in metadata so I'm pretty sure I'm  passing the wrong arguments. So, is there a document which I can refer to check which arguments to pass or can somebody tell me which arguments to pass?

Data returned from DiscoverInterfacesOnNode question

$
0
0

On a subject related to https://thwack.solarwinds.com/message/257013#257013,

 

When I get returned data from Invoking the DiscoverInterfacesOnNode ( Orion.NPM.Interfaces/DiscoverInterfacesOnNode) verb, I have of course noticed the "Result" field, and recently noticed that one particular call returned a 1 as the Result value vs. the 0 I normally/typically see. Is there any documentation as to what these Result value(s) mean?

 

{
    "DiscoveredInterfaces": null,
    "Result": 1
}

 

Or can you / someone tell me?

 


Thanks,
Scott F.

Viewing all 2677 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>