go-junos & Junos Space

A little while back, I introduced you to the go-junos Go library that I wrote for interaction with Junos devices. I have a lot planned, as far as features go. Today, I'd like to announce that you will be able to interact with Junos Space through the library as well! Currently, it's limited to the following abilities...but more are on the way:

  • List all devices managed by Junos Space.
  • Add and remove devices to/from Junos Space.
  • Get information about all of the software images that Junos Space manages.
    • With this information, you can stage images to devices to be used at a later time to upgrade.
    • Directly issue a software upgrade to a device.
    • Remove staged images from a device.

Soon you'll be able to interact with Security Director as well, with the following features planned:

  • Add/remove address objects and groups.
  • Push/publish changes to firewalls.
  • Policy management (this one might take longer than the previous items).

So, without futher adieu, here's a basic tutorial on how to add/remove devices, and issue a software upgrade to one of them.

Establish our connection

First, make sure you have the go-junos library imported.

// Make sure you have the go-junos library imported.
import (  
    "github.com/scottdware/go-junos"
)

Now let's connect to our Junos Space server.

space := junos.NewServer("space.company.com", "admin", "juniper123")  

Device Management

Now that we've established our connection, let's work with the devices.

// Get information about all the devices within Junos Space.
devices, err := space.Devices()  
if err != nil {  
    fmt.Println(err)
}

The devices variable returns a struct list of the following information:

type DeviceList struct {  
    XMLName xml.Name `xml:"devices"`
    Devices []Device `xml:"device"`
}

type Device struct {  
    ID        int    `xml:"key,attr"`
    Family    string `xml:"deviceFamily"`
    Version   string `xml:"OSVersion"`
    Platform  string `xml:"platform"`
    Serial    string `xml:"serialNumber"`
    IPAddress string `xml:"ipAddr"`
    Name      string `xml:"name"`
}

So to loop over them, and extract the fields that we want, we can do the following:

for _, device := range devices.Devices {  
    fmt.Printf("Name: %s, Version: %s, IPAddress: %s\n", device.Name, device.Version, device.IPAddress)
}

Let's add a device:

jobID, err := space.AddDevice("sdubs-fw", "admin", "warmachinerox")  
if err != nil {  
    fmt.Println(err)
}

Note: Currently, there is no action to handle the jobID number that is returned, but something is in the works. You could query the job-management API and return job info if you'd like. See the Junos Space API for more information.

Eh, we don't want that device anymore so now let's get rid of it:

err = space.RemoveDevice("sdubs-fw")  
if err != nil {  
    fmt.Println(err)
}

Here's how to resynchronize a device with Junos Space. This comes in handy if you make a lot of changes outside of Space, such as adding interfaces, etc.

jobID, err := space.Resync("sdubs-fw")  
if err != nil {  
    fmt.Println(err)
}

Software Management

Let's take a look at how we can issue a software upgrade using this library.

We need a list of what software packages Junos Space manages that we can use. You can grab this information like so:

sw, err := space.Software()  
if err != nil {  
    fmt.Println(err)
}

Similar to listing our devices earlier, the sw variable holds the following information:

type SoftwarePackages struct {  
    Packages []SoftwarePackage `xml:"package"`
}

type SoftwarePackage struct {  
    ID       int    `xml:"key,attr"`
    Name     string `xml:"fileName"`
    Version  string `xml:"version"`
    Platform string `xml:"platformType"`
}

We can loop through this and just get the names of the packages:

for _, pkg := range sw.Packages {  
    fmt.Println(pkg.Name)
}

Alright, now that we've picked an image, let's stage it (which basically just copies/downloads the image to the device) to be used for a later upgrade:

jobID, err := space.StageSoftware("sdubs-fw", "junos-srxsme-12.1X46-D20.5-domestic.tgz", false)  
if err != nil {  
    fmt.Println(err)
}

The false option basically let's you choose if you want to remove any pre-existing image when staging a new one. true for yes, false for no.

Now that we have our image staged on our device...let's prepare to upgrade it! We'll need to configure some options that we pass to our upgrade function, and those can be specified like so:

    // UseDownloaded: Use a pre-staged image. If set to false, then the image will be downloaded at the time of the upgrade.
    // Validate: Validates our configuration against the new image.
    // Reboot: Reboot after an upgrade.
    // RebootAfter: Reboot after X minutes. Leaving this 0 basically disables this option.
    // Cleanup: Remove any existing images.
    // RemoveAfter: Remove our image after a successful upgrade, to free up more space.

    options := &junos.SoftwareUpgrade{
        UseDownloaded: true,
        Validate: false,
        Reboot: true,
        RebootAfter: 0,
        Cleanup: false,
        RemoveAfter: false,
    }

    job, err := space.DeploySoftware("sdubs-fw", "junos-srxsme-12.1X46-D20.5-domestic.tgz", options)
    if err != nil {
        fmt.Println(err)
    }

And that's pretty much it! Software upgrades can take a while, depending on the device and image, so please keep that in mind. Just like I noted above, the jobID has no function at the moment, but will in the future. Again, you could query the server yourself to check the status, or see the job status in the Junos Space GUI.

I hope that you find this helpful. More abilities will be coming soon, so please check back.

For more information, please check the documentation on the Github repo, or the GoDoc page.