func (p *PaloAlto) RestartSystem() error {
	var reqError requestError
	command := "<request><restart><system></system></restart></request>"
	_, resp, errs := r.Post(p.URI).Query(fmt.Sprintf("type=op&cmd=%s&key=%s", command, p.Key)).End()
	if errs != nil {
		return errs[0]
	}
	if err := xml.Unmarshal([]byte(resp), &reqError); err != nil {
		return err
	}
	if reqError.Status != "success" {
		return fmt.Errorf("error code %s: %s", reqError.Code, errorCodes[reqError.Code])
	}
	return nil
}
RestartSystem will issue a system restart to the device.
package panos
import (
	"crypto/tls"
	"encoding/xml"
	"errors"
	"fmt"
	"io/ioutil"
	"net/url"
	"regexp"
	"strconv"
	"strings"
	"github.com/parnurzeal/gorequest"
	"gopkg.in/resty.v1"
)
type PaloAlto struct {
	Host                       string
	Key                        string
	URI                        string
	Platform                   string
	Model                      string
	Serial                     string
	SoftwareVersion            string
	DeviceType                 string
	Panorama                   bool
	Shared                     bool
	IPAddress                  string
	Netmask                    string
	DefaultGateway             string
	MACAddress                 string
	Time                       string
	Uptime                     string
	GPClientPackageVersion     string
	GPDatafileVersion          string
	GPDatafileReleaseDate      string
	GPClientlessVPNVersion     string
	GPClientlessVPNReleaseDate string
	AppVersion                 string
	AppReleaseDate             string
	AntiVirusVersion           string
	AntiVirusReleaseDate       string
	ThreatVersion              string
	ThreatReleaseDate          string
	WildfireVersion            string
	WildfireReleaseDate        string
	URLDB                      string
	URLFilteringVersion        string
	LogDBVersion               string
	MultiVsys                  string
	OperationalMode            string
}
type AuthMethod struct {
	Credentials []string
	APIKey      string
}
type Jobs struct {
	XMLName xml.Name `xml:"response"`
	Status  string   `xml:"status,attr"`
	Code    string   `xml:"code,attr"`
	Jobs    []Job    `xml:"result>job"`
}
type Job struct {
	ID            int      `xml:"id"`
	User          string   `xml:"user"`
	Type          string   `xml:"type"`
	Status        string   `xml:"status"`
	Queued        string   `xml:"queued"`
	Stoppable     string   `xml:"stoppable"`
	Result        string   `xml:"result"`
	Description   string   `xml:"description,omitempty"`
	QueuePosition int      `xml:"positionInQ"`
	Progress      string   `xml:"progress"`
	Details       []string `xml:"details>line"`
	Warnings      string   `xml:"warnings,omitempty"`
	StartTime     string   `xml:"tdeq"`
	EndTime       string   `xml:"tfin"`
}
type Logs struct {
	XMLName   xml.Name `xml:"response"`
	Status    string   `xml:"status,attr"`
	Code      string   `xml:"code,attr"`
	StartTime string   `xml:"result>job>tdeq"`
	EndTime   string   `xml:"result>job>tfin"`
	JobStatus string   `xml:"result>job>status"`
	JobID     int      `xml:"result>job>id"`
	Logs      []Log    `xml:"result>log>logs>entry"`
}
type Log struct {
	DeviceName                 string `xml:"device_name,omitempty"`
	Serial                     string `xml:"serial,omitempty"`
	Rule                       string `xml:"rule,omitempty"`
	TimeGenerated              string `xml:"time_generated,omitempty"`
	TimeReceived               string `xml:"time_received,omitempty"`
	Type                       string `xml:"type,omitempty"`
	Subtype                    string `xml:"subtype,omitempty"`
	From                       string `xml:"from,omitempty"`
	To                         string `xml:"to,omitempty"`
	Source                     string `xml:"src,omitempty"`
	SourceUser                 string `xml:"srcuser,omitempty"`
	SourcePort                 int    `xml:"sport,omitempty"`
	SourceCountry              string `xml:"srcloc,omitempty"`
	Destination                string `xml:"dst,omitempty"`
	DestinationPort            int    `xml:"dport,omitempty"`
	DestinationCountry         string `xml:"dstloc,omitempty"`
	Application                string `xml:"app,omitempty"`
	Action                     string `xml:"action,omitempty"`
	NATSourceIP                string `xml:"natsrc,omitempty"`
	NATSourcePort              int    `xml:"natsport,omitempty"`
	NATDestinationIP           string `xml:"natdst,omitempty"`
	NATDestinationPort         int    `xml:"natdport,omitempty"`
	Packets                    int    `xml:"packets,omitempty"`
	PacketsSent                int    `xml:"pkts_sent,omitempty"`
	PacketsReceived            int    `xml:"pkts_received,omitempty"`
	Bytes                      int    `xml:"bytes,omitempty"`
	BytesSent                  int    `xml:"bytes_sent,omitempty"`
	BytesReceived              int    `xml:"bytes_received,omitempty"`
	SessionID                  int    `xml:"sessionid,omitempty"`
	SessionEndReason           string `xml:"session_end_reason,omitempty"`
	RepeatCount                int    `xml:"repeatcnt,omitempty"`
	Start                      string `xml:"start,omitempty"`
	Elapsed                    string `xml:"elapsed,omitempty"`
	Category                   string `xml:"category,omitempty"`
	ThreatCategory             string `xml:"thr_category,omitempty"`
	ThreatName                 string `xml:"threatid,omitempty"`
	ThreatID                   int    `xml:"tid,omitempty"`
	Misc                       string `xml:"misc,omitempty"`
	Severity                   string `xml:"severity,omitempty"`
	Direction                  string `xml:"direction,omitempty"`
	InboundInterface           string `xml:"inbound_if,omitempty"`
	OutboundInterface          string `xml:"outbound_if,omitempty"`
	ID                         int    `xml:"logid,attr"`
	Domain                     int    `xml:"domain,omitempty"`
	ReceiveTime                string `xml:"receive_time,omitempty"`
	SequenceNumber             string `xml:"seqno,omitempty"`
	ActionFlags                string `xml:"actionflags,omitempty"`
	ConfigVersion              int    `xml:"config_ver,omitempty"`
	Vsys                       string `xml:"vsys,omitempty"`
	Logset                     string `xml:"logset,omitempty"`
	Flags                      string `xml:"flags,omitempty"`
	Pcap                       string `xml:"flag-pcap,omitempty"`
	PcapID                     int    `xml:"pcap_id,omitempty"`
	Flagged                    string `xml:"flag-flagged,omitempty"`
	Proxy                      string `xml:"flag-proxy,omitempty"`
	URLDenied                  string `xml:"flag-url-denied,omitempty"`
	NAT                        string `xml:"flag-nat,omitempty"`
	CaptivePortal              string `xml:"captive-portal"`
	NonStandardDestinationPort string `xml:"non-std-dport"`
	Transaction                string `xml:"transaction,omitempty"`
	PBFClient2Server           string `xml:"pbf-c2s,omitempty"`
	PBFServer2Client           string `xml:"pbf-s2c,omitempty"`
	TemporaryMatch             string `xml:"temporary-match,omitempty"`
	SymmetricReturn            string `xml:"sym-return,omitempty"`
	SSLDecryptMirror           string `xml:"decrypt-mirror,omitempty"`
	CredentialDetected         string `xml:"credential-detected,omitempty"`
	MPTCP                      string `xml:"flag-mptcp-set,omitempty"`
	TunnelInspected            string `xml:"flag-tunnel-inspected,omitempty"`
	ReconExcluded              string `xml:"flag-recon-excluded,omitempty"`
	Protocol                   string `xml:"proto,omitempty"`
	TunnelType                 string `xml:"tunnel,omitempty"`
	TPadding                   int    `xml:"tpadding,omitempty"`
	CPadding                   int    `xml:"cpadding,omitempty"`
	TunnelIMSI                 int    `xml:"tunnelid_imsi,omitempty"`
	VsysID                     int    `xml:"vsys_id,omitempty"`
	ParentSessionID            int    `xml:"parent_session_id,omitempty"`
	ReportID                   int    `xml:"reportid,omitempty"`
	URLIndex                   int    `xml:"url_idx,omitempty"`
	HTTPMethod                 string `xml:"http_method,omitempty"`
	XForwardedFor              string `xml:"xff,omitempty"`
	Referer                    string `xml:"referer,omitempty"`
	UserAgent                  string `xml:"user_agent,omitempty"`
	SignatureFlags             string `xml:"sig_flags,omitempty"`
	ContentVersion             string `xml:"contentver,omitempty"`
	FileDigest                 string `xml:"filedigest,omitempty"`
	Filetype                   string `xml:"filetype,omitempty"`
	Sender                     string `xml:"sender,omitempty"`
	Recipient                  string `xml:"recipient,omitempty"`
	Subject                    string `xml:"subject,omitempty"`
	Cloud                      string `xml:"cloud,omitempty"`
	Padding                    int    `xml:"padding,omitempty"`
	ActionSource               string `xml:"action_source,omitempty"`
	TunnelID                   int    `xml:"tunnelid,omitempty"`
	IMSI                       string `xml:"imsi,omitempty"`
	MonitorTag                 string `xml:"monitortag,omitempty"`
	IMEI                       string `xml:"imei,omitempty"`
	DeviceGroupHierarchy1      int    `xml:"dg_hier_level_1,omitempty"`
	DeviceGroupHierarchy2      int    `xml:"dg_hier_level_2,omitempty"`
	DeviceGroupHierarchy3      int    `xml:"dg_hier_level_3,omitempty"`
	DeviceGroupHierarchy4      int    `xml:"dg_hier_level_4,omitempty"`
	Host                       string `xml:"host,omitempty"`
	Command                    string `xml:"cmd,omitempty"`
	Admin                      string `xml:"admin,omitempty"`
	Client                     string `xml:"client,omitempty"`
	Result                     string `xml:"result,omitempty"`
	Path                       string `xml:"path,omitempty"`
	BeforeChangePreview        string `xml:"before-change-preview,omitempty"`
	AfterChangePreview         string `xml:"after-change-preview,omitempty"`
	FullPath                   string `xml:"full-path,omitempty"`
	EventID                    string `xml:"eventid,omitempty"`
	Module                     string `xml:"module,omitempty"`
	Description                string `xml:"opaque,omitempty"`
}
type LogParameters struct {
	Query string
	NLogs int
	Skip int
	Direction string
	Action string
}
type RoutingTable struct {
	XMLName xml.Name `xml:"response"`
	Status  string   `xml:"status,attr"`
	Code    string   `xml:"code,attr"`
	Flags   string   `xml:"result>flags"`
	Routes  []Route  `xml:"result>entry"`
}
type Route struct {
	VirtualRouter string `xml:"virtual-router"`
	Destination   string `xml:"destination"`
	NextHop       string `xml:"nexthop"`
	Metric        int    `xml:"metric"`
	Flags         string `xml:"flags"`
	Age           int64  `xml:"age"`
	Interface     string `xml:"interface"`
}
type authKey struct {
	XMLName xml.Name `xml:"response"`
	Status  string   `xml:"status,attr"`
	Code    string   `xml:"code,attr"`
	Key     string   `xml:"result>key"`
}
type systemInfo struct {
	XMLName                    xml.Name `xml:"response"`
	Status                     string   `xml:"status,attr"`
	Code                       string   `xml:"code,attr"`
	Platform                   string   `xml:"result>system>platform-family"`
	Model                      string   `xml:"result>system>model"`
	Serial                     string   `xml:"result>system>serial"`
	SoftwareVersion            string   `xml:"result>system>sw-version"`
	IPAddress                  string   `xml:"result>system>ip-address"`
	Netmask                    string   `xml:"result>system>netmask"`
	DefaultGateway             string   `xml:"result>system>default-gateway"`
	MACAddress                 string   `xml:"result>system>mac-address"`
	Time                       string   `xml:"result>system>time"`
	Uptime                     string   `xml:"result>system>uptime"`
	GPClientPackageVersion     string   `xml:"result>system>global-protect-client-package-version"`
	GPDatafileVersion          string   `xml:"result>system>global-protect-datafile-version"`
	GPDatafileReleaseDate      string   `xml:"result>system>global-protect-datafile-release-date"`
	GPClientlessVPNVersion     string   `xml:"result>system>global-protect-clientless-vpn-version"`
	GPClientlessVPNReleaseDate string   `xml:"result>system>global-protect-clientless-vpn-release-date"`
	AppVersion                 string   `xml:"result>system>app-version"`
	AppReleaseDate             string   `xml:"result>system>app-release-date"`
	AntiVirusVersion           string   `xml:"result>system>av-version"`
	AntiVirusReleaseDate       string   `xml:"result>system>av-release-date"`
	ThreatVersion              string   `xml:"result>system>threat-version"`
	ThreatReleaseDate          string   `xml:"result>system>threat-release-date"`
	WildfireVersion            string   `xml:"result>system>wildfire-version"`
	WildfireReleaseDate        string   `xml:"result>system>wildfire-release-date"`
	URLDB                      string   `xml:"result>system>url-db"`
	URLFilteringVersion        string   `xml:"result>system>url-filtering-version"`
	LogDBVersion               string   `xml:"result>system>logdb-version"`
	MultiVsys                  string   `xml:"result>system>multi-vsys"`
	OperationalMode            string   `xml:"result>system>operational-mode"`
}
type commandOutput struct {
	XMLName xml.Name `xml:"response"`
	Status  string   `xml:"status,attr"`
	Code    string   `xml:"code,attr"`
	Data    string   `xml:"result"`
}
type requestError struct {
	XMLName xml.Name `xml:"response"`
	Status  string   `xml:"status,attr"`
	Code    string   `xml:"code,attr"`
	Message string   `xml:"result>msg,omitempty"`
}
type testURL struct {
	XMLName xml.Name `xml:"response"`
	Status  string   `xml:"status,attr"`
	Code    string   `xml:"code,attr"`
	Result  string   `xml:"result"`
}
type logID struct {
	XMLName xml.Name `xml:"response"`
	Status  string   `xml:"status,attr"`
	Code    string   `xml:"code,attr"`
	ID      int      `xml:"result>job"`
}
type routeLookupResults struct {
	XMLName   xml.Name `xml:"response"`
	Status    string   `xml:"status,attr"`
	Code      string   `xml:"code,attr"`
	NextHop   string   `xml:"result>nh"`
	Source    string   `xml:"result>src"`
	IP        string   `xml:"result>ip"`
	Metric    int      `xml:"result>metric"`
	Interface string   `xml:"result>interface"`
	DataPlane string   `xml:"result>dp"`
}
type RouteLookup struct {
	NextHop   string
	Source    string
	IP        string
	Metric    int
	Interface string
	DataPlane string
}
type SessionTable struct {
	XMLName  xml.Name  `xml:"response"`
	Status   string    `xml:"status,attr"`
	Code     string    `xml:"code,attr"`
	Sessions []Session `xml:"result>entry"`
}
type Session struct {
	Application           string `xml:"application"`
	IngressInterface      string `xml:"ingress"`
	EgressInterface       string `xml:"egress"`
	VsysID                int    `xml:"vsys-idx"`
	NATSourceAddress      string `xml:"xsource"`
	SourceNAT             string `xml:"srcnat"`
	SourcePort            int    `xml:"sport"`
	SecurityRule          string `xml:"security-rule"`
	From                  string `xml:"from"`
	Protocol              int    `xml:"proto"`
	DestinationAddress    string `xml:"dst"`
	To                    string `xml:"to"`
	State                 string `xml:"state"`
	NATDestinationAddress string `xml:"xdst"`
	NAT                   string `xml:"nat"`
	Type                  string `xml:"type"`
	StartTime             string `xml:"start-time"`
	Proxy                 string `xml:"proxy"`
	DecryptMirror         string `xml:"decrypt-mirror"`
	ID                    int    `xml:"idx"`
	TotalByteCount        int    `xml:"total-byte-count"`
	DestinationNAT        string `xml:"dstnat"`
	Vsys                  string `xml:"vsys"`
	NATSourcePort         int    `xml:"xsport"`
	NATDestinationPort    int    `xml:"xdport"`
	Flags                 string `xml:"flags,omitempty"`
	SourceAddress         string `xml:"source"`
	DestinationPort       int    `xml:"dport"`
}
type allApplications struct {
	XMLName      xml.Name      `xml:"response"`
	Status       string        `xml:"status,attr"`
	Code         string        `xml:"code,attr"`
	Applications []Application `xml:"result>application>entry"`
}
type singleApplication struct {
	XMLName      xml.Name      `xml:"response"`
	Status       string        `xml:"status,attr"`
	Code         string        `xml:"code,attr"`
	Applications []Application `xml:"result>entry"`
}
type ApplicationInformation struct {
	Applications []Application
}
type Application struct {
	ID                      string                  `xml:"id,attr"`
	Name                    string                  `xml:"name,attr"`
	OriginCountry           string                  `xml:"ori_country,attr"`
	OriginLanguage          string                  `xml:"ori_language,attr"`
	Category                string                  `xml:"category"`
	Subcategory             string                  `xml:"subcategory"`
	Technology              string                  `xml:"technology"`
	VirusIdent              string                  `xml:"virus-ident"`
	FileTypeIdent           string                  `xml:"file-type-ident"`
	TunnelOtherApplications string                  `xml:"tunnel-other-applications"`
	DataIdent               string                  `xml:"data-ident"`
	FileForward             string                  `xml:"file-forward"`
	IsSAAS                  string                  `xml:"is-saas"`
	EvasiveBehavior         string                  `xml:"evasive-behavior"`
	ConsumeBigBandwidth     string                  `xml:"consume-big-bandwidth"`
	UsedByMalware           string                  `xml:"used-by-malware"`
	AbleToTransferFile      string                  `xml:"able-to-transfer-file"`
	HasKnownVulnerability   string                  `xml:"has-known-vulnerability"`
	ProneToMisuse           string                  `xml:"prone-to-misuse"`
	PervasiveUse            string                  `xml:"pervasive-use"`
	References              []ApplicationReferences `xml:"references>entry"`
	DefaultPort             []string                `xml:"default>port>member"`
	UseApplications         []string                `xml:"use-applications>member"`
	ImplicitUseApplications []string                `xml:"implicit-use-applications>member"`
	Risk                    int                     `xml:"risk"`
}
type ApplicationReferences struct {
	Name string `xml:"name,attr"`
	Link string `xml:"link"`
}
type SessionID struct {
	XMLName xml.Name      `xml:"response"`
	Status  string        `xml:"status,attr"`
	Code    string        `xml:"code,attr"`
	Session SingleSession `xml:"result"`
}
type SingleSession struct {
	ProxySession        string `xml:"prxy-session"`
	C2SPackets          int    `xml:"c2s-packets"`
	FirewallEndReason   string `xml:"firewall"`
	ProxyStatus         string `xml:"prxy-status"`
	URLFilteringEnabled string `xml:"url-en"`
	SYNCookies          string `xml:"syncookie"`
	NATRule             string `xml:"nat-rule"`
	QoSClass            int    `xml:"qos-clas"`
	NATDestination      string `xml:"nat-dst"`
	S2CPackets          int    `xml:"s2c-packets"`
	Slot                int    `xml:"slot"`
	AppInsufficient     string `xml:"app-insufficient"`
	ProxyStarted        string `xml:"prxy-started"`
	CaptivePortal       string `xml:"captive-portal"`
	Application         string `xml:"application"`
	NATSource           string `xml:"nat-src"`
	FlowType            int    `xml:"flow-type"`
	EndReason           string `xml:"end-reason"`
	Timestamp           int    `xml:"timestamp"`
	URLCategory         string `xml:"url-cat"`
	SessionHASync       string `xml:"sess-ha-sync"`
	TunnelSession       string `xml:"tunnel-session"`
	HostSession         string `xml:"host-session"`
	C2SOctets           int    `xml:"c2s-octets"`
	SessionEndLog       string `xml:"sess-log"`
	StartTime           string `xml:"start-time"`
	S2COctets           int    `xml:"s2c-octets"`
	EgressInterface     string `xml:"egr-if"`
	NATRuleVsys         string `xml:"nat-rule-vsys"`
	Vsys                string `xml:"vsys"`
	Rule                string `xml:"rule"`
	SessionAger         string `xml:"sess-ager"`
	TimeStart           int    `xml:"time-start"`
	Timeout             int    `xml:"timeout"`
	QoSRule             string `xml:"qos-rule"`
	IngressInterface    string `xml:"igr-if"`
	DataplaneCPU        int    `xml:"cpu"`
	C2SSrcUser          string `xml:"c2s>src-user"`
	C2SProtocol         int    `xml:"c2s>proto"`
	C2SDestAddress      string `xml:"c2s>dst"`
	C2SDestUser         string `xml:"c2s>dst-user"`
	C2SSourceAddress    string `xml:"c2s>source"`
	C2SState            string `xml:"c2s>state"`
	C2SFrom             string `xml:"c2s>source-zone"`
	C2SIPVersion        int    `xml:"c2s>ipver"`
	C2SDestPort         int    `xml:"c2s>dport"`
	C2SSourcePort       int    `xml:"c2s>sport"`
	C2SType             string `xml:"c2s>type"`
	S2CSrcUser          string `xml:"s2c>src-user"`
	S2CProtocol         int    `xml:"s2c>proto"`
	S2CDestAddress      string `xml:"s2c>dst"`
	S2CDestUser         string `xml:"s2c>dst-user"`
	S2CSourceAddress    string `xml:"s2c>source"`
	S2CState            string `xml:"s2c>state"`
	S2CFrom             string `xml:"s2c>source-zone"`
	S2CIPVersion        int    `xml:"s2c>ipver"`
	S2CDestPort         int    `xml:"s2c>dport"`
	S2CSourcePort       int    `xml:"s2c>sport"`
	S2CType             string `xml:"s2c>type"`
}
var (
	r = gorequest.New().TLSClientConfig(&tls.Config{InsecureSkipVerify: true})
	errorCodes = map[string]string{
		"400": "Bad request - Returned when a required parameter is missing, an illegal parameter value is used",
		"403": "Forbidden - Returned for authentication or authorization errors including invalid key, insufficient admin access rights",
		"1":   "Unknown command - The specific config or operational command is not recognized",
		"2":   "Internal error - Check with technical support when seeing these errors",
		"3":   "Internal error - Check with technical support when seeing these errors",
		"4":   "Internal error - Check with technical support when seeing these errors",
		"5":   "Internal error - Check with technical support when seeing these errors",
		"6":   "Bad Xpath - The xpath specified in one or more attributes of the command is invalid. Check the API browser for proper xpath values",
		"7":   "Object not present - Object specified by the xpath is not present. For example, entry[@name=’value’] where no object with name ‘value’ is present",
		"8":   "Object not unique - For commands that operate on a single object, the specified object is not unique",
		"9":   "Internal error - Check with technical support when seeing these errors",
		"10":  "Reference count not zero - Object cannot be deleted as there are other objects that refer to it. For example, address object still in use in policy",
		"11":  "Internal error - Check with technical support when seeing these errors",
		"12":  "Invalid object - Xpath or element values provided are not complete",
		"13":  "Operation failed - A descriptive error message is returned in the response",
		"14":  "Operation not possible - Operation is not possible. For example, moving a rule up one position when it is already at the top",
		"15":  "Operation denied - For example, Admin not allowed to delete own account, Running a command that is not allowed on a passive device",
		"16":  "Unauthorized - The API role does not have access rights to run this query",
		"17":  "Invalid command - Invalid command or parameters",
		"18":  "Malformed command - The XML is malformed",
		"19":  "Success - Command completed successfully",
		"20":  "Success - Command completed successfully",
		"21":  "Internal error - Check with technical support when seeing these errors",
		"22":  "Session timed out - The session for this query timed out",
	}
)
func splitSWVersion(version string) []int {
	re := regexp.MustCompile(`(\d+)\.(\d+)\.(\d+)`)
	match := re.FindStringSubmatch(version)
	maj, _ := strconv.Atoi(match[1])
	min, _ := strconv.Atoi(match[2])
	rel, _ := strconv.Atoi(match[3])
	return []int{maj, min, rel}
}
func sliceToString(slice []string) string {
	var str string
	for _, item := range slice {
		str += fmt.Sprintf("%s, ", item)
	}
	return strings.TrimRight(str, ", ")
}
func stringToSlice(str string) []string {
	var slice []string
	list := strings.Split(str, ",")
	for _, item := range list {
		slice = append(slice, strings.TrimSpace(item))
	}
	return slice
}
func NewSession(host string, authmethod *AuthMethod) (*PaloAlto, error) {
	var keygen authKey
	var key string
	var info systemInfo
	var pan commandOutput
	status := false
	deviceType := "panos"
	if len(authmethod.Credentials) > 0 {
		_, body, errs := r.Get(fmt.Sprintf("https://%s/api/?type=keygen&user=%s&password=%s", host, authmethod.Credentials[0], authmethod.Credentials[1])).End()
		if errs != nil {
			return nil, fmt.Errorf("unable to connect to %s - %s", host, errs[0])
		}
		err := xml.Unmarshal([]byte(body), &keygen)
		if err != nil {
			return nil, err
		}
		if keygen.Status != "success" {
			return nil, fmt.Errorf("error code %s: %s (keygen)", keygen.Code, errorCodes[keygen.Code])
		}
		key = keygen.Key
	}
	if len(authmethod.APIKey) > 0 {
		key = authmethod.APIKey
	}
	uri := fmt.Sprintf("https://%s/api/?", host)
	_, getInfo, errs := r.Get(fmt.Sprintf("%s&key=%s&type=op&cmd=<show><system><info></info></system></show>", uri, key)).End()
	if errs != nil {
		return nil, fmt.Errorf("unable to get system info for %s - %s", host, errs[0])
	}
	err := xml.Unmarshal([]byte(getInfo), &info)
	if err != nil {
		return nil, err
	}
	if info.Status != "success" {
		return nil, fmt.Errorf("error code %s: %s (show system info)", info.Code, errorCodes[info.Code])
	}
	_, panStatus, errs := r.Get(fmt.Sprintf("%s&key=%s&type=op&cmd=<show><panorama-status></panorama-status></show>", uri, key)).End()
	if errs != nil {
		return nil, fmt.Errorf("unable to get Panorama status for %s - %s", host, errs[0])
	}
	err = xml.Unmarshal([]byte(panStatus), &pan)
	if err != nil {
		return nil, err
	}
	if info.Platform == "m" || info.Model == "Panorama" {
		deviceType = "panorama"
	}
	if strings.Contains(pan.Data, ": yes") {
		status = true
	}
	return &PaloAlto{
		Host:                       host,
		Key:                        key,
		URI:                        fmt.Sprintf("https://%s/api/?", host),
		Platform:                   info.Platform,
		Model:                      info.Model,
		Serial:                     info.Serial,
		SoftwareVersion:            info.SoftwareVersion,
		DeviceType:                 deviceType,
		Panorama:                   status,
		Shared:                     false,
		IPAddress:                  info.IPAddress,
		Netmask:                    info.Netmask,
		DefaultGateway:             info.DefaultGateway,
		MACAddress:                 info.MACAddress,
		Time:                       strings.Trim(info.Time, "[\r\n]"),
		Uptime:                     info.Uptime,
		GPClientPackageVersion:     info.GPClientPackageVersion,
		GPDatafileVersion:          info.GPDatafileVersion,
		GPDatafileReleaseDate:      info.GPDatafileReleaseDate,
		GPClientlessVPNVersion:     info.GPClientlessVPNVersion,
		GPClientlessVPNReleaseDate: info.GPClientlessVPNReleaseDate,
		AppVersion:                 info.AppVersion,
		AppReleaseDate:             info.AppReleaseDate,
		AntiVirusVersion:           info.AntiVirusVersion,
		AntiVirusReleaseDate:       info.AntiVirusReleaseDate,
		ThreatVersion:              info.ThreatVersion,
		ThreatReleaseDate:          info.ThreatReleaseDate,
		WildfireVersion:            info.WildfireVersion,
		WildfireReleaseDate:        info.WildfireReleaseDate,
		URLDB:                      info.URLDB,
		URLFilteringVersion:        info.URLFilteringVersion,
		LogDBVersion:               info.LogDBVersion,
		MultiVsys:                  info.MultiVsys,
		OperationalMode:            info.OperationalMode,
	}, nil
}
func (p *PaloAlto) Commit() error {
	var reqError requestError
	_, resp, errs := r.Get(p.URI).Query(fmt.Sprintf("type=commit&cmd=<commit></commit>&key=%s", p.Key)).End()
	if errs != nil {
		return errs[0]
	}
	if err := xml.Unmarshal([]byte(resp), &reqError); err != nil {
		return err
	}
	if reqError.Status != "success" {
		return fmt.Errorf("error code %s: %s", reqError.Code, errorCodes[reqError.Code])
	}
	return nil
}
func (p *PaloAlto) CommitAll(devicegroup string, devices ...string) error {
	var reqError requestError
	var cmd string
	if p.DeviceType == "panorama" && len(devices) <= 0 {
		cmd = fmt.Sprintf("<commit-all><shared-policy><device-group><entry name=\"%s\"/></device-group></shared-policy></commit-all>", devicegroup)
	}
	if p.DeviceType == "panorama" && len(devices) > 0 {
		cmd = fmt.Sprintf("<commit-all><shared-policy><device-group><entry name=\"%s\"/>><devices>", devicegroup)
		for _, d := range devices {
			cmd += fmt.Sprintf("<entry name=\"%s\"/>", d)
		}
		cmd += "</devices></entry></device-group></shared-policy></commit-all>"
	}
	_, resp, errs := r.Get(p.URI).Query(fmt.Sprintf("type=commit&action=all&cmd=%s&key=%s", cmd, p.Key)).End()
	if errs != nil {
		return errs[0]
	}
	if err := xml.Unmarshal([]byte(resp), &reqError); err != nil {
		return err
	}
	if reqError.Status != "success" {
		return fmt.Errorf("error code %s: %s", reqError.Code, errorCodes[reqError.Code])
	}
	return nil
}