'''
Created on Apr 12, 2015
@author: Puneet Garg
Copyright (c) 2015 by Cisco Systems, Inc.
All rights reserved.
Classes used for device request and response parser utilities.
'''
from devpkg.utils.util import asciistr
from devpkg.base.command_interaction import CommandResult, CommandInteraction, CommandParam
from devpkg.base.command_dispatch import TokenObjectHelper
from devpkg.base.command_interaction import item_does_not_exist_error
import requests, traceback
import devpkg.utils.env as env
from requests.auth import HTTPBasicAuth
from devpkg.base.requestexecutor.login_executor import LoginExecutor
from devpkg.base.requestexecutor.login_executor import save_device_information
import json
from devpkg.utils.state_type import State
from devpkg.utils.errors import FaultCode, FMC429Error
import re
from devpkg.utils.util import sleep
from devpkg.utils.errors import DeviceConfigError
from random import randint
from fmc.config_keeper import ConfigKeeper
from ftd.networks import Networks
from ftd.hosts import Hosts
import selective_probe
import time
'''
GET/POST Globals
'''
GET = "GET"
POST= "POST"
DELETE = "DELETE"
PUT = "PUT"
'''
Requests Basic functions.
'''
def get_by_name_and_store(response, name, target, store):
try:
items = response.json()['items']
for item in items:
if item['name'] == name:
store.param_value = item
store.param_uuid = store.param_value
return item[target]
except:
pass
def get_device_uuid(command_executor, force=False):
"""
Used by the LoginExecutor
Gets the device uuid and sets it into TOKEN
"""
probe = command_executor.probe
if force or probe is None or isinstance(probe, list) or len(probe.config_keeper.get(command_executor.dispatch.device_ip + ':' + probe.ldev_id + ':' + 'device_uuid')) == 0:
command_result = CommandResult(
cli='Devices',
err_type='conn_error',
err_msg=None,
model_key='host')
command_result.resource = command_executor.dispatch
command_result.resource_key = 'device_uuid'
command_executor.command_holder.param_value = command_executor.dispatch.device_ip
command_executor.command_holder.postexecute = item_does_not_exist_error
params = "?expanded=true&hostName=%s" % command_executor.dispatch.device_ip
command_executor.command_holder.name = command_executor.dispatch.device_ip
url = command_executor.dispatch.url + command_executor.command_holder.get_url(url='fmc_config/v1/domain/<domainUUID>/devices/devicerecords', domainUUID=command_executor.dispatch.domain_uuid)
command_executor.command_holder.response_parser = save_device_information
command_executor.command_holder.response_parser_arg = {"command_executor" : command_executor}
return execute_request(command_executor, url, params, command_result, GET)[0]
else:
ldev = probe.ldev_id
device_uuid = probe.config_keeper.get(command_executor.dispatch.device_ip + ':' + ldev + ':' + 'device_uuid')
device_name = probe.config_keeper.get(command_executor.dispatch.device_ip + ':' + ldev + ':' + 'device_name')
if len(device_uuid) > 0 and len(device_name) > 0:
command_executor.dispatch.device_uuid = device_uuid
command_executor.dispatch.device_name = device_name
command_executor.command_holder.param_uuid = device_uuid
return [None]
else:
print("404xxxdevice, unable to get device_uuid, which should have been saved by login_executor.")
def k2v_json(toFind, data):
"""
find the value of a certain key if you dont know where the key is in a nested dict.Like a json
@param toFind: string that needs to be found in the json. is the key
@param data: the json that we are looking in
"""
found = None
if isinstance(data, dict):
for k, v in data.iteritems():
if k == toFind:
return v
else:
t = k2v_json(toFind, v)
if t is not None:
found = t
break
if isinstance(data, list):
for v in data:
t = k2v_json(toFind, v)
if t is not None:
found = t
break
return found
def is_cifs_etherchannel(config):
''' Check if Ether-channel (aka Port-channel) is used as cifs
'''
intf_d = k2v_json('cifs', config) # e.g. INPUT: 'cifs': {'dev6': 'Port-channel3'}, OUTPUT: {'dev6': 'Port-channel3'}
if intf_d is None or len(intf_d) == 0:
return False
for k, v in intf_d.iteritems():
return v.startswith('Port-channel')
def generate_request_url(command_executor):
return command_executor.dispatch.url + command_executor.command_holder.get_url(domainUUID=command_executor.dispatch.domain_uuid, deviceUUID=command_executor.dispatch.device_uuid)
def return_json(response, *args, **kwargs):
return response.json()
def parse_response_for_target(response, target):
"""
Finds the target within the response
@param response: the response object from a request command
@param target: a string that tries the find data associated with it. EX: target = 'id' will find the data for id
@return: string of the target found or None if nothing is found
"""
response_json = response.json()
if response_json.has_key('items'):
try:
response_json = response_json['items'][0]
except Exception as e:
env.debug("Unexpected exception: " + asciistr(e) + '\n' + traceback.format_exc())
if response_json.has_key("metadata"):
del response_json['metadata']
if response_json.has_key("defaultAction"):
del response_json['defaultAction']
try:
return response_json[target]
except:
return k2v_json(target, response_json)
def parse_response_for_target_in_header(response, target):
"""
Used internally
Finds the target in the response header
@param response: the response object from a request command
@param target: a string that tries to find data associated with it
@return: string of the target found or None if nothing is found
"""
try:
return response.headers[target]
except Exception as e:
env.debug("Unexpected exception: " + asciistr(e) + '\n' + traceback.format_exc())
return None
def parse_response_for_target_and_store_json(response, target, store):
"""
Parses the response for the target then stores the response into store
@param response: the response object from a request command
@param target: a string that tries to find data associated with it
@param store: the ParamCommand that the data will be stored in.
@return: string of the target found or None if nothing is found
"""
try:
json_data = return_json(response)
if json_data.has_key('items'):
if len(json_data['items']) == 1:
store.param_uuid = json_data['items'][0]
else:
store.param_uuid = json_data
else:
store.param_uuid = json_data
store.param_value = store.param_uuid
uuid = json_data['items'][0][target]
if uuid is None:
store.param_uuid = None
store.param_value = None
return uuid
except:
uuid = parse_response_for_target(response, target)
if uuid is None:
store.param_uuid = None
store.param_value = None
return uuid
def execute_request(command_executor, url = None, params = None, command_result = None, request_type = "GET", deploy_request = False):
"""
Executes the command_executor
@param command_executor: the CommandExecutor object
@param url: the url being PUT/POST/GET/DELETE/etc to
@param params: if a PUT/POST the paramaters bein