How to append to python dictionary inside a function - python

I have the following code:
def main():
content = si.RetrieveContent()
esx_vm = {}
search_index = si.content.searchIndex
for child in content.rootFolder.childEntity:
if hasattr(child, 'vmFolder'):
datacenter = child
vmFolder = datacenter.vmFolder
vmList = vmFolder.childEntity
for vm in vmList:
vmname = PrintVmInfo(vm)
if vmname is not None:
hostname = vmname
vm = si.content.searchIndex.FindByDnsName(None, hostname, True)
try :
ESX = vm.runtime.host.name
except :
pass
esx_vm.update({ESX:hostname})
print(esx_vm)
if __name__ == "__main__":
main()
The code is supposed to create a dictionary mapping esx to vm in the below format:
{'esx1': 'vm1'}
But I am getting only one key-value {'esx1': 'vm1'} and not all the esx:vm mappings. I am excepting to get:
{'esx1': 'vm1','esx2': 'vm2','esx3': 'vm3','esx4': 'vm4'}
and so on.
Any advise how to get the the correct values of the dictionary?

You might want to update ESX values inside "for loop". But its happening to be outside, that's why there is one key in the dict. Please add ESX key as part of for loop. Something like this (inside for loop),
try :
ESX = vm.runtime.host.name
esx_vm.update({ESX:hostname}) # Or, just, esx_vm[ESX]=hostname
except :
pass

Related

Python Flask show multiple results in a list

I am messing around with a script in Flask I have this portion here
def get_interfaces_list2(device):
output_interfaces = device.send_command('show interfaces switchport')
current_dir = os.getcwd()
template_file = open(current_dir + "/scripts/textfsm/show_interface_switchport.template", "r")
template = TextFSM(template_file)
parsed_interfaces = template.ParseText(output_interfaces)
interface_list = []
for interface_data in parsed_interfaces:
resultDict = {}
resultDict["interface"] = interface_data[0]
resultDict["admin_mode"] = interface_data[5]
resultDict["access_vlan"] = interface_data[6]
resultDict["voice_vlan"] = interface_data[8]
resultDict["trunking_vlans"] = interface_data[9]
interface_list.append(resultDict)
Return interface_list
I would like to add another command to add more info from the switch
output_interfaces1 = device.send_command('show interfaces description')
current_dir = os.getcwd()
template_file = open(current_dir + "/scripts/textfsm/show_interface_description.template", "r")
template = TextFSM(template_file)
parsed_interfaces1 = template.ParseText(output_interfaces1)
interface_list1 = []
for interface_data1 in parsed_interfaces1:
resultDict["descrip"] = interface_data1
interface_list.append(interface_list1)
return interface_list
I would like to combine this into a single list and return that info in an HTML
If I understood correctly, you are currently saving information about an interface in a dictionary and storing that dict in a list. You then want to add more information about the interface. I think there are two approaches you can take here:
Run a single for loop on both parsed_interfaces and parsed_interfaces1 and store all of the info in one shot.
Store the info from your first loop in another dictionary instead of a list where the key is the interface name. Then in the second loop use that key to access the nested dict and store the new info.

How do I reuse the code from this function cleanly?

The following function is used within a module to query network devices and is called from multiple scripts I use. The arguments it takes are a nested dictionary (the device IP and creds etc) and a string (the command to run on the device):
def query_devices(hosts, cmd):
results = {
'success' : [],
'failed' : [],
}
for host in hosts:
device = hosts[host]
try:
swp = ConnectHandler(device_type=device['dev_type'],
ip=device['ip'],
username=device['user'],
password=device['pwd'],
secret=device['secret'])
swp.enable()
results[host] = swp.send_command(cmd)
results['success'].append(host)
swp.disconnect()
except (NetMikoTimeoutException, NetMikoAuthenticationException) as e:
results['failed'].append(host)
results[host] = e
return results
I want to reuse all of the code to update a device and the only changes would be:
The function would take the same dictionary but the cmd argument would now be a list of commands.
The following line:
results[host] = swp.send_command(cmd)
would be replaced by:
results[host] = swp.send_config_set(cmd)
I could obviously just replicate the function making those two changes and as it is in a module I reuse, I am only having to do it once but I am still basically repeating a lot of the same code.
Is there a better way to do this as I seem to come across the same issue quite often in my code.
You could just add a check on the changed line:
...
if isinstance(cmd, str):
results[host] = swp.send_command(cmd)
else:
results[host] = swp.send_config_set(cmd)
...
The rest of the function can stay the same and now you can simply call it with either a string or a list of strings...
You could use the unpacking operator to always make cmds an iterable (a tuple, actually) even if it is a single value. That way you could always call send_config_set. Here is a super simplified example to illustrate the concept.
def query_devices(hosts, *cmds):
for one_cmd in cmds:
print(one_cmd)
print('query_devices("hosts", "cmd_1")')
query_devices("hosts", "cmd_1")
print('\nquery_devices("hosts", "cmd_1", "cmd_2", "cmd_3")')
query_devices("hosts", "cmd_1", "cmd_2", "cmd_3")
print('\nquery_devices("hosts", *["cmd_1", "cmd_2", "cmd_3"])')
query_devices("hosts", *["cmd_1", "cmd_2", "cmd_3"])
Output:
query_devices("hosts", "cmd_1")
cmd_1
query_devices("hosts", "cmd_1", "cmd_2", "cmd_3")
cmd_1
cmd_2
cmd_3
query_devices("hosts", *["cmd_1", "cmd_2", "cmd_3"])
cmd_1
cmd_2
cmd_3

AWS Lambda, Python : Get Instances with launch tme for sorting syntax error, Error in Comparing tags

I am working on an AWS Lambda code where I want to get all instances with a specific Value, sort them in reverse order to remove the oldest instance, and pass commands to the remaining instances.
Here are the 2 issues I am facing :
1) As soon as I remove print "Tag value is %s"%(tag['Value']) from the code part, I am getting null response for perfectly working code otherwise.
2) As I am adding the instances to a list, I am not able to sort them with LaunchTime attribute, is there any alternate way?
Code :
def lambda_handler(event, context):
reservations = boto3.client('ec2').describe_instances()['Reservations']
instances_list = []
process_instance_list = []
command = 'crontab -r'
ssm = boto3.client('ssm')
for res in reservations:
instances = res['Instances']
for inst in res['Instances']:
for tag in inst['Tags']:
print("Tag value is {}".format(tag['Value']))
//Below if loop doesn't work if above printout is removed.
if tag['Value']=='Ubuntu_Magento':
print("{} {} {}".format(tag['Value'], inst['InstanceId'], inst['LaunchTime']))
instances_list.append(inst)
// Below line gives syntax error, even though I have used LaunchTime param above
instances_list.sort(key=lambda x: x['LaunchTime'] reverse=False)
non_processed_id=instances_list[0]['InstanceId']
for val in instances_list:
if val['InstanceId'] != non_processed_id['InstanceId']:
ssmresponse = ssm.send_command(InstanceIds=[val['InstanceId']], DocumentName='AWS-RunShellScript', Parameters= { 'commands': [command]})

monitoring a text site (json) using python

IM working on a program to grab variant ID from this website
https://www.deadstock.ca/collections/new-arrivals/products/nike-air-max-1-cool-grey.json
Im using the code
import json
import requests
import time
endpoint = "https://www.deadstock.ca/collections/new-arrivals/products/nike-air-max-1-cool-grey.json"
req = requests.get(endpoint)
reqJson = json.loads(req.text)
for id in reqJson['product']:
name = (id['title'])
print (name)
I dont know what to do here in order to grab the Name of the items. If you visit the link you will see that the name is under 'title'. If you could help me with this that would be awesome.
I get the error message "TypeError: string indices must be integers" so im not too sure what to do.
Your biggest problem right now is that you are adding items to the list before you're checking if they're in it, so everything is coming back as in the list.
Looking at your code right now, I think what you want to do is combine things into a single for loop.
Also as a heads up you shouldn't use a variable name like list as it is shadowing the built-in Python function list().
list = [] # You really should change this to something else
def check_endpoint():
endpoint = ""
req = requests.get(endpoint)
reqJson = json.loads(req.text)
for id in reqJson['threads']: # For each id in threads list
PID = id['product']['globalPid'] # Get current PID
if PID in list:
print('checking for new products')
else:
title = (id['product']['title'])
Image = (id['product']['imageUrl'])
ReleaseType = (id['product']['selectionEngine'])
Time = (id['product']['effectiveInStockStartSellDate'])
send(title, PID, Image, ReleaseType, Time)
print ('added to database'.format(PID))
list.append(PID) # Add PID to the list
return
def main():
while(True):
check_endpoint()
time.sleep(20)
return
if __name__ == "__main__":
main()

Python variable substitution

I have a script that calls a list of linux guests I am trying to tidy up. Here is the code:
#!/usr/bin/python
guests = ['guest1','guest2','guest3','guest*']
def serverCheck(guestList)
for g in guestList:
server = AdminControl.completeObjectName('cell=tstenvironment,node=guest1,name=uatenvironment,type=Server,*')
try:
status = AdminControl.getAttribute(server, 'state')
print g + status
except:
print "Error %s is down." % g
serverCheck(guests)
The problem lies in this line:
server = AdminControl.completeObjectName('cell=Afcutst,node=%s,name=afcuuat1,type=Server,*') % g
How do I use my list to populate the node variable while still being able to pass the info within the parentheses to the AdminControl function?
The argument string itself is the argument to the % operator, not the return value of the function call.
server = AdminControl.completeObjectName(
'cell=Afcutst,node=%s,name=afcuuat1,type=Server,*' % (g,)
)
Peeking into the crystal ball, Python 3.6 will allow you to write
server = AdminControl.completeObjectName(
f'cell=Afcutst,node={g},name=afcuuat1,type=Server,*'
)
embedding the variable directly into a special format string literal.
can you try like this
AdminControl.completeObjectName('cell=tstenvironment,node=%s,name=uatenvironment,type=Server,*'%g)
For more readability I would suggest this and also using the same way to format strings from variables (here I chose str.format)
guests = ['guest1','guest2','guest3','guest*']
def serverCheck(guestList)
name_tpl = 'cell=tstenvironment,node={},name=uatenvironment,type=Server,*'
for g in guestList:
obj_name = name_tpl.format(g)
server = AdminControl.completeObjectName(obj_name)
try:
status = AdminControl.getAttribute(server, 'state')
print '{}: {}'.format(g, status)
except:
print 'Error {} is down'.format(g)
serverCheck(guests)

Categories

Resources