c3444e384d
Configure tox+content to fetch event and convert alarms and logs to rst for use in build. Handle non-existant tmp dir in zuul builds Add static events.yaml for CI/CD testingx Generalize label construction to prevent namespace conflicts Consume events directly from fm repo (required changes merged) Update logs template for legibility. Add clean up for temporary rst files. Point parser at dynamically downloaded events file Restore logs template Note: This review deletes static alarm and log files Note: This review excludes alarm files from git as they are now build-time temp files. Note: This review uses a static copy of events.yaml to pass tox until the dep. below is met. It will need reconfiguration at that time. Depends-On: https://review.opendev.org/c/starlingx/fault/+/863574 Signed-off-by: Ron Stone <ronald.stone@windriver.com> Change-Id: I0bb8d0a77b9d3cf22b33f8930c569b3e70b7291c
246 lines
10 KiB
Python
Executable File
246 lines
10 KiB
Python
Executable File
|
|
import argparse
|
|
import yaml
|
|
from yaml.loader import SafeLoader
|
|
import re
|
|
import os
|
|
|
|
def parseLayoutFile():
|
|
layoutFile = open(args.layout,"r")
|
|
data = layoutFile.read()
|
|
layoutFile.close()
|
|
regex= r'(?<=\")([\s\S]*?)(?=\")'
|
|
data = re.findall(regex, data)
|
|
if(len(data) != 5):
|
|
raise Exception('layout file has a different structure from expected')
|
|
return [data[0], data[2], data[4]]
|
|
|
|
|
|
def parseEventFile():
|
|
eventFile = open(args.event, "r")
|
|
data = yaml.load(eventFile, Loader=SafeLoader)
|
|
eventFile.close()
|
|
return data
|
|
|
|
def alignMultiLine(characterCounter, multilineString):
|
|
index = 0
|
|
strings = multilineString.split('\n')
|
|
for string in strings:
|
|
if(index !=0):
|
|
string = string.lstrip()
|
|
string = "\n"+"".join(" " for i in range(characterCounter)) + string
|
|
strings[index] = string
|
|
index+=1
|
|
return "\n".join(strings)
|
|
|
|
def replaceSymbols(text, oldSymbols, newSymbols):
|
|
counter = 0
|
|
for oldSymbol in oldSymbols:
|
|
if(len(newSymbols[counter]) - len(oldSymbols[counter]) > 0):
|
|
text = str(text).replace(oldSymbol, " "+newSymbols[counter]+" ")
|
|
else:
|
|
text = str(text).replace(oldSymbol, newSymbols[counter])
|
|
counter+=1
|
|
return text
|
|
|
|
def getTitleLength(header):
|
|
idx1 = header.find("<over_score>")+14
|
|
idx2 = header.find("<under_score>")
|
|
return idx2 - idx1
|
|
|
|
# def getContext(context):
|
|
# if(len(context) == 3):
|
|
# return "starlingx-openstack-empty"
|
|
# elif(len(context) == 2):
|
|
# if("starlingx" in context):
|
|
# if("openstack" in context):
|
|
# return "starlingx-openstack"
|
|
# else:
|
|
# return "starlingx-empty"
|
|
# else:
|
|
# return "openstack-empty"
|
|
# else:
|
|
# return context[0]
|
|
|
|
# RS - 11-16-22 - generalize getContext to all runtime scenarios
|
|
def getContext(context):
|
|
return '-'.join(map(str, context))
|
|
|
|
def seriesFilter(key, serie):
|
|
if(float(serie)%100 > 1):
|
|
return (float(key)//10) == (float(serie)//10)
|
|
else:
|
|
return (float(key)//100) == (float(serie)//100)
|
|
|
|
def seriesFile(layout, events, types, fileExtension, oldSymbols, newSymbols, products, sort ):
|
|
series = args.series.split(",")
|
|
for serie in series:
|
|
matchingKeys = [key for key in events.keys() if seriesFilter(key, serie) and events[key]["Type"] in types and events[key]["Context"] in products ]
|
|
if(sort):
|
|
matchingKeys.sort()
|
|
if(len(matchingKeys) > 0):
|
|
serieFile = open(args.outputPath+str(serie)+"-series-"+'-'.join(types).lower()+"-messages"+fileExtension, "w")
|
|
header = layout[0]
|
|
header = header.replace("<series_number>",serie).replace("<series-number>",serie)
|
|
score = "".join(args.titleSymbol for i in range(getTitleLength(header)))
|
|
header = header.replace("<over_score>", score)
|
|
header = header.replace("<Context>", getContext(products))
|
|
header = header.replace("<under_score>", score)
|
|
serieFile.write(header)
|
|
for matchingKey in matchingKeys:
|
|
body = layout[1]
|
|
body = body.replace("<alarm_id>", format(matchingKey, '.3f'))
|
|
fields = re.findall('(?<=\<)(.*?)(?=\>)', body)
|
|
for field in fields:
|
|
if(field in events[matchingKey]):
|
|
if(type(events[matchingKey][field]) == type(events)):
|
|
value = []
|
|
for subkey in events[matchingKey][field]:
|
|
value.append(events[matchingKey][field][subkey])
|
|
events[matchingKey][field] = "\n".join(value)
|
|
else:
|
|
events[matchingKey][field] = (re.sub(r'\n\s*\n','\n',str(events[matchingKey][field]),re.MULTILINE))
|
|
if(oldSymbols != None and newSymbols != None):
|
|
events[matchingKey][field]= replaceSymbols(events[matchingKey][field], oldSymbols,newSymbols)
|
|
if('\n' in events[matchingKey][field]):
|
|
index = body.index('<'+field+'>')
|
|
characterCounter= 0
|
|
while(body[index] != '\n'):
|
|
index-=1
|
|
characterCounter+=1
|
|
body = body.replace('<'+field+'>',alignMultiLine(characterCounter-1, events[matchingKey][field]))
|
|
else:
|
|
body = body.replace('<'+field+'>',events[matchingKey][field])
|
|
else:
|
|
body = body.replace('<'+field+'>','N/A')
|
|
serieFile.write(body)
|
|
footer = layout[2]
|
|
serieFile.write(footer)
|
|
serieFile.close
|
|
|
|
def recordsFile(layout, events, fileExtension, oldSymbols, newSymbols, sort):
|
|
records = args.records.split(",")
|
|
if(len(records) > 0):
|
|
matchingKeys = [float(record) for record in records for key in events.keys() if float(key) == float(record)]
|
|
if(sort):
|
|
matchingKeys.sort()
|
|
if(len(matchingKeys) > 0):
|
|
serieFile = open(args.outputPath+args.fileName+fileExtension, "w")
|
|
header = layout[0]
|
|
score = "".join(args.titleSymbol for i in range(getTitleLength(header)))
|
|
header = header.replace("<over_score>", score)
|
|
header = header.replace("<under_score>", score)
|
|
serieFile.write(header)
|
|
for matchingKey in matchingKeys:
|
|
body = layout[1]
|
|
body = body.replace("<alarm_id>", format(matchingKey, '.3f'))
|
|
fields = re.findall('(?<=\<)(.*?)(?=\>)', body)
|
|
for field in fields:
|
|
if(field in events[matchingKey]):
|
|
if(type(events[matchingKey][field]) == type(events)):
|
|
value = []
|
|
for subkey in events[matchingKey][field]:
|
|
value.append(events[matchingKey][field][subkey])
|
|
events[matchingKey][field] = "\n".join(value)
|
|
else:
|
|
events[matchingKey][field] = (re.sub(r'\n\s*\n','\n',str(events[matchingKey][field]),re.MULTILINE))
|
|
if(oldSymbols != None and newSymbols != None):
|
|
events[matchingKey][field]= replaceSymbols(events[matchingKey][field], oldSymbols,newSymbols)
|
|
if('\n' in events[matchingKey][field]):
|
|
index = body.index('<'+field+'>')
|
|
characterCounter= 0
|
|
while(body[index] != '\n'):
|
|
index-=1
|
|
characterCounter+=1
|
|
body = body.replace('<'+field+'>',alignMultiLine(characterCounter-1, events[matchingKey][field]))
|
|
else:
|
|
body = body.replace('<'+field+'>',events[matchingKey][field])
|
|
else:
|
|
body = body.replace('<'+field+'>','N/A')
|
|
serieFile.write(body)
|
|
footer = layout[2]
|
|
serieFile.write(footer)
|
|
serieFile.close
|
|
|
|
|
|
parser = argparse.ArgumentParser()
|
|
invalidArguments = False
|
|
parser.add_argument("-l", "--layout", required=True, help = "path for the layout file")
|
|
parser.add_argument("-e", "--event", required=True, help = "path for the events.yaml file")
|
|
parser.add_argument("-s", "--series", help = "list of the desired series")
|
|
parser.add_argument("-ts", "--titleSymbol", required=True, help = "Symbol used between the title")
|
|
parser.add_argument("-replace", "--replace", required=False, help = "replaces a symbol with another")
|
|
parser.add_argument("-type", "--type", help = "type can be Alarm or Log, it also can be both")
|
|
parser.add_argument("-outputPath", "--outputPath", required=True, help="Path where the output will be saved")
|
|
parser.add_argument("-records", "--records", help="list of the desired records")
|
|
parser.add_argument("-fileName", "--fileName", help="file name for the output file")
|
|
parser.add_argument("-product", "--product", help="product type for filtering")
|
|
parser.add_argument("-sort", "--sort", help="argument that defines if the output will be sorted")
|
|
|
|
|
|
args = parser.parse_args()
|
|
oldSymbol = None
|
|
newSymbol = None
|
|
types = []
|
|
|
|
if(args.series == None and args.records == None):
|
|
invalidArguments = True
|
|
print("Expected either series or records as an argument")
|
|
if(args.series != None and args.product == None):
|
|
invalidArguments = True
|
|
print("Expected product as an argument")
|
|
if(args.series != None and args.type == None):
|
|
invalidArguments=True
|
|
print("Expected type as an argument")
|
|
if(args.replace != None):
|
|
replaceItems =args.replace.split(",")
|
|
oldSymbols = []
|
|
newSymbols = []
|
|
for replaceItem in replaceItems:
|
|
replace = replaceItem.lstrip().split(" ")
|
|
if(len(replace) == 2):
|
|
oldSymbols.append(replace[0])
|
|
newSymbols.append(replace[1])
|
|
if(args.type != None):
|
|
types = args.type.split(",")
|
|
counter = 0
|
|
for recordtype in types:
|
|
types[counter] = recordtype.lstrip().rstrip().capitalize()
|
|
if(types[counter] != "Alarm" and types[counter]!= "Log"):
|
|
invalidArguments = True
|
|
print("Invalid type argument")
|
|
counter +=1
|
|
if(args.records != None):
|
|
if(args.fileName == None):
|
|
invalidArguments = True
|
|
print("Expected fileName as an argument")
|
|
if(args.product != None):
|
|
products = args.product.split(",")
|
|
counter = 0
|
|
for product in products:
|
|
products[counter] = product.lstrip().rstrip().lower()
|
|
if(products[counter] != "openstack" and products[counter] != "starlingx"):
|
|
if(products[counter] == "empty"):
|
|
products[counter] = None
|
|
else:
|
|
print("Invalid product argument")
|
|
invalidArguments= True
|
|
counter +=1
|
|
if(args.sort != None):
|
|
if(args.sort.upper() == 'TRUE'):
|
|
sort = True
|
|
else:
|
|
sort = False
|
|
else:
|
|
sort = False
|
|
|
|
|
|
|
|
if(invalidArguments == False):
|
|
fileName, fileExtension = os.path.splitext(args.layout)
|
|
layout = parseLayoutFile()
|
|
events = parseEventFile()
|
|
if(args.records != None):
|
|
recordsFile(layout,events,fileExtension, oldSymbols, newSymbols,sort)
|
|
else:
|
|
seriesFile(layout, events, types, fileExtension, oldSymbols, newSymbols, products,sort) |