<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>second phase &#187; opsware</title>
	<atom:link href="http://www.phase2.net/tag/opsware/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.phase2.net</link>
	<description>confessions of a geek</description>
	<lastBuildDate>Fri, 06 Jan 2012 19:51:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Here&#8217;s an SA quickie</title>
		<link>http://www.phase2.net/2011/08/heres-an-sa-quickie/</link>
		<comments>http://www.phase2.net/2011/08/heres-an-sa-quickie/#comments</comments>
		<pubDate>Wed, 17 Aug 2011 20:10:47 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[opsware]]></category>

		<guid isPermaLink="false">http://www.phase2.net/?p=1502</guid>
		<description><![CDATA[Not going to explain this one much &#8211; basically got asked by a coworker to write up a script real quick for him to update the Deployment Stage against every &#8230; <a class="more" href="http://www.phase2.net/2011/08/heres-an-sa-quickie/">Continue reading</a>]]></description>
			<content:encoded><![CDATA[<p>Not going to explain this one much &#8211; basically got asked by a coworker to write up a script real quick for him to update the Deployment Stage against every system in a device group.</p>
<pre class="brush:py">#!/opt/opsware/agent/bin/python

import sys
sys.path.append("/opt/opsware/pylibs")
sys.path.append("/opt/opsware/agent/pylibs")

from pytwist import *
from pytwist.com.opsware.device import DeviceGroupRef

ts = twistserver.TwistServer()
ds = ts.device.DeviceGroupService
ss = ts.server.ServerService

# Enter your username and password here
ts.authenticate("username","password")

# Enter the device group object ID for the group you want to iterate over
# You can get this object ID from the GUI
dgref = DeviceGroupRef(#######)
srefs = ds.getDevices(dgref)
for sref in srefs:
    svo = ss.getServerVO(sref)
    print "Updating %s" % svo.name
    # Set the stage.  This has to be a valid option - these are always in caps.
    svo.stage = "PRODUCTION"
    ss.update(sref, svo, 0, 0)</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.phase2.net/2011/08/heres-an-sa-quickie/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HP SA &#8211; Running a known script from pytwist</title>
		<link>http://www.phase2.net/2011/08/hp-sa-running-a-known-script-from-pytwist/</link>
		<comments>http://www.phase2.net/2011/08/hp-sa-running-a-known-script-from-pytwist/#comments</comments>
		<pubDate>Tue, 16 Aug 2011 20:06:04 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[Work]]></category>
		<category><![CDATA[opsware]]></category>

		<guid isPermaLink="false">http://www.phase2.net/?p=1497</guid>
		<description><![CDATA[I was asked to put up a script that displays an easy way to find a script reference and then start that script. One thing to realize is that the &#8230; <a class="more" href="http://www.phase2.net/2011/08/hp-sa-running-a-known-script-from-pytwist/">Continue reading</a>]]></description>
			<content:encoded><![CDATA[<p>I was asked to put up a script that displays an easy way to find a script reference and then start that script. One thing to realize is that the hardest part about the pytwist API, besides some of the obscure functions, is actually finding your references so that you can get the objects to work on.</p>
<p>There are a few ways you can go around doing this. You can use filters and the search capability, you can manually create your ref, or you can find the refs via other objects, like device groups. The last one I mentioned is actually a very good way to loop through a set of systems to perform a task.</p>
<p>I&#8217;ll display the first method in this article and write up the other two later.</p>
<p>The first thing we need to do is get our script reference. Every object you work with in SA generally has a reference object and what I call the &#8216;virtual object&#8217; ( or whatever VO really stands for ). The VO contains all the important attributes where as the reference only contains the id of the object in SA and the name. There are some methods contained in the VO, but the pytwist API makes common use of a &#8216;Service&#8217; interface for specific types of objects, like the ServerService, the ServerScriptService, the SearchService, JobService, DeviceGroupService and so on that contain the methods that really make use of the VOs.</p>
<p>This first script enables us to run a known SA script on a known host thru SA from a command line. Note that the command line can be any host that has an agent &#8211; this doesn&#8217;t need to be run from the core.</p>
<p>I&#8217;ll show the script first, then explain it. This script is a version that can be run from an agent that has the Python 2 API Access for Server module installed.</p>
<pre class="brush:py">import sys
from optparse import OptionParser
from getpass import getpass
sys.path.append('/opt/opsware/smopylibs2')
sys.path.append('/opt/opsware/agent_tools/') 

import agenttools_common
from pytwist import *
from pytwist.com.opsware.server import ServerRef
from pytwist.com.opsware.script import ServerScriptRef
from pytwist.com.opsware.custattr import NoSuchFieldException

ts = twistserver.TwistServer()

ss = ts.server.ServerService
scs = ts.script.ServerScriptService

# This is the same basic authentication scheme used in most of
# my scripts.  You can tear this out and just use the
# ts.authenticate method with the values already filled in.
parser = OptionParser()
parser.add_option("-u","--user",dest="sauser",
                  help="SA login id")
parser.add_option("-p","--pass",dest="sapasswd",
                  help="SA login password")
parser.add_option("-r","--prompt",action="store_true",dest="readstdin",
                  help="Prompt for passwords instead of using arguments")

(options, args) = parser.parse_args()

if not options.sapasswd and not options.readstdin:
        print "You must specify a password to login to SA."
        sys.exit(1)

if not options.sauser:
        print "You must specify a username to login to SA."
        sys.exit(1)

if options.readstdin:
    options.sapasswd = getpass("Enter Opsware Password: ")

ts.authenticate(options.sauser, options.sapasswd)

# Now the real work starts

# Create a reference to a script we know the ID of
# The ID can be obtained from the SA Gui
scriptRef = ServerScriptRef(22530102)

# Create a reference to a server we know about
serverRef = ServerRef(730102)

# In order to run the script, we'll use the startServerScript method
# from the ServerScriptService.  It requires the script ref, an arugments
# object.  We can optionally give it a tag that it will put under
# the ticket ID.  There are also optional arguments for a job notification
# and job schedule that I won't cover here.
#
# We have the reference already, so we need to create the job argument
# object.  We only need to set the list of targets, although there are
# options for setting the username and password of the script

# Creates the object
scriptArgs = com.opsware.script.ServerScriptJobArgs()

# Requires a list of scriptableRefs, which can be ServerRefs,
# DeviceGroupRefs or HypervisorRefs.  In our case, ServerRefs
scriptArgs.targets = [serverRef]

# Now we can run the job
runScript = scs.startServerScript(scriptRef, scriptArgs, 'Ticket ID #001', None, None)
print "Job started as id %d" % runScript.id</pre>
<p>So, besides the basic authentication and argument parsing, there isn&#8217;t too much to this script. We have to create the references needed and we do that by importing the references in from pytwist and then using them as constructors like so:</p>
<pre class="brush:py">from pytwist.com.opsware.server import ServerRef
from pytwist.com.opsware.script import ServerScriptRef
...
scriptRef = ServerScriptRef(22530102)
serverRef = ServerRef(730102)</pre>
<p>In order to run the script, we need to call the startServerScript, which is part of the ServerScriptService interface. But, in order to call it, we need to create one more object, the ServerScriptJobArgs object. We create the object by calling the constructor directly:</p>
<pre class="brush:py">scriptArgs = com.opsware.script.ServerScriptJobArgs()</pre>
<p>You should note that we could have done the same things with the ServerRef and ScriptRef constructors. Instead of importing them and then calling them, we could have simply done this:</p>
<pre class="brush:py">scriptRef = com.opsware.script.ScriptRef(22530102)
serverRef = com.opsware.server.ServerRef(730102)</pre>
<p>Generally I&#8217;m using alot of server refs, so I like to import to save on typing. Either way, we now have a blank ServerScriptJobArgs object that we need to fill. In our case, we only need to fill out the targets attribute, which is actually a list of any Scriptable Ref. This tells our script which targets it&#8217;s going to run on. As mentioned in the comments, a scriptable reference is either a DeviceGroupRef, a ServerRef or a HypervisorRef. Since we have a ServerRef, we just need to contain it in a list and assign it to the targets attribute:</p>
<pre class="brush:py">scriptArgs.targets = [serverRef]</pre>
<p>Everything is setup now, so I can just call the startServerScript method. The method takes 5 arguments, 3 of which are optional. The 3 optional requires are a ticket id tag, a job notification object and a job schedule object. The ticket id tag is just a string, so it&#8217;s easy to create but I&#8217;m not going to bother with the other two, so our call looks like this:</p>
<pre class="brush:py">runScript = scs.startServerScript(scriptRef, scriptArgs, 'Ticket ID #001'
, None, None)</pre>
<p>Remember that the &#8216;scs&#8217; is just a shortcut to the ServerScriptService. We could have called this method another way:</p>
<pre class="brush:py">runScript = scs.startServerScript(scriptRef, scriptArgs, 'Ticket ID #001', None, None)</pre>
<p>Again, I prefer the former just to save on typing if I plan on using the service multiple times. The method returns a Run Server Script instance, which we can do other things with, but that&#8217;ll have to wait for another article. In the example, I print out the job ID so that I can find and verify the job in the GUI easily.</p>
<p>That&#8217;s it for now &#8211; in the next article I&#8217;ll show how you can use the filter to give the user a way to specify the name of the script they want to run and on which servers.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.phase2.net/2011/08/hp-sa-running-a-known-script-from-pytwist/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Opsware Custom Attributes and You.</title>
		<link>http://www.phase2.net/2010/03/opsware-custom-attributes-and-you/</link>
		<comments>http://www.phase2.net/2010/03/opsware-custom-attributes-and-you/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 22:01:36 +0000</pubDate>
		<dc:creator>steve</dc:creator>
				<category><![CDATA[Work]]></category>
		<category><![CDATA[dns]]></category>
		<category><![CDATA[opsware]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://www.phase2.net/?p=1027</guid>
		<description><![CDATA[I realize most of the time I end up complaining about Opsware &#8211; that&#8217;s generally because it&#8217;s part of the human condition.  We say stuff when we&#8217;re upset or angry &#8230; <a class="more" href="http://www.phase2.net/2010/03/opsware-custom-attributes-and-you/">Continue reading</a>]]></description>
			<content:encoded><![CDATA[<p>I realize most of the time I end up complaining about Opsware &#8211; that&#8217;s generally because it&#8217;s part of the human condition.  We say stuff when we&#8217;re upset or angry or don&#8217;t like something.  How many times have you ever called up the phone company to tell them &#8216;Great job!&#8217;</p>
<p>Yeah, I thought so.</p>
<p>So I figured I&#8217;d write an article on one of the great things I love about Opsware &#8211; Custom Attributes! Combined with Dynamic Groups, these puppies provide the ability to create scripts that I don&#8217;t have to duplicate for different hosts.</p>
<p>First, however, I should explain what Dynamic Groups are.  Dynamic Groups allow the user to group systems based on certain criteria.  For instance, you want all the systems in a certain network to be grouped together.  Whenever you add a system from that network into Opsware, it automatically becomes a member of that group.  Neat by itself but nothing extraordinary.</p>
<p>However, you can assign Custom Attributes ( further known as CAs ) to the Dynamic Group.  So for my new dynamic group that I created ( for example, a group that pulls in all hosts in the 192.168.0.0/24 network ), I can assign some CAs to the group and the CAs get assigned to each host within the group.</p>
<p>You may ask yourself, &#8216;Why is this useful?&#8217;.  It&#8217;s not yet.  There&#8217;s one more piece that&#8217;s missing from the puzzle.  The piece that is missing is a software package that Opsware comes with &#8211; Agent Tools.  When you install the Agent Tools, it comes with a set of python Opsware APIs and small scripts that use the API to make calls back to the master Opsware system and get information &#8211; including those CAs!</p>
<p>Armed with these 3 pieces, it becomes easy to create a script that uses the CAs that are dynamically assigned to your host to do all sorts of things.  For example, let&#8217;s say you want to create a script that checks your /etc/resolv.conf on any system in that 192.168.0.0/24 network.  First, we&#8217;ll create the dynamic group and assign it the correct device membership.</p>
<p>Next, edit the group and add a CA named something like &#8216;<strong>DNS_SERVERS</strong>&#8216;.  For the value, put in a DNS server on separate lines and then save your group.  Make sure you&#8217;ve got the agent tools package installed and we can run a simple test.</p>
<pre class="terminal">[root@frenzy1a.star.dev:~]# /opt/opsware/agent_tools/get_cust_attr.sh DNS_SERVERS
192.168.0.20
192.168.0.21</pre>
<p>With that information, we can create a pretty simple shell or python script ( pick your poison ) to make sure that our /etc/resolv.conf has those servers defined.  For kicks, here&#8217;s an example script that checks to make sure the IPs in the <strong>DNS_SERVERS</strong> CA are set in /etc/resolv.conf.  You could easily modify this so that it actually inserts the values.</p>
<pre class="brush:py">#!/opt/opsware/agent/bin/python

import sys
sys.path.append('/opt/opsware/agent_tools/')
import agenttools_common
import re
from string import split
from pytwist.com.opsware.custattr import NoSuchFieldException

def searchFile(file,pattern):
    found = 0
    search = re.compile(pattern)
    try:
        f = open(file, "r")
    except IOError:
        sys.stderr.write("Could not open file %s.n" % (file))
        sys.exit(3)

    for line in f.readlines():
        if search.match(line):
            found = 1
        break

    return found

def main(args):
    ts = agenttools_common.ts
    servers = {}
    result = 0
    hostref = agenttools_common.getServerRef()

    try:
        custattr = ts.server.ServerService.getCustAttr(hostref,
        "DNS_SERVERS", 1)
    except NoSuchFieldException:
        sys.stderr.write("Could not find custom attribute DNS_SERVERS.n")
        sys.exit(3)

    servers = split(custattr)
    for s in servers:
        found = searchFile("/etc/resolv.conf","^nameservers+" + s)
        if not found:
            sys.stderr.write("The server %s was not configured in"
            " /etc/resolv.conf" % (s))
        result = 1

    return result

if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))</pre>
<p>Now if I have another network, say, 192.168.120.0/24, I can do the same thing.  Make the group, assign the membership, create the <strong>DNS_SERVERS</strong> CA and assign the script and presto &#8211; it&#8217;s done! No duplication of work involved here and I can control the contents of the file from the Opsware console.</p>
<p>One last thing about CAs &#8211; they do support overrides.  For instance, I can override the CA by creating the same named CA on the host itself.  This will override the CA at the group level.  One thing you need to be careful, however, is that you don&#8217;t assign a host into two groups that define the same CA &#8211; there&#8217;s no priority between the groups and they don&#8217;t combine the contents of the CA to make one CA, so you&#8217;ll get random results.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.phase2.net/2010/03/opsware-custom-attributes-and-you/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

