-
Notifications
You must be signed in to change notification settings - Fork 41
/
devices.go
195 lines (166 loc) · 4.79 KB
/
devices.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
package junos
import (
"encoding/xml"
"fmt"
"regexp"
"github.com/scottdware/go-rested"
)
// Devices contains a list of managed devices.
type Devices struct {
XMLName xml.Name `xml:"devices"`
Devices []Device `xml:"device"`
}
// A Device contains information about each individual 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"`
ConnectionStatus string `xml:"connectionStatus"`
ManagedStatus string `xml:"managedStatus"`
}
// addDeviceIPXML is the XML we send (POST) for adding a device by IP address.
var addDeviceIPXML = `
<discover-devices>
<ipAddressDiscoveryTarget>
<ipAddress>%s</ipAddress>
</ipAddressDiscoveryTarget>
<sshCredential>
<userName>%s</userName>
<password>%s</password>
</sshCredential>
<manageDiscoveredSystemsFlag>true</manageDiscoveredSystemsFlag>
<usePing>true</usePing>
</discover-devices>
`
// addDeviceHostXML is the XML we send (POST) for adding a device by hostname.
var addDeviceHostXML = `
<discover-devices>
<hostNameDiscoveryTarget>
<hostName>%s</hostName>
</hostNameDiscoveryTarget>
<sshCredential>
<userName>%s</userName>
<password>%s</password>
</sshCredential>
<manageDiscoveredSystemsFlag>true</manageDiscoveredSystemsFlag>
<usePing>true</usePing>
</discover-devices>
`
// getDeviceID returns the ID of a managed device.
func (s *Space) getDeviceID(device interface{}) (int, error) {
var err error
var deviceID int
ipRegex := regexp.MustCompile(`(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})`)
devices, err := s.Devices()
if err != nil {
return 0, err
}
switch device.(type) {
case int:
deviceID = device.(int)
case string:
if ipRegex.MatchString(device.(string)) {
for _, d := range devices.Devices {
if d.IPAddress == device.(string) {
deviceID = d.ID
}
}
}
for _, d := range devices.Devices {
if d.Name == device.(string) {
deviceID = d.ID
}
}
}
return deviceID, nil
}
// AddDevice adds a new managed device to Junos Space, and returns the Job ID.
func (s *Space) AddDevice(host, user, password string) (int, error) {
r := rested.NewRequest()
r.BasicAuth(s.User, s.Password)
headers := map[string]string{
"Content-Type": contentDiscoverDevices,
}
var job jobID
var addDevice, xmlBody string
ipRegex := regexp.MustCompile(`(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})`)
if ipRegex.MatchString(host) {
addDevice = addDeviceIPXML
}
addDevice = addDeviceHostXML
uri := fmt.Sprintf("https://%s/api/space/device-management/discover-devices", s.Host)
xmlBody = fmt.Sprintf(addDevice, host, user, password)
resp := r.Send("post", uri, []byte(xmlBody), headers, nil)
if resp.Error != nil {
return 0, resp.Error
}
err := xml.Unmarshal(resp.Body, &job)
if err != nil {
return 0, err
}
return job.ID, nil
}
// Devices queries the Junos Space server and returns all of the information
// about each device that is managed by Space.
func (s *Space) Devices() (*Devices, error) {
r := rested.NewRequest()
r.BasicAuth(s.User, s.Password)
var devices Devices
uri := fmt.Sprintf("https://%s/api/space/device-management/devices", s.Host)
resp := r.Send("get", uri, nil, nil, nil)
if resp.Error != nil {
return nil, resp.Error
}
err := xml.Unmarshal(resp.Body, &devices)
if err != nil {
return nil, err
}
return &devices, nil
}
// RemoveDevice removes a device from Junos Space. You can specify the device ID, name
// or IP address.
func (s *Space) RemoveDevice(device interface{}) error {
r := rested.NewRequest()
r.BasicAuth(s.User, s.Password)
var err error
deviceID, err := s.getDeviceID(device)
if err != nil {
return err
}
if deviceID != 0 {
uri := fmt.Sprintf("https://%s/api/space/device-management/devices/%d", s.Host, deviceID)
resp := r.Send("delete", uri, nil, nil, nil)
if resp.Error != nil {
return resp.Error
}
}
return nil
}
// Resync synchronizes the device with Junos Space. Good to use if you make a lot of
// changes outside of Junos Space such as adding interfaces, zones, etc.
func (s *Space) Resync(device interface{}) (int, error) {
r := rested.NewRequest()
r.BasicAuth(s.User, s.Password)
headers := map[string]string{
"Content-Type": contentResync,
}
var job jobID
deviceID, err := s.getDeviceID(device)
if err != nil {
return 0, err
}
uri := fmt.Sprintf("https://%s/api/space/device-management/devices/%d/exec-resync", s.Host, deviceID)
resp := r.Send("post", uri, nil, headers, nil)
if resp.Error != nil {
return 0, resp.Error
}
err = xml.Unmarshal(resp.Body, &job)
if err != nil {
return 0, err
}
return job.ID, nil
}