44 Replies Latest reply on Jan 27, 2014 10:45 AM by scottfraley

    How to create array of arguments for Unmanage/Remanage? (C#)

    fourmica

      I am trying to write a method for Unmanaging and Remanaging nodes in Orion, in C#. Using the CSClient example, I've been able to write a query Orion for a NodeID based on sysname. However, when I want to Invoke("Orion.Nodes", "Unmanage", args) I don't know how to correctly create the ArrayOfXMLElement that the method seems to want. I tried modifying the code used for the alert example, but it gives me "FaultException`1" when I try it. I created the data object to store the arguments based on the column names in the Nodes table. I am using VS2010, .net 4.0, Orion 2012.2.0, and SDK 1.6. I am very new at this so please be gentle :-) The portion of the code that gets the NodeID based on sysname works fine.

       

      This is what my code looks like:

       

      using System;

      using System.Net;

      using System.Runtime.Serialization;

      using System.Xml;

      using System.Linq;

      using System.Xml.Linq;

      using System.Xml.XPath;

      using CSClient.SWIS;

       

      namespace CSClient

      {

          class Program

          {

              static void Main()

              {

                  const string hostname = "myorionserver";

                  const string username = @"myuser";

                  const string password = "mypassword";

                 

                  ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;

       

                  var client = new InformationServiceClient("BasicHttpBinding_InformationService", string.Format("https://{0}:17778/SolarWinds/InformationService/v3/OrionBasic", hostname));

                  client.ClientCredentials.UserName.UserName = username;

                  client.ClientCredentials.UserName.Password = password;

                  client.Open();

                  var nodeIDInfo = client.QueryXml("SELECT TOP 1 NodeID from Orion.Nodes WHERE sysname like 'targetserver' RETURN XML AUTO", null);

                  nodeIDInfo.Save(@"c:\temp\orionoutput.xml");

                  var nodeID = nodeIDInfo.XPathSelectElement("//*[local-name()='NodeID']").Value;

                  Console.WriteLine("Node ID is " + nodeID.ToString());

       

                  string unmanageFrom = DateTime.Now.ToString();

                  string unmanageUntil = DateTime.Now.AddHours(6).ToString();

       

                  var unmanageInfo = new UnmanageInfo

                  {

                      NodeID = nodeID,

                      UnManageFrom = unmanageFrom,

                      UnManageUntil = unmanageUntil

                  };

                  var unmanaged = new[] { unmanageInfo };

       

                  var dcs = new DataContractSerializer(unmanaged.GetType());

                  var doc = new XmlDocument();

                  using (var writer = doc.CreateNavigator().AppendChild())

                  {

                      dcs.WriteObject(writer, unmanaged);

                  }

       

                  var arguments = new ArrayOfXmlElement { XDocument.Load(new XmlNodeReader(doc)).Root };

                  var result2 = client.Invoke("Orion.Nodes", "Unmanage", arguments);

                  Console.Write(result2);

                  Console.Read();

              }

       

              [DataContract(Name = "UnmanageInfo", Namespace = "http://schemas.solarwinds.com/2008/Orion")]

              public class UnmanageInfo

              {

                  [DataMember(Order = 1)]

                  public string NodeID;

       

                  [DataMember(Order = 2)]

                  public string UnManageFrom;

       

                  [DataMember(Order = 3)]

                  public string UnManageUntil;

       

              }

       

          }

      }

        • Re: How to create array of arguments for Unmanage/Remanage? (C#)
          tdanner

          Orion.AlertStatus.Acknowledge takes one argument that is an array of AlertInfo structures. Orion.Nodes.Unmanage takes four arguments: a net object id (basically "N:" and then the node id value), the DateTime to start the unmanage period, the DateTime to end the unmanage period, and a boolean for "is relative" (if you pass true for this last one, it will ignore the date portion of the third argument and use the time portion as the duration of the unmanage period; I recommend you compute the end of the unmanage period yourself and just pass false for the fourth argument). Here's a program that worked for me:

           

          using System;

          using System.Linq;

          using System.Net;

          using System.Runtime.Serialization;

          using System.Xml;

          using System.Xml.Linq;

          using System.Xml.XPath;

          using CSClient.SWIS;

           

           

          namespace CSClient

          {

              class Program

              {

                  static void Main()

                  {

                      const string hostname = "localhost";

                      const string username = "admin";

                      const string password = "";

                     

                      ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true;

           

           

                      var client = new InformationServiceClient("BasicHttpBinding_InformationService",

                                                                string.Format("https://{0}:17778/SolarWinds/InformationService/v3/OrionBasic", hostname));

                      client.ClientCredentials.UserName.UserName = username;

                      client.ClientCredentials.UserName.Password = password;

                      client.Open();

           

           

                      var result = client.QueryXml("SELECT TOP 1 NodeID from Orion.Nodes WHERE sysname like 'Tok-foundry' RETURN XML AUTO", null);

           

           

                      var nodeID = result.XPathSelectElement("//*[local-name()='NodeID']").Value;

           

           

                      var arguments = PrepareArguments("N:" + nodeID, DateTime.Now, DateTime.Now.AddHours(6), false);

                      var result2 = client.Invoke("Orion.Nodes", "Unmanage", arguments);

           

           

                      Console.Write(result2);

           

           

                      client.Close();

                      Console.ReadLine();

                  }

           

           

                  static XElement PrepareArgument(object argument)

                  {

                      var dcs = new DataContractSerializer(argument.GetType());

                      var doc = new XmlDocument();

                      using (var writer = doc.CreateNavigator().AppendChild())

                      {

                          dcs.WriteObject(writer, argument);

                      }

           

           

                      return XDocument.Load(new XmlNodeReader(doc)).Root;

                  }

           

           

                  static ArrayOfXmlElement PrepareArguments(params object[] args)

                  {

                      var aoxe = new ArrayOfXmlElement();

                      aoxe.AddRange(args.Select(PrepareArgument));

                      return aoxe;

                  }

              }

          }

            • Re: How to create array of arguments for Unmanage/Remanage? (C#)
              fourmica

              Thank you very much, I appreciate your help! It worked!

              • Re: How to create array of arguments for Unmanage/Remanage? (C#)
                satventures

                I was just looking for the using statement I needed to work with SWIS in C# since it's a pretty new language for me, but that code example is fantastic! Thanks for sharing.

                • Re: How to create array of arguments for Unmanage/Remanage? (C#)
                  pbishop

                  Hello TDanner -

                  I have been playing with the SDK with Powershell - but am interested in creating a tool using C#.

                  I tried building a tool using your script but got stuck at [Using CSClient.SWIS] I did not know what file [.dll?] to reference.

                   

                  Please provide some assistance if you could?

                   

                  Regards,

                  Peter

                  • Re: How to create array of arguments for Unmanage/Remanage? (C#)
                    scottfraley

                    Hello tdanner,

                     

                    Wow, this is just about exactly what I'm trying to do, but I want to use the REST API (in C#) instead of the SOAP stuff (because the SOAP stuff is a royal pain). Is that possible?

                     

                    I'm also trying to get all the interfaces connected to a given node using the following query;

                    / SELECT N.NodeID, N.Caption, N.IPAddress, N.NodeName, N.Status, N.Interfaces FROM Orion.Nodes N WHERE N.NodeName LIKE 'NodeNames%' / but I just get '400 (bad request)'. Unfortunately the Orion SDK document only does a surface job of explaining the SWQL syntax. If you can point me to some other document that explains 'joined' selects, that would be great! (Or at least a fix to this query for now.) ;D

                     

                     

                    Thanks,

                    Scott

                      • Re: How to create array of arguments for Unmanage/Remanage? (C#)
                        tdanner

                        In general, anything you can do with the SOAP API should work with the REST API as well.

                         

                        To diagnose your "400 Bad Request" error, I would need to see more details about how you are making the request. But my first guess is that you are putting the SWQL query in the URL query string and not URL-encoding the "%" character in the WHERE clause. HTML URL Encoding Reference

                          • Re: How to create array of arguments for Unmanage/Remanage? (C#)
                            scottfraley

                            tdanner wrote:

                             

                            In general, anything you can do with the SOAP API should work with the REST API as well.

                            That's great to hear, but then becomes all about "How?" Especially if one is trying to do what at least seems like a semi-complex query such as...

                             

                            My query now looks like this: [...SolarWinds/InformationService/v3/Json/Query?query=]

                            SELECT N.NodeID, N.IPAddress, N.NodeName, N.Status, N.Interfaces FROM Orion.Nodes N WHERE N.NodeName LIKE '<nodeNames>%25'

                             

                            The interesting thing is that with or without the 'url encoded' % symbol, I'm getting the following fault.

                             

                            <Fault xmlns="https://lsdorion/SolarWinds/InformationService/v3/Json/Query">

                               <Message>Data type Orion.NPM.Interfaces not found</Message>

                            </Fault>

                             

                            (side(ish) question: as a general rule, should I be UrlEncoding the part of the Uri after "?query=" ?)

                             

                            So, I'm trying to figure out the best way to get a collection of nodes, along with each node's connected Interfaces. Is that doable in a single query? And if so, can you show me?  (I'll be yer best friend!) 

                             

                             

                            Thanks,

                            Scott

                        • Re: How to create array of arguments for Unmanage/Remanage? (C#)
                          scottfraley

                          Hi again,

                           

                          Hopefully my last question, at least for the day.. ( ).  I still need to know how to do the following via a REST call. (I swear I searched the document up and down and didn't see anything on how to 'Invoke a Verb' via the REST API.)

                          tdanner wrote:

                                      var arguments = PrepareArguments("N:" + nodeID, DateTime.Now, DateTime.Now.AddHours(6), false);

                                      var result2 = client.Invoke("Orion.Nodes", "Unmanage", arguments);

                           

                          As always; any help appreciated!

                           

                          -Scott

                            • Re: Re: How to create array of arguments for Unmanage/Remanage? (C#)
                              tdanner

                              Invoke Request

                              POST https://localhost:17778/SolarWinds/InformationService/v3/Json/Invoke/Metadata.Entity/GetAliases HTTP/1.1
                              Authorization: Basic YWRtaW46
                              User-Agent: curl/7.20.0 (i386-pc-win32) libcurl/7.20.0 OpenSSL/0.9.8l zlib/1.2.3
                              Host: localhost:17778
                              Accept: */*
                              Content-Type: application/json
                              Content-Length: 39
                              
                              ["SELECT B.Caption FROM Orion.Nodes B"]
                              

                               

                              Invoke Response

                              HTTP/1.1 200 OK
                              Content-Length: 19
                              Content-Type: application/json
                              Server: Microsoft-HTTPAPI/2.0
                              Date: Fri, 27 Jul 2012 19:23:27 GMT
                              
                              {"B":"Orion.Nodes"}
                              

                               

                              The Metadata.GetAliases verb takes one string argument and returns a PropertyBag.

                               

                              To unmanage a node, the URL would be: https://server:17778/SolarWinds/InformationService/v3/Json/Invoke/Orion.Nodes/Unmanage and the post data would be:

                               

                              ["N:15", "2014-01-16T22:00Z", "2014-01-16T22:30Z", "false"]
                              

                               

                              Those timestamps are in ISO 8601 format, since JSON does not have a native datetime format.

                               

                              Note: ordinarily the fourth parameter to Orion.Nodes.Unmanage is a boolean, so you would expect the json to just be false rather than the string "false", but we seem to have a parsing bug that causes it to get confused on the native JSON boolean. Fortunately if you pass it as a string it will figure it out and do the right thing.

                                • Re: How to create array of arguments for Unmanage/Remanage? (C#)
                                  scottfraley

                                  Well color me embarrassed. I just looked back at the Orion SDK doc under Useful Verbs and oh look, there's exactly what I need!  (Well, the description of the parameters at least.)

                                   

                                   

                                  Thanks again,

                                  Scott

                                  • Re: Re: How to create array of arguments for Unmanage/Remanage? (C#)
                                    scottfraley

                                    I got my code together today and am trying to Unmanage a Node. So, I POST the following Uri using HttpClient/HttpRequestMessage.

                                     

                                    https://<ourServer>:17778/SolarWinds/InformationService/v3/Json/Invoke/Orion.Nodes/Unmanage

                                     

                                    And I send content (set using myHttpRequestMessage.Content = new StringContent(manageNodeStateRequestData);

                                    (Where manageNodeStateRequestData contains: ["N:712", "2014-01-17T22:58Z", "2014-01-17T22:59Z", "false"])

                                     

                                    And I keep getting the following response:

                                    500 (Internal Server Error)

                                     

                                    Can anyone (tdanner / Bueler? ... Bueler? ) give my any advice on how to figure out what the heck I'm doing wrong here, and/or how to figure out why I'm getting a 500?

                                     

                                     

                                    Thanks,

                                    Scott

                                      • Re: Re: How to create array of arguments for Unmanage/Remanage? (C#)
                                        scottfraley

                                        Finally got a message I could use and found out I was sending the request body/data as 'plain text' when it needed to be 'application/json'. Fixed that, and now get "Access to Orion.Nodes.Unmanage verb denied." !!

                                         

                                        Here are the request and response. Do I have to have special permissions on the server in order to do this 'action,' or... ?

                                         

                                        REQUEST: (Via C# / .Net 4.5)

                                        POST https://OurServer:17778/SolarWinds/InformationService/v3/Json/Invoke/Orion.Nodes/Unmanage HTTP/1.1

                                        Accept: application/json

                                        Authorization: Basic <Encoded user:pass>

                                        Content-Type: application/json

                                        Host: OurServer:17778

                                        Content-Length: 60

                                        Expect: 100-continue

                                         

                                        ["N:712", "2014-01-20T16:10Z", "2014-01-20T16:11Z", "false"]

                                         

                                         

                                        RESPONSE:

                                        HTTP/1.1 400 Bad Request

                                        Content-Length: 132

                                        Content-Type: application/json

                                        Server: Microsoft-HTTPAPI/2.0

                                        Date: Mon, 20 Jan 2014 16:10:28 GMT

                                         

                                        {"Message":"Access to Orion.Nodes.Unmanage verb denied.","ErrorCode":20,"UserMessage":"Access to Orion.Nodes.Unmanage verb denied."}

                                         

                                        Also, is there a document or page somewhere that lists out the 'ErrorCode(s)' ? I can't help but wonder if that 20 (above) gives me more info than just access denied.

                                         

                                        P.S. I keep forgetting to ask this question; the reason we want to 'unmanage' a Node (and it's connected interfaces) is so that when a given node needs to have it's firmware updated, and we take it offline to do so, we don't want to get a ton of alerts for something we know is happening. The question is, is Unmanaging a Node (& the i-faces) the correct way to accomplish this?)

                                         

                                        Thanks!

                                        Scott

                                • Re: How to create array of arguments for Unmanage/Remanage? (C#)
                                  fourmica

                                  Tdanner,

                                   

                                  Thank you again for helping me with this. May I please lean on you for a follow-up?

                                   

                                  How do I interpret the results returned by these methods to determine if the operation was successful? For example, if I unmanage an internal Node, the following XML is returned:


                                  <?xml version="1.0" encoding="utf-8" ?>

                                  <Return i:nil="true" xmlns="http://schemas.datacontract.org/2004/07/SolarWinds.InformationService.Contract" xmlns:d1p1="http://schemas.datacontract.org/2004/07/System" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" />

                                  I can't figure out how to interpret this for success or failure; right now I'm while-looping against the Nodes table until Unmanaged == true. I'm guessing there's a better way than this?

                                  Thanks,

                                  Josh