You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
879 lines
32 KiB
879 lines
32 KiB
# Copyright (C) 2005-2025 Splunk Inc. All Rights Reserved.
|
|
|
|
"""
|
|
Use this module to work with your Events in ITSI!
|
|
|
|
Due to dependency on a Splunk ITSI module, this module must reside on the same
|
|
host where ITSI is currently installed. Eventually, we will be moving to
|
|
consuming standard REST interfaces and then it should be OK to move this module
|
|
to a different host.
|
|
"""
|
|
import itsi_py3
|
|
import sys
|
|
import json
|
|
import time
|
|
from copy import deepcopy
|
|
|
|
from splunk.clilib.bundle_paths import make_splunkhome_path
|
|
|
|
from splunk import ResourceNotFound, RESTException
|
|
|
|
sys.path.append(make_splunkhome_path(['etc', 'apps', 'SA-ITOA', 'lib', 'ITOA']))
|
|
from ITOA.event_management.notable_event_tag import NotableEventTag
|
|
from ITOA.event_management.notable_event_comment import NotableEventComment
|
|
from ITOA.itoa_common import extract
|
|
from ITOA.event_management.notable_event_ticketing import ExternalTicket
|
|
|
|
sys.path.append(make_splunkhome_path(['etc', 'apps', 'SA-ITOA', 'lib', 'itsi', 'event_management']))
|
|
from itsi_notable_event_group import ItsiNotableEventGroup
|
|
|
|
from .eventing_base import EventBase
|
|
from .eventing import EventMeta
|
|
|
|
########
|
|
# Setup a default Logger
|
|
########
|
|
from ITOA.setup_logging import logger
|
|
|
|
########
|
|
# APIs
|
|
########
|
|
|
|
|
|
class GroupMeta(EventMeta):
|
|
"""
|
|
Import this class to get information about ITSI Episodes.
|
|
- What are all the available status values I can set on an Episode?
|
|
- What are all the available owners I can have for an Episode?
|
|
- What are all the available severities I can set on an Episode?
|
|
|
|
Usage:
|
|
>>> meta = GroupMeta(session_key) # or
|
|
>>> meta = GroupMeta(None, username, password)
|
|
|
|
Provide your own logger if you want to, else we'll default to default_logger
|
|
"""
|
|
pass
|
|
|
|
|
|
class EventGroup(EventBase):
|
|
"""
|
|
Import this class to operate on ITSI Event Group.
|
|
"""
|
|
def __init__(self, session_key, username=None, password=None, logger=logger):
|
|
"""
|
|
@type session_key: string
|
|
@param session_key: session key given by Splunkd when you log in
|
|
If you dont have one, pass in None. But you will have to provide
|
|
credentials
|
|
|
|
@type username: string
|
|
@param username: your username
|
|
|
|
@type password: string
|
|
@param password: your password
|
|
|
|
@type logger: object of type logger
|
|
@param logger: if you have an existing logger, pass it in, we'll log
|
|
stuff there...else check ITSI logs
|
|
"""
|
|
super(EventGroup, self).__init__(session_key, username, password, logger)
|
|
self.group = ItsiNotableEventGroup(self.session_key, action_dispatch_config=self.action_dispatch_config)
|
|
|
|
def _get_from_index(self, group_ids, split_by="," , **kwargs):
|
|
"""
|
|
given an id or list of ids, return a dictionary of pertinent fields
|
|
for that group. This method runs a Splunk search.
|
|
|
|
@type group_id: str
|
|
@param group_id: a unique id for a group
|
|
|
|
@type split_by: str
|
|
@param split_by: if group_ids is of type basestring, we will split it
|
|
into many group ids into a list. What is the separator? Defaults to `,`
|
|
|
|
@type kwargs: dict
|
|
@param kwargs: send in keys `earliest_time` and
|
|
`latest_time` with corresponding values if you know what you are doing.
|
|
Ex:
|
|
'-15m' implies '15 mins ago'
|
|
'-15s' implies '15 seconds ago'
|
|
'-15d' implies '15 days ago'
|
|
'-15w' implies '15 weeks ago'
|
|
'rt' implies real time
|
|
'now' implies current time
|
|
no other values are supported
|
|
|
|
@return a valid Dict if event is found; None if no resource is found
|
|
"""
|
|
if isinstance(group_ids, itsi_py3.string_type):
|
|
group_ids = group_ids.split(',')
|
|
|
|
if not isinstance(group_ids, list):
|
|
raise TypeError('Expecting group_ids to be a string or list')
|
|
|
|
# we only care about `earliest_time` and `latest_time`. get rid of other
|
|
# keys
|
|
supported_params = ('earliest_time', 'latest_time')
|
|
for i in list(kwargs.keys()):
|
|
kwargs.pop(i) if i not in supported_params else None
|
|
|
|
objects = None
|
|
|
|
# indexing takes time and just because we have a group_id does not
|
|
# really means that event has been indexed. we shall therefore
|
|
# retry..yes, 10 times.
|
|
retries = 10
|
|
while retries:
|
|
time.sleep(5)
|
|
try:
|
|
objects = self.group.get_bulk(group_ids)
|
|
if objects:
|
|
break
|
|
retries -= 1
|
|
except ResourceNotFound:
|
|
self.logger.exception('Unable to find group_id: %s', group_ids)
|
|
break
|
|
except Exception:
|
|
self.logger.exception('Internal Error.')
|
|
break
|
|
return objects
|
|
|
|
def get_severity(self, group_ids=None, split_by=",", **kwargs):
|
|
"""
|
|
given a list of group ids, return their severities
|
|
|
|
@type group_ids: str or list
|
|
@param group_ids: a unique id for a group or a list of them
|
|
|
|
@type split_by: str
|
|
@param split_by: if `group_ids` is of type basestring, we will split it
|
|
into many group ids; into a list. What is the separator? Defaults to `,`
|
|
|
|
@type kwargs: dict
|
|
@param kwargs: send in keys `earliest_time` and
|
|
`latest_time` with corresponding values if you know what you are doing.
|
|
Ex:
|
|
'-15m' implies '15 mins ago'
|
|
'-15s' implies '15 seconds ago'
|
|
'-15d' implies '15 days ago'
|
|
'-15w' implies '15 weeks ago'
|
|
'rt' implies real time
|
|
'now' implies current time
|
|
no other values are supported
|
|
|
|
@return a list of tuples (group_id: severity) on valid request
|
|
None on invalid request.
|
|
"""
|
|
# validate + normalize
|
|
if not group_ids:
|
|
raise ValueError('Expecting `group_ids`.')
|
|
|
|
if isinstance(group_ids, itsi_py3.string_type):
|
|
group_ids = group_ids.split(split_by)
|
|
if not isinstance(group_ids, list):
|
|
return None
|
|
groups = self._get_from_index(group_ids, kwargs)
|
|
if not groups:
|
|
return None
|
|
|
|
severities = extract(groups, 'severity', False)
|
|
return list(zip(group_ids, severities))
|
|
|
|
def get_status(self, group_ids=None, split_by=",", **kwargs):
|
|
"""
|
|
given a list of group ids, return their statuses
|
|
|
|
@type group_ids: basestring/list
|
|
@param group_ids: a unique id for a group or a list of them
|
|
|
|
@type split_by: str
|
|
@param split_by: if `group_ids` is of type basestring, we will split it
|
|
into many event ids; into a list. What is the separator? Defaults to `,`
|
|
|
|
@type kwargs: dict
|
|
@param kwargs: send in keys `earliest_time` and
|
|
`latest_time` with corresponding values if you know what you are doing.
|
|
Ex:
|
|
'-15m' implies '15 mins ago'
|
|
'-15s' implies '15 seconds ago'
|
|
'-15d' implies '15 days ago'
|
|
'-15w' implies '15 weeks ago'
|
|
'rt' implies real time
|
|
'now' implies current time
|
|
no other values are supported
|
|
|
|
@return a list of tuples (group_id: severity) on valid request
|
|
None on an invalid request
|
|
"""
|
|
# validate + normalize
|
|
if not group_ids:
|
|
raise ValueError('Expecting `group_ids`.')
|
|
|
|
if isinstance(group_ids, itsi_py3.string_type):
|
|
group_ids = group_ids.split(split_by)
|
|
if not isinstance(group_ids, list):
|
|
return None
|
|
groups = self._get_from_index(group_ids, kwargs)
|
|
if not groups:
|
|
return None
|
|
|
|
statuses = extract(groups, 'status', False)
|
|
return list(zip(group_ids, statuses))
|
|
|
|
def get_owner(self, group_ids=None, split_by=",", **kwargs):
|
|
"""
|
|
given an group id, return its owner
|
|
|
|
@type group_ids: basestring/list
|
|
@param group_ids: a unique id for a group or a list of them
|
|
|
|
@type split_by: str
|
|
@param split_by: if `group_ids` is of type basestring, we will split it
|
|
into many group ids; into a list. What is the separator? Defaults to `,`
|
|
|
|
@type kwargs: dict
|
|
@param kwargs: send in keys `earliest_time` and
|
|
`latest_time` with corresponding values if you know what you are doing.
|
|
Ex:
|
|
'-15m' implies '15 mins ago'
|
|
'-15s' implies '15 seconds ago'
|
|
'-15d' implies '15 days ago'
|
|
'-15w' implies '15 weeks ago'
|
|
'rt' implies real time
|
|
'now' implies current time
|
|
no other values are supported
|
|
|
|
@rtype: list of tuples
|
|
@return: [(group_id, owner)] if valid. None if invalid.
|
|
"""
|
|
# validate + normalize
|
|
if not group_ids:
|
|
raise ValueError('Expecting `group_ids`.')
|
|
|
|
if isinstance(group_ids, itsi_py3.string_type):
|
|
group_ids = group_ids.split(split_by)
|
|
if not isinstance(group_ids, list):
|
|
return None
|
|
groups = self._get_from_index(group_ids, kwargs)
|
|
if not groups:
|
|
return None
|
|
|
|
# extract owners now that we have events...
|
|
owners = extract(groups, 'owner', False)
|
|
return list(zip(group_ids, owners))
|
|
|
|
def add_drilldown(self, group_id, drilldown):
|
|
"""
|
|
Adds drilldown to a notable event group.
|
|
@type group_id: string
|
|
@param group_id: id of the group where add_drilldown to be operated on
|
|
|
|
@type drilldown: string
|
|
@param drilldown: The drilldown data that wanted to be add to
|
|
{
|
|
'name': "DrilldownName",
|
|
'link': "http://drill.down"
|
|
}
|
|
"""
|
|
return self.group.add_drilldown(group_id, drilldown)
|
|
|
|
def update_drilldown(self, group_id, drilldown):
|
|
"""
|
|
Update a drilldown for a NotableEventGroup
|
|
|
|
@type group_id: string
|
|
@param group_id: id of the group who owns the drilldown to be updated
|
|
|
|
@type drilldown: dict
|
|
@param drilldown: drilldown to be updated
|
|
"""
|
|
return self.group.update_drilldown(group_id, drilldown)
|
|
|
|
def delete_drilldown(self, group_id, drilldown):
|
|
"""
|
|
Delete a drilldown for a NotableEventGroup
|
|
|
|
@type group_id: string
|
|
@param group_id: id of the group who owns the drilldown to be deleted
|
|
|
|
@type drilldown: dict
|
|
@param drilldown: drilldown to be deleted
|
|
"""
|
|
return self.group.delete_drilldown(group_id, drilldown)
|
|
|
|
def create_tag(self, group_id, tag_value, policy_id=None, raise_exceptions=False):
|
|
"""
|
|
create a tag for given group_id
|
|
|
|
@type event_id: str
|
|
@param group_id: id of a group
|
|
|
|
@type tag_value: str
|
|
@param tag_value: new value of this tag
|
|
|
|
@type policy_id: basestring
|
|
@param policy_id: policy id of the group
|
|
|
|
@rtype: dict
|
|
@return a nicely formatted dictionary/None on failure.
|
|
"""
|
|
if not isinstance(group_id, itsi_py3.string_type):
|
|
raise TypeError('Expecting `group_id` to be non-empty basestring. Received: %s' % group_id)
|
|
if not isinstance(tag_value, itsi_py3.string_type):
|
|
raise TypeError('Expecting `tag_value` to be non-empty basestring. Received: %s' % tag_value)
|
|
|
|
obj = NotableEventTag(self.session_key)
|
|
data = {
|
|
'event_id': group_id,
|
|
'tag_name': tag_value,
|
|
'itsi_policy_id': policy_id
|
|
}
|
|
|
|
try:
|
|
tag_id = obj.create(data)
|
|
except RESTException as e:
|
|
if e.statusCode == 409 and not raise_exceptions:
|
|
return None
|
|
else:
|
|
raise
|
|
|
|
if any([
|
|
not isinstance(tag_id, dict),
|
|
isinstance(tag_id, dict) and '_key' not in tag_id
|
|
]):
|
|
self.logger.error('Unable to create requested tag for group_id: `%s`. tag_value: `%s`', group_id, tag_value)
|
|
return None
|
|
|
|
return {
|
|
'group_id': group_id,
|
|
'tag_id': tag_id['_key'],
|
|
'tag_name': tag_value
|
|
}
|
|
|
|
def update_tag(self, group_id, tag_id, tag_value):
|
|
"""
|
|
given a group id, a tag_id update the existing tag.
|
|
A group can have more than one tag.
|
|
Each tag has an id. Hence the tag id! For a given group, no duplicate
|
|
tags will be allowed.
|
|
|
|
@type group_id: str
|
|
@param group_id: id of a group
|
|
|
|
@type tag_id: str
|
|
@param tag_id: id of the tag
|
|
|
|
@type tag_value: str
|
|
@param tag_value: new value of this tag
|
|
|
|
@rtype dict:
|
|
@return committed value...
|
|
"""
|
|
if not isinstance(group_id, itsi_py3.string_type):
|
|
raise TypeError('Expecting `group_id` to be non-empty basestring. Received: %s' % group_id)
|
|
if not isinstance(tag_id, itsi_py3.string_type):
|
|
raise TypeError('Expecting `tag_id` to be non-empty basestring. Received: %s' % tag_id)
|
|
|
|
obj = NotableEventTag(self.session_key)
|
|
data = {
|
|
'event_id': group_id,
|
|
'_key': tag_id,
|
|
'tag_name': tag_value
|
|
}
|
|
rval = obj.update(tag_id, data, is_partial_update=True)
|
|
return rval
|
|
|
|
def get_all_tags(self, group_id):
|
|
"""
|
|
given an group_id, fetch all of its tags
|
|
@type group_id: str
|
|
@param group_id: id of a group
|
|
|
|
@rtype: list
|
|
@return: list of all existing tags for a given group
|
|
"""
|
|
if not isinstance(group_id, itsi_py3.string_type):
|
|
raise TypeError('Expecting `group_id` to be non-empty basestring. Received: %s' % group_id)
|
|
|
|
obj = NotableEventTag(self.session_key)
|
|
rval = obj.get(group_id, is_event_id=True)
|
|
tags = extract(rval, 'tag_name')
|
|
return tags
|
|
|
|
def get_tag(self, tag_id):
|
|
"""
|
|
given a tag id, fetch its value
|
|
@type tag_id: str
|
|
@param tag_id: id of desired tag
|
|
|
|
@rtype: basestring
|
|
@return: tag value corresponding to `tag_id`
|
|
"""
|
|
if not isinstance(tag_id, itsi_py3.string_type):
|
|
raise TypeError('Expecting `tag_id` to be non-empty basestring. Received: %s' % tag_id)
|
|
obj = NotableEventTag(self.session_key)
|
|
rval = obj.get(tag_id)
|
|
tag = extract(rval, 'tag_name')
|
|
return tag
|
|
|
|
def delete_tag(self, tag_id):
|
|
"""
|
|
given a tag_id, delete its value
|
|
@type tag_id: str
|
|
@param tag_id: id of the tag you are interested in deleting in.
|
|
@return nothing
|
|
"""
|
|
if not isinstance(tag_id, itsi_py3.string_type):
|
|
raise TypeError('Expecting `tag_id` to be non-empty basestring. Received: %s' % tag_id)
|
|
obj = NotableEventTag(self.session_key)
|
|
obj.delete(tag_id)
|
|
return
|
|
|
|
def delete_all_tags(self, group_id):
|
|
"""
|
|
given an group_id, delete all of its tags
|
|
@type group_id: str
|
|
@param group_id: id of the group whose tags you want to delete
|
|
@return nothing
|
|
"""
|
|
if not isinstance(group_id, itsi_py3.string_type):
|
|
raise TypeError('Expecting `group_id` to be non-empty basestring. Received: %s' % group_id)
|
|
obj = NotableEventTag(self.session_key)
|
|
obj.delete(group_id, is_event_id=True)
|
|
return
|
|
|
|
def create_comment(self, group_id, comment, policy_id=None):
|
|
"""
|
|
for given group_id, add a new comment
|
|
@type group_id: str
|
|
@param group_id: id of the group you want to add a comment to
|
|
|
|
@type comment: str
|
|
@param comment: the comment you wish to add
|
|
|
|
@type policy_id: basestring
|
|
@param policy_id: policy id of the group
|
|
|
|
@rtype: dict
|
|
@return: a nicely formatted dict consisting of comment, comment id and
|
|
event id
|
|
"""
|
|
if not isinstance(group_id, itsi_py3.string_type):
|
|
raise TypeError('Expecting `group_id` to be non-empty basestring. Received: %s' % group_id)
|
|
if not isinstance(comment, itsi_py3.string_type):
|
|
raise TypeError('Expecting `comment` to be non-empty basestring. Received: %s' % comment)
|
|
obj = NotableEventComment(self.session_key)
|
|
data = {
|
|
'event_id': group_id,
|
|
'comment': comment,
|
|
'itsi_policy_id': policy_id
|
|
}
|
|
r = obj.create(data)
|
|
if not r:
|
|
self.logger.error('Unable to create requested comment `%s` for group id: `%s`', comment, group_id)
|
|
return None
|
|
|
|
rval = {
|
|
'event_id': group_id,
|
|
'comment_id': r.get('comment_id'),
|
|
'comment': comment
|
|
}
|
|
self.logger.debug('Successfully created comment: `%s` for group id: `%s`. comment id: `%s`',
|
|
comment, group_id, r.get('comment_id'))
|
|
return rval
|
|
|
|
def get_comment(self, comment_id):
|
|
"""
|
|
for a given comment id, fetch the comment
|
|
@type comment_id: str
|
|
@param comment_id: id of the comment we care about
|
|
|
|
@rtype: str
|
|
@return: comment corresponding to comment id
|
|
"""
|
|
if not isinstance(comment_id, itsi_py3.string_type):
|
|
raise TypeError('Expecting `comment_id` to be non-empty basestring. Received: %s' % comment_id)
|
|
obj = NotableEventComment(self.session_key)
|
|
res = obj.get(comment_id)
|
|
rval = json.loads(res['_raw'])
|
|
comment = extract(rval, 'comment')
|
|
if isinstance(comment, str):
|
|
return comment
|
|
else:
|
|
return comment[0]
|
|
|
|
def get_all_comments(self, group_id):
|
|
"""
|
|
for a given group id, fetch all of its comments
|
|
@type group_id: str
|
|
@param group_id: id of the group we care about
|
|
|
|
@rtype: list
|
|
@return: list of comments corresponding to group_id
|
|
"""
|
|
if not isinstance(group_id, itsi_py3.string_type):
|
|
raise TypeError('Expecting `group_id` to be non-empty basestring. Received: %s' % group_id)
|
|
obj = NotableEventComment(self.session_key)
|
|
res = obj.get(group_id, is_group_id=True)
|
|
comments = []
|
|
for result in res:
|
|
rval = json.loads(result['_raw'])
|
|
comment = extract(rval, 'comment')
|
|
comments.append(comment[0])
|
|
|
|
return comments
|
|
|
|
def delete_comment(self, comment_id):
|
|
"""
|
|
delete the comment associated with comment id
|
|
@type comment_id: str
|
|
@param comment_id: id of the comment we care about
|
|
|
|
@returns: nothing
|
|
|
|
This operation is currently unsupported.
|
|
"""
|
|
raise NotImplementedError('delete_comment operation is not supported')
|
|
|
|
def delete_all_comments(self, group_id):
|
|
"""
|
|
delete all comments associated with group id
|
|
@type group_id: str
|
|
@param group_id: id of the event we care about
|
|
|
|
@returns nothing
|
|
|
|
This operation is currently unsupported.
|
|
"""
|
|
raise NotImplementedError('delete_all_comments operation is not supported')
|
|
|
|
def update_comment(self, group_id, comment_id, comment):
|
|
"""
|
|
given a group id, a comment_id update the comment.
|
|
A group can have more than one comment.
|
|
Each comment has an id. Hence the event id! For a given event, no duplicate
|
|
comments will be allowed.
|
|
|
|
@type group_id: str
|
|
@param group_id: id of a group
|
|
|
|
@type comment_id: str
|
|
@param comment_id: id of the comment
|
|
|
|
@type comment: str
|
|
@param comment: new value of this comment
|
|
|
|
@rtype dict:
|
|
@return committed value...
|
|
|
|
This operation is currently unsupported.
|
|
"""
|
|
raise NotImplementedError('update_comment operation is not supported')
|
|
|
|
def update_ticket_info(self, group_ids, ticket_system, ticket_id,
|
|
ticket_url, **other_params):
|
|
"""
|
|
given a list of group_ids, update each of them with an external
|
|
ticket info
|
|
@type group_ids: list/basestring
|
|
@param group_ids: list of group_ids or comma separated string of
|
|
group_ids
|
|
|
|
@type ticket_system: basestring
|
|
@param ticket_system: string representing an external ticket system
|
|
Ex: Remedy, Siebel, ServiceNow etc...
|
|
|
|
@type ticket_id: basestring
|
|
@param ticket_id: identifier of an external ticket.
|
|
|
|
@type ticket_url: basestring
|
|
@param ticket_url: url to reach external ticket.
|
|
|
|
@type other_params: dict
|
|
@param other_params: other key value pairs to locate your event. Pass nothing if you dont know these
|
|
values.
|
|
|
|
@rtype dict:
|
|
@return: dict with list of ticket ids that are successfully updated
|
|
and list of ticket ids that were fail to update.
|
|
|
|
"""
|
|
if isinstance(group_ids, itsi_py3.string_type):
|
|
group_ids = group_ids.split(',')
|
|
if not isinstance(group_ids, list):
|
|
raise TypeError('Expecting group_ids to be a list type. Received=%s.' % type(group_ids).__name__)
|
|
if not group_ids:
|
|
raise ValueError('Expecting group_ids to have at least 1 id. Received=%s.' % group_ids)
|
|
rval = {
|
|
'success': [],
|
|
'failed': []
|
|
}
|
|
|
|
self.logger.debug(('Group ids=%s ticket_system=%s ticket_id=%s'
|
|
' ticket_url=%s other params=%s'), group_ids, ticket_system,
|
|
ticket_id, ticket_url, json.dumps(other_params))
|
|
|
|
for id_ in group_ids:
|
|
ticket = ExternalTicket(id_, self.session_key, self.logger)
|
|
content = ticket.upsert(ticket_system, ticket_id, ticket_url, **other_params)
|
|
if content:
|
|
rval['success'].append(ticket_id)
|
|
else:
|
|
rval['failed'].append(ticket_id)
|
|
|
|
self.logger.debug('Succeeded for ids=%s Failed for ids=%s', rval['success'], rval['failed'])
|
|
return rval
|
|
|
|
def delete_ticket_info(self, group_ids, ticket_system, ticket_id):
|
|
"""
|
|
Delete external ticketing based information for given group_ids
|
|
@type group_ids: list/basestring
|
|
@param group_ids: list of group_ids or comma separated string of
|
|
group_ids
|
|
|
|
@type ticket_system: basestring
|
|
@param ticket_system: string representing an external ticket system
|
|
Ex: Remedy, Siebel, ServiceNow etc...
|
|
Set ticket_system to None to delete all tickets for these event_ids
|
|
|
|
@type ticket_id: basestring
|
|
@param ticket_id: identifier of an external ticket.
|
|
Set ticket_id to None to delete all tickets for this ticket_system
|
|
|
|
@rtype dict:
|
|
@return: dict with list of ticket ids that are successfully deleted
|
|
and list of ticket ids that were fail to delete.
|
|
|
|
"""
|
|
if isinstance(group_ids, itsi_py3.string_type):
|
|
group_ids = group_ids.split(',')
|
|
if not isinstance(group_ids, list):
|
|
raise TypeError('Expecting group_ids to be a list type. Received=%s.' % type(group_ids).__name__)
|
|
if not group_ids:
|
|
raise ValueError('Expecting group_ids to have at least 1 id. Received=%s.' % group_ids)
|
|
rval = {
|
|
'success': [],
|
|
'failed': []
|
|
}
|
|
|
|
self.logger.debug(('Group ids=%s ticket_system=%s ticket_id=%s'' ticket_url=%s other params=%s'),
|
|
group_ids, ticket_system, ticket_id)
|
|
|
|
for id_ in group_ids:
|
|
ticket = ExternalTicket(id_, self.session_key, self.logger)
|
|
ticket.delete(ticket_system, ticket_id)
|
|
rval['success'].append(id_)
|
|
self.logger.debug('Succeeded for ids=%s Failed for ids=%s', rval['success'], rval['failed'])
|
|
return rval
|
|
|
|
def update(self, blob, split_by=',', **kwargs):
|
|
"""
|
|
update each group id in `blob` with given data value individually
|
|
This method only deals with updating `status`, `severity` and `owner`
|
|
|
|
To update tags and comments, use `update_tag()` and `update_comment()`
|
|
Why separate methods? This is an implementation *secret*.
|
|
|
|
@type blob: dict
|
|
@param blob:
|
|
[
|
|
{
|
|
'group_ids': ['group_id1', 'group_ida', ... ],
|
|
'severity': '1',
|
|
'status': '5',
|
|
'owner': 'cottonmouth'
|
|
},
|
|
{
|
|
'group_ids': ['group_id2', 'event_idb', ... ],
|
|
'severity': '6',
|
|
'status': '2',
|
|
'owner': 'black_mamba'
|
|
},
|
|
...
|
|
]
|
|
@type kwargs: dict
|
|
@param kwargs: send in keys `earliest_time` and
|
|
`latest_time` with corresponding values if you know what you are doing.
|
|
Ex:
|
|
'-15m' implies '15 mins ago'
|
|
'-15s' implies '15 seconds ago'
|
|
'-15d' implies '15 days ago'
|
|
'-15w' implies '15 weeks ago'
|
|
'rt' implies real time
|
|
'now' implies current time
|
|
no other values are supported
|
|
|
|
@rtype: dict
|
|
@return: dictionary of event_id schemas, in the order of input...
|
|
"""
|
|
if isinstance(blob, dict):
|
|
blob = [blob]
|
|
if not isinstance(blob, list):
|
|
raise TypeError('Expecting `blob` to be a dict/list. Received: %s' % type(blob).__name__)
|
|
|
|
if not blob:
|
|
raise ValueError('Expecting `blob` to be non-empty.')
|
|
|
|
rval = []
|
|
for group in blob:
|
|
# validate/sanitize...
|
|
if not isinstance(group, dict):
|
|
raise TypeError('Expecting a dictionary. Received: `%s`. Type: `%s`' % (group, type(group).__name__))
|
|
if 'group_ids' not in group:
|
|
raise KeyError('Expecting `group_ids` in your input.')
|
|
keys = group.pop('group_ids')
|
|
|
|
# sanitize request, get rid of unsupported keys...
|
|
supported_keys = ('owner', 'severity', 'status', 'group_ids')
|
|
for k in list(group.keys()):
|
|
if k not in supported_keys:
|
|
self.logger.debug('Getting rid of `%s`: `%s`. Unsupported.' % (k, group[k]))
|
|
group.pop(k)
|
|
|
|
if isinstance(keys, itsi_py3.string_type):
|
|
keys = keys.split(split_by)
|
|
data = []
|
|
for i in keys:
|
|
group_data = deepcopy(group)
|
|
group_data['group_id'] = i
|
|
data.append(group_data)
|
|
kwargs['is_partial_update'] = True
|
|
self.logger.debug('Updating keys: `%s` with: %s. kwargs: %s', keys, data, kwargs)
|
|
objects = self.group.update_bulk(keys, data, kwargs)
|
|
rval.extend(objects)
|
|
return rval
|
|
|
|
def update_severity(self, group_ids, severity, split_by=',', **kwargs):
|
|
"""
|
|
given a list of group ids, update each of its severity to given
|
|
severity value.
|
|
@type group_ids: basestring/list
|
|
@param group_ids: comma separated group ids or list of group ids
|
|
|
|
@type severity: basestring
|
|
@param severity: one of the many supported severity values
|
|
|
|
@type split_by: basestring
|
|
@param split_by: if `group_ids` is a string, what are the group ids split
|
|
by? defaults to `,`
|
|
|
|
@type kwargs: dict
|
|
@param kwargs: other time specific params like `earliest_time` and
|
|
`latest_time` to locate your event. Pass nothing if you dont know these
|
|
values.
|
|
|
|
@rtype: list
|
|
@return: updated notable event groups
|
|
"""
|
|
if isinstance(group_ids, itsi_py3.string_type):
|
|
if not group_ids.strip():
|
|
raise ValueError('Expecting `group_ids` to contain some value. Received: %s' % group_ids)
|
|
group_ids = group_ids.split(split_by)
|
|
if not isinstance(group_ids, list):
|
|
raise TypeError('Expecting `group_ids` to be of type basestring list. Received: {}. Type: {}'
|
|
.format(group_ids, type(group_ids).__name__))
|
|
if not group_ids or not severity.strip():
|
|
raise ValueError('Expecting non-empty list of `group_ids`. and valid severity string')
|
|
|
|
# prepare data
|
|
data = []
|
|
for i in group_ids:
|
|
data.append({'severity': severity, 'group_id': i})
|
|
|
|
kwargs['is_partial_update'] = True
|
|
self.logger.debug('Updating keys: `%s` with: %s. kwargs: %s', group_ids, data, kwargs)
|
|
objects = self.group.update_bulk(group_ids, data, kwargs)
|
|
return objects
|
|
|
|
def update_status(self, group_ids, status, split_by=',', **kwargs):
|
|
"""
|
|
given list of group ids, update each of its status to given
|
|
value.
|
|
@type group_ids: basestring/list
|
|
@param group_ids: comma separated group ids or list of group ids
|
|
|
|
@type status: basestring
|
|
@param status: value of the new status
|
|
|
|
@type split_by: basestring
|
|
@param split_by: if `group_ids` is a string, what are the group ids split
|
|
by? defaults to `,`
|
|
|
|
@type kwargs: dict
|
|
@param kwargs: other time specific params like `earliest_time` and
|
|
`latest_time` to locate your event. Pass nothing if you dont know these
|
|
values.
|
|
|
|
@rtype: list
|
|
@return: updated notable event groups
|
|
"""
|
|
if isinstance(group_ids, itsi_py3.string_type):
|
|
if not group_ids.strip():
|
|
raise ValueError('Expecting `group_ids` to contain some value. Received: {}'.format(group_ids))
|
|
group_ids = group_ids.split(split_by)
|
|
if not isinstance(group_ids, list):
|
|
raise TypeError('Expecting `group_ids` to be of type basestring list. Received: {}. Type: {}'.
|
|
format(group_ids, type(group_ids).__name__))
|
|
if not group_ids or not status.strip():
|
|
raise ValueError('Expecting non-empty list of `group_ids`. and valid status string')
|
|
|
|
# prepare data
|
|
data = []
|
|
for i in group_ids:
|
|
data.append({'status': status, 'group_id': i})
|
|
|
|
kwargs['is_partial_update'] = True
|
|
self.logger.debug('Updating keys: `%s` with: %s. kwargs: %s', group_ids, data, kwargs)
|
|
objects = self.group.update_bulk(group_ids, data, kwargs)
|
|
return objects
|
|
|
|
def update_owner(self, group_ids, owner, split_by=',', **kwargs):
|
|
"""given list of group ids, update each of its owner to given
|
|
value.
|
|
@type group_ids: basestring/list
|
|
@param group_ids: comma separated group ids or list of group ids
|
|
|
|
@type owner: basestring
|
|
@param owner: value of the new owner
|
|
|
|
@type split_by: basestring
|
|
@param split_by: if `group_ids` is a string, what are the group ids split
|
|
by? defaults to `,`
|
|
|
|
@type kwargs: dict
|
|
@param kwargs: other time specific params like `earliest_time` and
|
|
`latest_time` to locate your event. Pass nothing if you dont know these
|
|
values.
|
|
|
|
@rtype: list
|
|
@return: updated notable event groups
|
|
"""
|
|
if isinstance(group_ids, itsi_py3.string_type):
|
|
if not group_ids.strip():
|
|
raise ValueError('Expecting `group_ids` to contain some value. Received: %s' % group_ids)
|
|
group_ids = group_ids.split(split_by)
|
|
if not isinstance(group_ids, list):
|
|
raise TypeError('Expecting `group_ids` to be of type basestring list. Received: %s. Type: %s'
|
|
% (group_ids, type(group_ids).__name__))
|
|
if not group_ids or not owner.strip():
|
|
raise ValueError('Expecting non-empty list of `group_ids`. and valid owner string')
|
|
|
|
# prepare data
|
|
data = []
|
|
for i in group_ids:
|
|
data.append({'owner': owner, 'group_id': i})
|
|
|
|
kwargs['is_partial_update'] = True
|
|
self.logger.debug('Updating keys: `%s` with: %s. kwargs: %s', group_ids, data, kwargs)
|
|
objects = self.group.update_bulk(group_ids, data, kwargs)
|
|
return objects
|
|
|
|
def get(self, group_id):
|
|
"""
|
|
Get the EventGroup Object
|
|
@type group_id: string
|
|
@param group_id: id of the group where add_drilldown to be operated on
|
|
"""
|
|
return self.group.get(group_id)
|