2018-05-09 08:05:17 -05:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace App\Models;
|
|
|
|
|
2018-09-24 02:07:00 -05:00
|
|
|
use DB;
|
2018-07-30 16:58:38 -05:00
|
|
|
use Fico7489\Laravel\Pivot\Traits\PivotEventTrait;
|
|
|
|
use Illuminate\Database\Eloquent\Builder;
|
2018-09-21 10:08:17 -05:00
|
|
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
2018-07-30 16:58:38 -05:00
|
|
|
use Illuminate\Database\Query\JoinClause;
|
2018-08-11 23:37:45 +02:00
|
|
|
use LibreNMS\Exceptions\InvalidIpException;
|
2018-08-14 01:56:16 -05:00
|
|
|
use LibreNMS\Util\IP;
|
2018-08-11 23:37:45 +02:00
|
|
|
use LibreNMS\Util\IPv4;
|
|
|
|
use LibreNMS\Util\IPv6;
|
2018-07-30 16:58:38 -05:00
|
|
|
|
2018-05-09 08:05:17 -05:00
|
|
|
class Device extends BaseModel
|
|
|
|
{
|
2018-07-30 16:58:38 -05:00
|
|
|
use PivotEventTrait;
|
|
|
|
|
2018-05-09 08:05:17 -05:00
|
|
|
public $timestamps = false;
|
|
|
|
protected $primaryKey = 'device_id';
|
|
|
|
protected $fillable = ['hostname', 'ip', 'status', 'status_reason'];
|
2018-07-30 16:58:38 -05:00
|
|
|
protected $casts = ['status' => 'boolean'];
|
2018-05-09 08:05:17 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize this class
|
|
|
|
*/
|
|
|
|
public static function boot()
|
|
|
|
{
|
|
|
|
parent::boot();
|
|
|
|
|
|
|
|
static::deleting(function (Device $device) {
|
|
|
|
// delete related data
|
|
|
|
$device->ports()->delete();
|
|
|
|
$device->syslogs()->delete();
|
|
|
|
$device->eventlogs()->delete();
|
2018-07-30 16:58:38 -05:00
|
|
|
|
|
|
|
// handle device dependency updates
|
|
|
|
$device->children->each->updateMaxDepth($device->device_id);
|
|
|
|
});
|
|
|
|
|
|
|
|
// handle device dependency updates
|
|
|
|
static::updated(function (Device $device) {
|
|
|
|
if ($device->isDirty('max_depth')) {
|
|
|
|
$device->children->each->updateMaxDepth();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
static::pivotAttached(function (Device $device, $relationName, $pivotIds, $pivotIdsAttributes) {
|
|
|
|
if ($relationName == 'parents') {
|
|
|
|
// a parent attached to this device
|
|
|
|
|
|
|
|
// update the parent's max depth incase it used to be standalone
|
|
|
|
Device::whereIn('device_id', $pivotIds)->get()->each->validateStandalone();
|
|
|
|
|
|
|
|
// make sure this device's max depth is updated
|
|
|
|
$device->updateMaxDepth();
|
|
|
|
} elseif ($relationName == 'children') {
|
|
|
|
// a child device attached to this device
|
|
|
|
|
|
|
|
// if this device used to be standalone, we need to udpate max depth
|
|
|
|
$device->validateStandalone();
|
|
|
|
|
|
|
|
// make sure the child's max depth is updated
|
|
|
|
Device::whereIn('device_id', $pivotIds)->get()->each->updateMaxDepth();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
static::pivotDetached(function (Device $device, $relationName, $pivotIds) {
|
|
|
|
if ($relationName == 'parents') {
|
|
|
|
// this device detached from a parent
|
|
|
|
|
|
|
|
// update this devices max depth
|
|
|
|
$device->updateMaxDepth();
|
|
|
|
|
|
|
|
// parent may now be standalone, update old parent
|
|
|
|
Device::whereIn('device_id', $pivotIds)->get()->each->validateStandalone();
|
|
|
|
} elseif ($relationName == 'children') {
|
|
|
|
// a child device detached from this device
|
|
|
|
|
|
|
|
// update the detached child's max_depth
|
|
|
|
Device::whereIn('device_id', $pivotIds)->get()->each->updateMaxDepth();
|
|
|
|
|
|
|
|
// this device may be standalone, update it
|
|
|
|
$device->validateStandalone();
|
|
|
|
}
|
2018-05-09 08:05:17 -05:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---- Helper Functions ----
|
|
|
|
|
2018-08-11 23:37:45 +02:00
|
|
|
public static function findByHostname($hostname)
|
|
|
|
{
|
|
|
|
return static::where('hostname', $hostname)->first();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function findByIp($ip)
|
|
|
|
{
|
2018-08-14 01:56:16 -05:00
|
|
|
if (!IP::isValid($ip)) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2018-08-11 23:37:45 +02:00
|
|
|
$device = static::where('hostname', $ip)->orWhere('ip', inet_pton($ip))->first();
|
|
|
|
|
|
|
|
if ($device) {
|
|
|
|
return $device;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
$ipv4 = new IPv4($ip);
|
2018-08-14 01:56:16 -05:00
|
|
|
$port = Ipv4Address::where('ipv4_address', (string) $ipv4)
|
2018-08-11 23:37:45 +02:00
|
|
|
->with('port', 'port.device')
|
2018-08-14 01:56:16 -05:00
|
|
|
->firstOrFail()->port;
|
|
|
|
if ($port) {
|
|
|
|
return $port->device;
|
|
|
|
}
|
2018-08-11 23:37:45 +02:00
|
|
|
} catch (InvalidIpException $e) {
|
|
|
|
//
|
|
|
|
} catch (ModelNotFoundException $e) {
|
|
|
|
//
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
$ipv6 = new IPv6($ip);
|
2018-08-14 01:56:16 -05:00
|
|
|
$port = Ipv6Address::where('ipv6_address', $ipv6->uncompressed())
|
2018-08-11 23:37:45 +02:00
|
|
|
->with(['port', 'port.device'])
|
2018-08-14 01:56:16 -05:00
|
|
|
->firstOrFail()->port;
|
|
|
|
if ($port) {
|
|
|
|
return $port->device;
|
|
|
|
}
|
2018-08-11 23:37:45 +02:00
|
|
|
} catch (InvalidIpException $e) {
|
|
|
|
//
|
|
|
|
} catch (ModelNotFoundException $e) {
|
|
|
|
//
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2018-09-11 07:51:35 -05:00
|
|
|
/**
|
|
|
|
* Get the display name of this device (hostname) unless force_ip_to_sysname is set
|
|
|
|
* and hostname is an IP and sysName is set
|
|
|
|
*
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function displayName()
|
|
|
|
{
|
2018-09-21 10:08:17 -05:00
|
|
|
if (\LibreNMS\Config::get('force_ip_to_sysname') && $this->sysName && IP::isValid($this->hostname)) {
|
2018-09-11 07:51:35 -05:00
|
|
|
return $this->sysName;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->hostname;
|
|
|
|
}
|
|
|
|
|
2018-09-20 15:33:03 -05:00
|
|
|
/**
|
|
|
|
* Get the shortened display name of this device.
|
|
|
|
* Length is always overridden by shorthost_target_length.
|
|
|
|
*
|
|
|
|
* @param int $length length to shorten to, will not break up words so may be longer
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function shortDisplayName($length = 12)
|
|
|
|
{
|
|
|
|
$name = $this->displayName();
|
|
|
|
|
|
|
|
// IP addresses should not be shortened
|
|
|
|
if (IP::isValid($name)) {
|
|
|
|
return $name;
|
|
|
|
}
|
|
|
|
|
2018-09-21 10:08:17 -05:00
|
|
|
$length = \LibreNMS\Config::get('shorthost_target_length', $length);
|
2018-09-20 15:33:03 -05:00
|
|
|
if ($length < strlen($name)) {
|
|
|
|
$take = substr_count($name, '.', 0, $length) + 1;
|
|
|
|
return implode('.', array_slice(explode('.', $name), 0, $take));
|
|
|
|
}
|
|
|
|
|
|
|
|
return $name;
|
|
|
|
}
|
|
|
|
|
2018-09-24 02:07:00 -05:00
|
|
|
/**
|
|
|
|
* Check if user can access this device.
|
|
|
|
*
|
|
|
|
* @param User $user
|
|
|
|
* @return bool
|
|
|
|
*/
|
|
|
|
public function canAccess($user)
|
|
|
|
{
|
|
|
|
if (!$user) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($user->hasGlobalRead()) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return DB::table('devices_perms')
|
|
|
|
->where('user_id', $user->user_id)
|
|
|
|
->where('device_id', $this->device_id)->exists();
|
|
|
|
}
|
|
|
|
|
2018-09-11 07:51:35 -05:00
|
|
|
public function formatUptime($short = false)
|
|
|
|
{
|
|
|
|
$result = '';
|
|
|
|
$interval = $this->uptime;
|
|
|
|
$data = [
|
|
|
|
'years' => 31536000,
|
|
|
|
'days' => 86400,
|
|
|
|
'hours' => 3600,
|
|
|
|
'minutes' => 60,
|
|
|
|
'seconds' => 1,
|
|
|
|
];
|
|
|
|
|
|
|
|
foreach ($data as $k => $v) {
|
|
|
|
if ($interval >= $v) {
|
|
|
|
$diff = floor($interval / $v);
|
|
|
|
|
|
|
|
$result .= " $diff";
|
|
|
|
if ($short) {
|
|
|
|
$result .= substr($k, 0, 1);
|
|
|
|
} elseif ($diff > 1) {
|
|
|
|
$result .= $k;
|
|
|
|
} else {
|
|
|
|
$result .= substr($k, 0, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
$interval -= $v * $diff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
2018-05-09 08:05:17 -05:00
|
|
|
/**
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
public function logo()
|
|
|
|
{
|
|
|
|
$base_name = pathinfo($this->icon, PATHINFO_FILENAME);
|
|
|
|
$options = [
|
|
|
|
"images/logos/$base_name.svg",
|
|
|
|
"images/logos/$base_name.png",
|
|
|
|
"images/os/$base_name.svg",
|
|
|
|
"images/os/$base_name.png",
|
|
|
|
];
|
|
|
|
|
|
|
|
foreach ($options as $file) {
|
|
|
|
if (is_file(public_path()."/$file")) {
|
|
|
|
return asset($file);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return asset('images/os/generic.svg');
|
|
|
|
}
|
|
|
|
|
2018-12-16 15:18:17 -06:00
|
|
|
/**
|
|
|
|
* Get list of enabled graphs for this device.
|
|
|
|
*
|
|
|
|
* @return \Illuminate\Support\Collection
|
|
|
|
*/
|
|
|
|
public function graphs()
|
|
|
|
{
|
|
|
|
return DB::table('device_graphs')
|
|
|
|
->where('device_id', $this->device_id)
|
|
|
|
->pluck('graph');
|
|
|
|
}
|
|
|
|
|
2018-07-30 16:58:38 -05:00
|
|
|
/**
|
|
|
|
* Update the max_depth field based on parents
|
|
|
|
* Performs SQL query, so make sure all parents are saved first
|
|
|
|
*
|
|
|
|
* @param int $exclude exclude a device_id from being considered (used for deleting)
|
|
|
|
*/
|
|
|
|
public function updateMaxDepth($exclude = null)
|
|
|
|
{
|
|
|
|
// optimize for memory instead of time
|
|
|
|
$query = $this->parents()->getQuery();
|
|
|
|
if (!is_null($exclude)) {
|
|
|
|
$query->where('device_id', '!=', $exclude);
|
|
|
|
}
|
|
|
|
|
|
|
|
$count = $query->count();
|
|
|
|
if ($count === 0) {
|
|
|
|
if ($this->children()->count() === 0) {
|
|
|
|
$this->max_depth = 0; // no children or parents
|
|
|
|
} else {
|
|
|
|
$this->max_depth = 1; // has children
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$parents_max_depth = $query->max('max_depth');
|
|
|
|
$this->max_depth = $parents_max_depth + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->save();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Device dependency check to see if this node is standalone or not.
|
|
|
|
* Standalone is a special case where the device has no parents or children and is denoted by a max_depth of 0
|
|
|
|
*
|
|
|
|
* Only checks on root nodes (where max_depth is 1 or 0)
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
public function validateStandalone()
|
|
|
|
{
|
|
|
|
if ($this->max_depth === 0 && $this->children()->count() > 0) {
|
|
|
|
$this->max_depth = 1; // has children
|
|
|
|
} elseif ($this->max_depth === 1 && $this->parents()->count() === 0) {
|
|
|
|
$this->max_depth = 0; // no children or parents
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->save();
|
|
|
|
}
|
|
|
|
|
2018-05-09 08:05:17 -05:00
|
|
|
/**
|
|
|
|
* @return string
|
|
|
|
*/
|
2018-12-16 15:18:17 -06:00
|
|
|
public function statusName()
|
2018-05-09 08:05:17 -05:00
|
|
|
{
|
2018-12-16 15:18:17 -06:00
|
|
|
if ($this->disabled == 1) {
|
|
|
|
return 'disabled';
|
|
|
|
} elseif ($this->ignore == 1) {
|
|
|
|
return 'ignore';
|
|
|
|
} elseif ($this->status == 0) {
|
|
|
|
return 'down';
|
2018-05-09 08:05:17 -05:00
|
|
|
} else {
|
2018-12-16 15:18:17 -06:00
|
|
|
$warning_time = \LibreNMS\Config::get('uptime_warning', 84600);
|
|
|
|
if ($this->uptime < $warning_time && $this->uptime != 0) {
|
|
|
|
return 'warn';
|
|
|
|
}
|
|
|
|
|
|
|
|
return 'up';
|
2018-05-09 08:05:17 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---- Accessors/Mutators ----
|
2018-09-11 07:51:35 -05:00
|
|
|
|
2018-05-09 08:05:17 -05:00
|
|
|
public function getIconAttribute($icon)
|
|
|
|
{
|
|
|
|
if (isset($icon)) {
|
2018-07-30 16:58:38 -05:00
|
|
|
return "images/os/$icon";
|
2018-05-09 08:05:17 -05:00
|
|
|
}
|
2018-07-30 16:58:38 -05:00
|
|
|
return 'images/os/generic.svg';
|
2018-05-09 08:05:17 -05:00
|
|
|
}
|
|
|
|
public function getIpAttribute($ip)
|
|
|
|
{
|
|
|
|
if (empty($ip)) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
// @ suppresses warning, inet_ntop() returns false if it fails
|
|
|
|
return @inet_ntop($ip) ?: null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setIpAttribute($ip)
|
|
|
|
{
|
|
|
|
$this->attributes['ip'] = inet_pton($ip);
|
|
|
|
}
|
|
|
|
|
2018-07-30 16:58:38 -05:00
|
|
|
public function setStatusAttribute($status)
|
|
|
|
{
|
|
|
|
$this->attributes['status'] = (int)$status;
|
|
|
|
}
|
|
|
|
|
2018-05-09 08:05:17 -05:00
|
|
|
// ---- Query scopes ----
|
|
|
|
|
|
|
|
public function scopeIsUp($query)
|
|
|
|
{
|
|
|
|
return $query->where([
|
|
|
|
['status', '=', 1],
|
|
|
|
['ignore', '=', 0],
|
|
|
|
['disabled', '=', 0]
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function scopeIsActive($query)
|
|
|
|
{
|
|
|
|
return $query->where([
|
|
|
|
['ignore', '=', 0],
|
|
|
|
['disabled', '=', 0]
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function scopeIsDown($query)
|
|
|
|
{
|
|
|
|
return $query->where([
|
|
|
|
['status', '=', 0],
|
|
|
|
['ignore', '=', 0],
|
|
|
|
['disabled', '=', 0]
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function scopeIsIgnored($query)
|
|
|
|
{
|
|
|
|
return $query->where([
|
|
|
|
['ignore', '=', 1],
|
|
|
|
['disabled', '=', 0]
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function scopeNotIgnored($query)
|
|
|
|
{
|
|
|
|
return $query->where([
|
|
|
|
['ignore', '=', 0]
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function scopeIsDisabled($query)
|
|
|
|
{
|
|
|
|
return $query->where([
|
|
|
|
['disabled', '=', 1]
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
2018-07-30 16:58:38 -05:00
|
|
|
public function scopeCanPing(Builder $query)
|
|
|
|
{
|
|
|
|
return $query->where('disabled', 0)
|
|
|
|
->leftJoin('devices_attribs', function (JoinClause $query) {
|
|
|
|
$query->on('devices.device_id', 'devices_attribs.device_id')
|
|
|
|
->where('devices_attribs.attrib_type', 'override_icmp_disable');
|
|
|
|
})
|
|
|
|
->where(function (Builder $query) {
|
|
|
|
$query->whereNull('devices_attribs.attrib_value')
|
|
|
|
->orWhere('devices_attribs.attrib_value', '!=', 'true');
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-05-09 08:05:17 -05:00
|
|
|
public function scopeHasAccess($query, User $user)
|
|
|
|
{
|
|
|
|
return $this->hasDeviceAccess($query, $user);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---- Define Relationships ----
|
|
|
|
|
|
|
|
public function alerts()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\Alert', 'device_id');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function applications()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\Application', 'device_id');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function bgppeers()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\BgpPeer', 'device_id');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function cefSwitching()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\CefSwitching', 'device_id');
|
|
|
|
}
|
|
|
|
|
2018-07-30 16:58:38 -05:00
|
|
|
public function children()
|
|
|
|
{
|
|
|
|
return $this->belongsToMany('App\Models\Device', 'device_relationships', 'parent_device_id', 'child_device_id');
|
|
|
|
}
|
|
|
|
|
2018-05-09 08:05:17 -05:00
|
|
|
public function components()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\Component', 'device_id');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function eventlogs()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\General\Eventlog', 'host', 'device_id');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function groups()
|
|
|
|
{
|
|
|
|
return $this->belongsToMany('App\Models\DeviceGroup', 'device_group_device', 'device_id', 'device_group_id');
|
|
|
|
}
|
|
|
|
|
Refactored and update Location Geocoding (#9359)
- Fix location so it is a regular database relation (this allows multiple devices to be accurately linked to one location and saves api calls)
- Parse coordinates from the location more consistently
- Add settings to webui
- ~~Used [PHP Geocoder](http://geocoder-php.org/), which has lots of backends and is well tested. (also includes reverse and geoip)~~
- Google Maps, Bing, Mapquest, and OpenStreetMap supported initially.
- Default to OpenStreetMap, which doesn't require a key. They will liberally hand out bans if you exceed 1 query per second though.
- All other Geocoding APIs require an API key. (Google requires a credit card on file, but seems to be the most accurate)
- Update all (I think) sql queries to handle the new structure
- Remove final vestiges of override_sysLocation as a device attribute
- Update existing device groups and rules in DB
- Tested all APIs with good/bad location, no/bad/good key, and no connection.
- Cannot fix advanced queries that use location
This blocks #8868
DO NOT DELETE THIS TEXT
#### Please note
> Please read this information carefully. You can run `./scripts/pre-commit.php` to check your code before submitting.
- [x] Have you followed our [code guidelines?](http://docs.librenms.org/Developing/Code-Guidelines/)
#### Testers
If you would like to test this pull request then please run: `./scripts/github-apply <pr_id>`, i.e `./scripts/github-apply 5926`
After you are done testing, you can remove the changes with `./scripts/github-remove`. If there are schema changes, you can ask on discord how to revert.
2018-11-28 16:49:18 -06:00
|
|
|
public function location()
|
|
|
|
{
|
|
|
|
return $this->belongsTo('App\Models\Location', 'location_id', 'id');
|
|
|
|
}
|
|
|
|
|
2018-05-09 08:05:17 -05:00
|
|
|
public function ospfInstances()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\OspfInstance', 'device_id');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function packages()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\Package', 'device_id', 'device_id');
|
|
|
|
}
|
|
|
|
|
2018-07-30 16:58:38 -05:00
|
|
|
public function parents()
|
|
|
|
{
|
|
|
|
return $this->belongsToMany('App\Models\Device', 'device_relationships', 'child_device_id', 'parent_device_id');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function perf()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\DevicePerf', 'device_id');
|
|
|
|
}
|
|
|
|
|
2018-05-09 08:05:17 -05:00
|
|
|
public function ports()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\Port', 'device_id', 'device_id');
|
|
|
|
}
|
|
|
|
|
2018-12-20 19:50:12 -06:00
|
|
|
public function portsNac()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\PortsNac', 'device_id', 'device_id');
|
|
|
|
}
|
|
|
|
|
2018-05-09 08:05:17 -05:00
|
|
|
public function processors()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\Processor', 'device_id');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function rules()
|
|
|
|
{
|
|
|
|
return $this->belongsToMany('App\Models\AlertRule', 'alert_device_map', 'device_id', 'rule_id');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function sensors()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\Sensor', 'device_id');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function services()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\Service', 'device_id');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function storage()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\Storage', 'device_id');
|
|
|
|
}
|
|
|
|
|
2018-05-19 00:36:06 -04:00
|
|
|
public function mempools()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\Mempool', 'device_id');
|
|
|
|
}
|
|
|
|
|
2018-05-09 08:05:17 -05:00
|
|
|
public function syslogs()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\General\Syslog', 'device_id', 'device_id');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function users()
|
|
|
|
{
|
|
|
|
// FIXME does not include global read
|
|
|
|
return $this->belongsToMany('App\Models\User', 'devices_perms', 'device_id', 'user_id');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function vrfs()
|
|
|
|
{
|
|
|
|
return $this->hasMany('App\Models\Vrf', 'device_id');
|
|
|
|
}
|
|
|
|
}
|