diff --git a/vmanage/api/device.py b/vmanage/api/device.py index b7e0e6e..bcc3676 100644 --- a/vmanage/api/device.py +++ b/vmanage/api/device.py @@ -1,6 +1,7 @@ """Cisco vManage Device Inventory API Methods. """ +import re from vmanage.api.http_methods import HttpMethods from vmanage.data.parse_methods import ParseMethods from vmanage.utils import list_to_dict @@ -28,6 +29,30 @@ def __init__(self, session, host, port=443): self.port = port self.base_url = f'https://{self.host}:{self.port}/dataservice/' + def generate_bootstrap(self, uuid): + """Generate a bootstrap file for a device + + Args: + uuid (str): uuid of device + + Returns: + result (dict): All bootstrap data + """ + + url = f"{self.base_url}system/device/bootstrap/device/{uuid}?configtype=cloudinit" + response = HttpMethods(self.session, url).request('GET') + #result = ParseMethods.parse_data(response) + #bootstrap_config = result.json['bootstrapConfig'] + bootstrap_config = response['json']['bootstrapConfig'] + regex = re.compile(r'otp : (?P[a-z0-9]+)[^a-z0-9]') + match = regex.search(bootstrap_config) + if match: + otp = match.groups('otp')[0] + else: + otp = None + return_dict = {'bootstrapConfig': bootstrap_config, 'otp': otp, 'uuid': uuid} + return return_dict + def get_device_list(self, category): """Obtain a list of specified device type @@ -59,6 +84,34 @@ def post_device_cli_mode(self, deviceId, deviceType): result = ParseMethods.parse_status(response) return result + def get_device_ping(self, systemip, vpn, sourceip, destip): + """Ping a specified destination ip address + + Args: + systemip (str): systemip of source device + vpn (str): vpn id of source + sourceip (str): source ip address + destip (str): destination ip address + + + Returns: + result (str): ping response time + """ + + #api = f"device/tools/nping/{systemip}" + #url = self.base_url + api + url = f"{self.base_url}device/tools/nping/{systemip}" + payload = f"{{'host':'{destip}', 'vpn':'{vpn}', 'source':'{sourceip}', 'probetype':'icmp'}}" + response = HttpMethods(self.session, url).request('POST', payload=payload) + if response['json']: + #if response['status_code']==200: + result = response['json'] + else: + result = response['details'] + return result + #result = ParseMethods.parse_data(response) + #return result + def get_device_status_list(self): """Obtain a list of specified device type @@ -211,12 +264,20 @@ def post_device(self, device_ip, personality, username, password): """Add control plane device Args: - device_id (str): uuid for device object + device_ip (str): device interface IP + personality (str): controller type (vmanage, vsmart, vbond) + username (str): device username + password (str): device password Returns: result (list): Device status """ - + url = f"{self.base_url}system/device" + payload = f"{{'deviceIP':'{device_ip}','username':'{username}','password':'{password}','personality':'{personality}','generateCSR':'false'}}" + response = HttpMethods(self.session, url).request('POST', payload=payload,timeout=35) + result = ParseMethods.parse_status(response) + return result + def post_reset_interface(self, device_ip, vpn_id, ifname): """Reset an Interface Args: diff --git a/vmanage/api/device_templates.py b/vmanage/api/device_templates.py index 6464e16..6ce8f93 100644 --- a/vmanage/api/device_templates.py +++ b/vmanage/api/device_templates.py @@ -184,13 +184,15 @@ def get_template_input(self, template_id, device_id_list=None): if 'header' in response['json'] and 'columns' in response['json']['header']: column_list = response['json']['header']['columns'] - regex = re.compile(r'\((?P[^(]+)\)') + prod1 = re.compile(r"(?P.*)\((?P.*)\)") for column in column_list: if column['editable']: - match = regex.search(column['title']) - if match: - variable = match.groups('variable')[0] + m = prod1.match(column['title']) + if m: + intdict = m.groupdict() + titledesc = intdict['titledesc'] + variable = titledesc else: # If the variable is not found, use toolTip as variable name variable = column.get("toolTip") diff --git a/vmanage/api/notifications.py b/vmanage/api/notifications.py new file mode 100644 index 0000000..c4d6886 --- /dev/null +++ b/vmanage/api/notifications.py @@ -0,0 +1,41 @@ +"""Cisco vManage Notifications API Methods. +""" + +from vmanage.api.http_methods import HttpMethods +from vmanage.data.parse_methods import ParseMethods + + +class Notifications(object): + """Access to Notificaton rules. + + vManage can generate notificatons. This class allows you to + read these notifications. + + """ + def __init__(self, session, host, port=443): + """Initialize Notifications object with session parameters. + + Args: + session (obj): Requests Session object + host (str): hostname or IP address of vManage + port (int): default HTTPS 443 + + """ + + self.session = session + self.host = host + self.port = port + self.base_url = f'https://{self.host}:{self.port}/dataservice/' + + def get_notification_rules(self): + """Provides notification rules + + Returns: + result (dict): All data associated with a response. + """ + + api = "notifications/rules" + url = self.base_url + api + response = HttpMethods(self.session, url).request('GET') + result = ParseMethods.parse_data(response) + return result diff --git a/vmanage/cli/deactivate/central_policy.py b/vmanage/cli/deactivate/central_policy.py index 1ec0eb6..3b68b11 100644 --- a/vmanage/cli/deactivate/central_policy.py +++ b/vmanage/cli/deactivate/central_policy.py @@ -7,7 +7,7 @@ @click.option('--name', '-n', help="Name of policy to deactivate.") @click.option('--id', '-i', help="Id of policy to deactivate.") @click.pass_obj -def central_policy(ctx, name, id): +def central_policy(ctx, name, cpid): """ deactivate Central Policy """ @@ -15,8 +15,8 @@ def central_policy(ctx, name, id): vmanage_central_policy = CentralPolicy(ctx.auth, ctx.host, ctx.port) vmanage_utilities = Utilities(ctx.auth, ctx.host, ctx.port) central_policy_dict = vmanage_central_policy.get_central_policy_dict(remove_key=True) - if id: - vmanage_central_policy.deactivate_central_policy(id) + if cpid: + vmanage_central_policy.deactivate_central_policy(cpid) elif name: if name in central_policy_dict: click.echo(f'Deactivating Central Policy {name}') diff --git a/vmanage/cli/decommission/device.py b/vmanage/cli/decommission/device.py index e820fae..8de37d9 100644 --- a/vmanage/cli/decommission/device.py +++ b/vmanage/cli/decommission/device.py @@ -5,14 +5,14 @@ @click.command('device') @click.argument('device', required=True) @click.pass_obj -def device(ctx, device): +def device(ctx, decommdevice): """ Decommission device """ vmanage_device = Device(ctx.auth, ctx.host, ctx.port) - status = vmanage_device.get_device_status(device, key='host-name') + status = vmanage_device.get_device_status(decommdevice, key='host-name') if 'uuid' in status: vmanage_device.put_device_decommission(status['uuid']) else: - click.secho(f'Cannot find UUID for device {device}', fg="red") + click.secho(f'Cannot find UUID for device {decommdevice}', fg="red") diff --git a/vmanage/cli/reset/__init__.py b/vmanage/cli/reset/__init__.py index 199fa95..9aa2446 100644 --- a/vmanage/cli/reset/__init__.py +++ b/vmanage/cli/reset/__init__.py @@ -2,7 +2,6 @@ from vmanage.cli.reset.interface import interface - @click.group('reset') def reset(): """ diff --git a/vmanage/data/policy_data.py b/vmanage/data/policy_data.py index 6d67f9d..d5fab6d 100644 --- a/vmanage/data/policy_data.py +++ b/vmanage/data/policy_data.py @@ -171,6 +171,7 @@ def convert_list_id_to_name(self, id_list): id_list (list): Object """ + #print("DEBUG:",id_list) if isinstance(id_list, dict): for key, value in list(id_list.items()): if key.endswith( @@ -211,6 +212,7 @@ def convert_list_id_to_name(self, id_list): id_list['listType'] = policy_list['type'] id_list.pop('ref') else: + #print("DEBUG:",id_list) raise RuntimeError(f"Could not find name for list {id_list['ref']}") elif key == 'class': policy_list = self.policy_lists.get_policy_list_by_id(id_list['class']) @@ -340,6 +342,8 @@ def export_policy_definition_list(self, definition_type='all'): policy_definition_list = self.policy_definitions.get_policy_definition_list(definition_type) export_definition_list = [] for policy_definition in policy_definition_list: + #print("DEBUG: ",policy_definition) + #print("") definition_detail = self.policy_definitions.get_policy_definition(policy_definition['type'], policy_definition['definitionId']) converted_policy_definition = self.convert_policy_definition_to_name(definition_detail) diff --git a/vmanage/data/template_data.py b/vmanage/data/template_data.py index 910831f..e8e5f2c 100644 --- a/vmanage/data/template_data.py +++ b/vmanage/data/template_data.py @@ -337,16 +337,25 @@ def import_attachment_list(self, attachment_list, check_mode=False, update=False # the input changed, so we make an API call to get the input on last attach existing_template_input = self.device_templates.get_template_input( device_template_dict[attachment['template']]['templateId'], [device_uuid]) - current_variables = existing_template_input['data'][0] + #current_variables = existing_template_input['data'][0] + current_variables = {} + data = existing_template_input['data'][0] + for column in existing_template_input['columns']: + current_variables[column['variable']] = data[column['property']] + #print("DEBUG: current_variables: ",current_variables) + # haven't changed variables from properties to variables + # changed = False for property_name in attachment['variables']: - # Check to see if any of the passed in varibles have changed from what is + #print("DEBUG: checking: ",property_name) + # Check to see if any of the passed in variables have changed from what is # already on the attachment. We are are not checking to see if the # correct variables are here. That will be done on attachment. if ((property_name in current_variables) and (str(attachment['variables'][property_name]) != str(current_variables[property_name]))): changed = True if changed: + print("Changed!!!") if not check_mode and update: template_device_map.setdefault(template_id, []).append({ "config_type": config_type,