def rpc(module, items): responses = list() for item in items: name = item['name'] xattrs = item['xattrs'] fetch_config = False #args = item.get('args') text = item.get('text') #name = str(name).replace('_', '-') name = str(name) #if all((module.check_mode, not name.startswith('get'))): #module.fail_json(msg='invalid rpc for running in check_mode') if name == 'command' and text.startswith( 'show configuration') or name == 'get-configuration': fetch_config = True element = Element(name, xattrs) if text: element.text = text if fetch_config: reply = get_configuration(module, format=xattrs['format']) else: reply = send_request(module, element, ignore_warning=False) responses.append(tostring(reply)) return responses
def rpc(module, items): responses = list() for item in items: name = item['name'] xattrs = item['xattrs'] fetch_config = False text = item.get('text') name = str(name) if name == 'command' and text.startswith( 'show configuration') or name == 'get-configuration': fetch_config = True element = Element(name, xattrs) if text: element.text = text if fetch_config: reply = get_configuration(module, format=xattrs['format']) else: reply = send_request(module, element, ignore_warning=False) responses.append(tostring(reply)) return responses
def main(): """main entry point for Ansible module """ argument_spec = dict( rpc=dict(required=True), args=dict(type='dict'), output=dict(default='xml', choices=['xml', 'json', 'text']), ) argument_spec.update(junos_argument_spec) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False) warnings = list() check_args(module, warnings) result = {'changed': False, 'warnings': warnings} rpc = str(module.params['rpc']).replace('_', '-') if all((module.check_mode, not rpc.startswith('get'))): module.fail_json(msg='invalid rpc for running in check_mode') args = module.params['args'] or {} xattrs = {'format': module.params['output']} element = Element(module.params['rpc'], xattrs) for key, value in iteritems(args): key = str(key).replace('_', '-') if isinstance(value, list): for item in value: child = SubElement(element, key) if item is not True: child.text = item else: child = SubElement(element, key) if value is not True: child.text = value reply = send_request(module, element) result['xml'] = str(tostring(reply)) if module.params['output'] == 'text': data = reply.find('.//output') result['output'] = data.text.strip() result['output_lines'] = result['output'].split('\n') elif module.params['output'] == 'json': result['output'] = module.from_json(reply.text.strip()) else: result['output'] = str(tostring(reply)).split('\n') module.exit_json(**result)
def main(): """main entry point for Ansible module """ argument_spec = dict( rpc=dict(required=True), args=dict(type='dict'), output=dict(default='xml', choices=['xml', 'json', 'text']), ) argument_spec.update(junos_argument_spec) module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False) warnings = list() check_args(module, warnings) result = {'changed': False, 'warnings': warnings} rpc = str(module.params['rpc']).replace('_', '-') if all((module.check_mode, not rpc.startswith('get'))): module.fail_json(msg='invalid rpc for running in check_mode') args = module.params['args'] or {} xattrs = {'format': module.params['output']} element = Element(module.params['rpc'], xattrs) for key, value in iteritems(args): key = str(key).replace('_', '-') if isinstance(value, list): for item in value: child = SubElement(element, key) if item is not True: child.text = item else: child = SubElement(element, key) if value is not True: child.text = value reply = send_request(module, element) result['xml'] = str(tostring(reply)) if module.params['output'] == 'text': data = reply.find('.//output') result['output'] = data.text.strip() result['output_lines'] = result['output'].split('\n') elif module.params['output'] == 'json': result['output'] = module.from_json(reply.text.strip()) else: result['output'] = str(tostring(reply)).split('\n') module.exit_json(**result)
def get_configuration(module, compare=False, format='xml', rollback='0'): if format not in CONFIG_FORMATS: module.fail_json(msg='invalid config format specified') xattrs = {'format': format} if compare: _validate_rollback_id(module, rollback) xattrs['compare'] = 'rollback' xattrs['rollback'] = str(rollback) return send_request(module, Element('get-configuration', xattrs))
def get_configuration(module, compare=False, format='xml', rollback='0'): if format not in CONFIG_FORMATS: module.fail_json(msg='invalid config format specified') xattrs = {'format': format} if compare: _validate_rollback_id(module, rollback) xattrs['compare'] = 'rollback' xattrs['rollback'] = str(rollback) return send_request(module, Element('get-configuration', xattrs))
def commit_configuration(module, confirm=False, check=False, comment=None, confirm_timeout=None): obj = Element('commit-configuration') if confirm: SubElement(obj, 'confirmed') if check: SubElement(obj, 'check') if comment: subele = SubElement(obj, 'log') subele.text = str(comment) if confirm_timeout: subele = SubElement(obj, 'confirm-timeout') subele.text = str(confirm_timeout) return send_request(module, obj)
def commit_configuration(module, confirm=False, check=False, comment=None, confirm_timeout=None): obj = Element('commit-configuration') if confirm: SubElement(obj, 'confirmed') if check: SubElement(obj, 'check') if comment: subele = SubElement(obj, 'log') subele.text = str(comment) if confirm_timeout: subele = SubElement(obj, 'confirm-timeout') subele.text = str(confirm_timeout) return send_request(module, obj)
def load_configuration(module, candidate=None, action='merge', rollback=None, format='xml'): if all((candidate is None, rollback is None)): module.fail_json(msg='one of candidate or rollback must be specified') elif all((candidate is not None, rollback is not None)): module.fail_json(msg='candidate and rollback are mutually exclusive') if format not in FORMATS: module.fail_json(msg='invalid format specified') if format == 'json' and action not in JSON_ACTIONS: module.fail_json(msg='invalid action for format json') elif format in ('text', 'xml') and action not in ACTIONS: module.fail_json(msg='invalid action format %s' % format) if action == 'set' and not format == 'text': module.fail_json(msg='format must be text when action is set') if rollback is not None: _validate_rollback_id(module, rollback) xattrs = {'rollback': str(rollback)} else: xattrs = {'action': action, 'format': format} obj = Element('load-configuration', xattrs) if candidate is not None: lookup = { 'xml': 'configuration', 'text': 'configuration-text', 'set': 'configuration-set', 'json': 'configuration-json' } if action == 'set': cfg = SubElement(obj, 'configuration-set') else: cfg = SubElement(obj, lookup[format]) if isinstance(candidate, string_types): if format == 'xml': cfg.append(fromstring(candidate)) else: cfg.text = to_text(candidate, encoding='latin1') else: cfg.append(candidate) return send_request(module, obj)
def handle_purge(module, want): want_users = [item['name'] for item in want] element = Element('system') login = SubElement(element, 'login') reply = send_request(module, Element('get-configuration'), ignore_warning=False) users = reply.xpath('configuration/system/login/user/name') if users: for item in users: name = item.text if name not in want_users and name != 'root': user = SubElement(login, 'user', {'operation': 'delete'}) SubElement(user, 'name').text = name if element.xpath('/system/login/user/name'): return element
def commit_configuration(module, confirm=False, check=False, comment=None, confirm_timeout=None): obj = new_ele('commit-configuration') if confirm: sub_ele(obj, 'confirmed') if check: sub_ele(obj, 'check') if comment: children(obj, ('log', str(comment))) if confirm_timeout: children(obj, ('confirm-timeout', int(confirm_timeout))) return send_request(module, obj)
def rpc(module, items): responses = list() for item in items: name = item['name'] xattrs = item['xattrs'] args = item.get('args') text = item.get('text') name = str(name).replace('_', '-') if all((module.check_mode, not name.startswith('get'))): module.fail_json(msg='invalid rpc for running in check_mode') element = Element(name, xattrs) if text: element.text = text elif args: for key, value in iteritems(args): key = str(key).replace('_', '-') if isinstance(value, list): for item in value: child = SubElement(element, key) if item is not True: child.text = item else: child = SubElement(element, key) if value is not True: child.text = value reply = send_request(module, element) if xattrs['format'] == 'text': data = reply.find('.//output') responses.append(data.text.strip()) elif xattrs['format'] == 'json': responses.append(module.from_json(reply.text.strip())) else: responses.append(tostring(reply)) return responses
def handle_purge(module, want): want_users = [item['name'] for item in want] element = Element('system') login = SubElement(element, 'login') reply = send_request(module, Element('get-configuration'), ignore_warning=False) users = reply.xpath('configuration/system/login/user/name') if users: for item in users: name = item.text if name not in want_users and name != 'root': user = SubElement(login, 'user', {'operation': 'delete'}) SubElement(user, 'name').text = name if element.xpath('/system/login/user/name'): return element
def load_configuration(module, candidate=None, action='merge', rollback=None, format='xml'): if all((candidate is None, rollback is None)): module.fail_json(msg='one of candidate or rollback must be specified') elif all((candidate is not None, rollback is not None)): module.fail_json(msg='candidate and rollback are mutually exclusive') if format not in FORMATS: module.fail_json(msg='invalid format specified') if format == 'json' and action not in JSON_ACTIONS: module.fail_json(msg='invalid action for format json') elif format in ('text', 'xml') and action not in ACTIONS: module.fail_json(msg='invalid action format %s' % format) if action == 'set' and not format == 'text': module.fail_json(msg='format must be text when action is set') if rollback is not None: _validate_rollback_id(module, rollback) xattrs = {'rollback': str(rollback)} else: xattrs = {'action': action, 'format': format} obj = Element('load-configuration', xattrs) if candidate is not None: lookup = {'xml': 'configuration', 'text': 'configuration-text', 'set': 'configuration-set', 'json': 'configuration-json'} if action == 'set': cfg = SubElement(obj, 'configuration-set') else: cfg = SubElement(obj, lookup[format]) if isinstance(candidate, string_types): if format == 'xml': cfg.append(fromstring(candidate)) else: cfg.text = to_text(candidate, encoding='latin-1') else: cfg.append(candidate) return send_request(module, obj)
def populate(self): ele = Element('get-interface-information') SubElement(ele, 'detail') reply = send_request(self.module, ele) interfaces = {} for item in reply[0]: name = self.get_text(item, 'name') obj = { 'oper-status': self.get_text(item, 'oper-status'), 'admin-status': self.get_text(item, 'admin-status'), 'speed': self.get_text(item, 'speed'), 'macaddress': self.get_text(item, 'hardware-physical-address'), 'mtu': self.get_text(item, 'mtu'), 'type': self.get_text(item, 'if-type'), } interfaces[name] = obj self.facts['interfaces'] = interfaces
def populate(self): ele = Element('get-interface-information') SubElement(ele, 'detail') reply = send_request(self.module, ele) interfaces = {} for item in reply[0]: name = self.get_text(item, 'name') obj = { 'oper-status': self.get_text(item, 'oper-status'), 'admin-status': self.get_text(item, 'admin-status'), 'speed': self.get_text(item, 'speed'), 'macaddress': self.get_text(item, 'hardware-physical-address'), 'mtu': self.get_text(item, 'mtu'), 'type': self.get_text(item, 'if-type'), } interfaces[name] = obj self.facts['interfaces'] = interfaces
def unlock_configuration(x): return send_request(x, Element('unlock-configuration'))
def unlock_configuration(x): return send_request(x, Element('unlock-configuration'))
def command(module, command, format='text', rpc_only=False): xattrs = {'format': format} if rpc_only: command += ' | display xml rpc' xattrs['format'] = 'text' return send_request(module, Element('command', xattrs, text=command))
def rpc(self, rpc): return send_request(self.module, Element(rpc))
from ansible.module_utils.junos import check_args as junos_check_args from ansible.module_utils.netconf import send_request from ansible.module_utils.six import string_types USE_PERSISTENT_CONNECTION = True DEFAULT_COMMENT = 'configured by junos_config' def check_args(module, warnings): junos_check_args(module, warnings) if module.params['replace'] is not None: module.fail_json(msg='argument replace is deprecated, use update') zeroize = lambda x: send_request(x, ElementTree.Element('request-system-zeroize')) rollback = lambda x: get_diff(x) def guess_format(config): try: json.loads(config) return 'json' except ValueError: pass try: ElementTree.fromstring(config) return 'xml' except ElementTree.ParseError: pass
def zeroize(ele): return send_request(ele, Element('request-system-zeroize'))
subele.text = str(comment) if confirm_timeout: subele = SubElement(obj, 'confirm-timeout') subele.text = str(confirm_timeout) return send_request(module, obj) def command(module, command, format='text', rpc_only=False): xattrs = {'format': format} if rpc_only: command += ' | display xml rpc' xattrs['format'] = 'text' return send_request(module, Element('command', xattrs, text=command)) lock_configuration = lambda x: send_request(x, Element('lock-configuration')) unlock_configuration = lambda x: send_request(x, Element('unlock-configuration' )) @contextmanager def locked_config(module): try: lock_configuration(module) yield finally: unlock_configuration(module) def get_diff(module):
def zeroize(ele): return send_request(ele, Element('request-system-zeroize'))
def rpc(module, items): responses = list() for item in items: name = item['name'] xattrs = item['xattrs'] fetch_config = False args = item.get('args') text = item.get('text') name = str(name).replace('_', '-') if all((module.check_mode, not name.startswith('get'))): module.fail_json(msg='invalid rpc for running in check_mode') if name == 'command' and text.startswith('show configuration') or name == 'get-configuration': fetch_config = True element = Element(name, xattrs) if text: element.text = text elif args: for key, value in iteritems(args): key = str(key).replace('_', '-') if isinstance(value, list): for item in value: child = SubElement(element, key) if item is not True: child.text = item else: child = SubElement(element, key) if value is not True: child.text = value if fetch_config: reply = get_configuration(module, format=xattrs['format']) else: reply = send_request(module, element, ignore_warning=False) if xattrs['format'] == 'text': if fetch_config: data = reply.find('.//configuration-text') else: data = reply.find('.//output') if data is None: module.fail_json(msg=tostring(reply)) responses.append(data.text.strip()) elif xattrs['format'] == 'json': responses.append(module.from_json(reply.text.strip())) elif xattrs['format'] == 'set': data = reply.find('.//configuration-set') if data is None: module.fail_json(msg="Display format 'set' is not supported by remote device.") responses.append(data.text.strip()) else: responses.append(tostring(reply)) return responses
def main(): """ main entry point for module execution """ element_spec = dict( name=dict(), description=dict(), enabled=dict(default=True, type='bool'), speed=dict(), mtu=dict(type='int'), duplex=dict(choices=['full', 'half', 'auto']), tx_rate=dict(), rx_rate=dict(), delay=dict(default=10, type='int'), state=dict(default='present', choices=['present', 'absent', 'up', 'down']), active=dict(default=True, type='bool') ) aggregate_spec = deepcopy(element_spec) aggregate_spec['name'] = dict(required=True) # remove default in aggregate spec, to handle common arguments remove_default_spec(aggregate_spec) argument_spec = dict( aggregate=dict(type='list', elements='dict', options=aggregate_spec), ) argument_spec.update(element_spec) argument_spec.update(junos_argument_spec) required_one_of = [['name', 'aggregate']] mutually_exclusive = [['name', 'aggregate']] module = AnsibleModule(argument_spec=argument_spec, required_one_of=required_one_of, mutually_exclusive=mutually_exclusive, supports_check_mode=True) warnings = list() check_args(module, warnings) result = {'changed': False} if warnings: result['warnings'] = warnings top = 'interfaces/interface' param_to_xpath_map = collections.OrderedDict() param_to_xpath_map.update([ ('name', {'xpath': 'name', 'is_key': True}), ('description', 'description'), ('speed', 'speed'), ('mtu', 'mtu'), ('duplex', 'link-mode'), ('disable', {'xpath': 'disable', 'tag_only': True}) ]) choice_to_value_map = { 'link-mode': {'full': 'full-duplex', 'half': 'half-duplex', 'auto': 'automatic'} } params = to_param_list(module) requests = list() for param in params: # if key doesn't exist in the item, get it from module.params for key in param: if param.get(key) is None: param[key] = module.params[key] item = param.copy() state = item.get('state') item['disable'] = True if not item.get('enabled') else False if state in ('present', 'up', 'down'): item['state'] = 'present' validate_param_values(module, param_to_xpath_map, param=item) want = map_params_to_obj(module, param_to_xpath_map, param=item) requests.append(map_obj_to_ele(module, want, top, value_map=choice_to_value_map, param=item)) diff = None with locked_config(module): for req in requests: diff = load_config(module, tostring(req), warnings, action='merge') # issue commit after last configuration change is done commit = not module.check_mode if diff: if commit: commit_configuration(module) else: discard_changes(module) result['changed'] = True if module._diff: result['diff'] = {'prepared': diff} failed_conditions = [] for item in params: state = item.get('state') tx_rate = item.get('tx_rate') rx_rate = item.get('rx_rate') if state not in ('up', 'down') and tx_rate is None and rx_rate is None: continue element = Element('get-interface-information') intf_name = SubElement(element, 'interface-name') intf_name.text = item.get('name') if result['changed']: sleep(item.get('delay')) reply = send_request(module, element, ignore_warning=False) if state in ('up', 'down'): admin_status = reply.xpath('interface-information/physical-interface/admin-status') if not admin_status or not conditional(state, admin_status[0].text.strip()): failed_conditions.append('state ' + 'eq(%s)' % state) if tx_rate: output_bps = reply.xpath('interface-information/physical-interface/traffic-statistics/output-bps') if not output_bps or not conditional(tx_rate, output_bps[0].text.strip(), cast=int): failed_conditions.append('tx_rate ' + tx_rate) if rx_rate: input_bps = reply.xpath('interface-information/physical-interface/traffic-statistics/input-bps') if not input_bps or not conditional(rx_rate, input_bps[0].text.strip(), cast=int): failed_conditions.append('rx_rate ' + rx_rate) if failed_conditions: msg = 'One or more conditional statements have not be satisfied' module.fail_json(msg=msg, failed_conditions=failed_conditions) module.exit_json(**result)
def rpc(self, rpc): return send_request(self.module, Element(rpc))
def command(module, command, format='text', rpc_only=False): xattrs = {'format': format} if rpc_only: command += ' | display xml rpc' xattrs['format'] = 'text' return send_request(module, Element('command', xattrs, text=command))
check=False, comment=None, confirm_timeout=None): obj = new_ele('commit-configuration') if confirm: sub_ele(obj, 'confirmed') if check: sub_ele(obj, 'check') if comment: children(obj, ('log', str(comment))) if confirm_timeout: children(obj, ('confirm-timeout', int(confirm_timeout))) return send_request(module, obj) lock_configuration = lambda x: send_request(x, new_ele('lock-configuration')) unlock_configuration = lambda x: send_request(x, new_ele('unlock-configuration' )) @contextmanager def locked_config(module): try: lock_configuration(module) yield finally: unlock_configuration(module) def get_diff(module): reply = get_configuration(module, compare=True, format='text')
def rpc(module, items): responses = list() for item in items: name = item['name'] xattrs = item['xattrs'] fetch_config = False args = item.get('args') text = item.get('text') name = str(name).replace('_', '-') if all((module.check_mode, not name.startswith('get'))): module.fail_json(msg='invalid rpc for running in check_mode') if name == 'command' and text.startswith('show configuration') or name == 'get-configuration': fetch_config = True element = Element(name, xattrs) if text: element.text = text elif args: for key, value in iteritems(args): key = str(key).replace('_', '-') if isinstance(value, list): for item in value: child = SubElement(element, key) if item is not True: child.text = item else: child = SubElement(element, key) if value is not True: child.text = value if fetch_config: reply = get_configuration(module, format=xattrs['format']) else: reply = send_request(module, element, ignore_warning=False) if xattrs['format'] == 'text': if fetch_config: data = reply.find('.//configuration-text') else: data = reply.find('.//output') if data is None: module.fail_json(msg=tostring(reply)) responses.append(data.text.strip()) elif xattrs['format'] == 'json': responses.append(module.from_json(reply.text.strip())) elif xattrs['format'] == 'set': data = reply.find('.//configuration-set') if data is None: module.fail_json(msg="Display format 'set' is not supported by remote device.") responses.append(data.text.strip()) else: responses.append(tostring(reply)) return responses
def main(): """ main entry point for module execution """ neighbors_spec = dict( host=dict(), port=dict() ) element_spec = dict( name=dict(), description=dict(), enabled=dict(default=True, type='bool'), speed=dict(), mtu=dict(type='int'), duplex=dict(choices=['full', 'half', 'auto']), tx_rate=dict(), rx_rate=dict(), neighbors=dict(type='list', elements='dict', options=neighbors_spec), delay=dict(default=10, type='int'), state=dict(default='present', choices=['present', 'absent', 'up', 'down']), active=dict(default=True, type='bool') ) aggregate_spec = deepcopy(element_spec) aggregate_spec['name'] = dict(required=True) # remove default in aggregate spec, to handle common arguments remove_default_spec(aggregate_spec) argument_spec = dict( aggregate=dict(type='list', elements='dict', options=aggregate_spec), ) argument_spec.update(element_spec) argument_spec.update(junos_argument_spec) required_one_of = [['name', 'aggregate']] mutually_exclusive = [['name', 'aggregate']] module = AnsibleModule(argument_spec=argument_spec, required_one_of=required_one_of, mutually_exclusive=mutually_exclusive, supports_check_mode=True) warnings = list() check_args(module, warnings) result = {'changed': False} if warnings: result['warnings'] = warnings top = 'interfaces/interface' param_to_xpath_map = collections.OrderedDict() param_to_xpath_map.update([ ('name', {'xpath': 'name', 'is_key': True}), ('description', 'description'), ('speed', 'speed'), ('mtu', 'mtu'), ('duplex', 'link-mode'), ('disable', {'xpath': 'disable', 'tag_only': True}) ]) choice_to_value_map = { 'link-mode': {'full': 'full-duplex', 'half': 'half-duplex', 'auto': 'automatic'} } params = to_param_list(module) requests = list() for param in params: # if key doesn't exist in the item, get it from module.params for key in param: if param.get(key) is None: param[key] = module.params[key] item = param.copy() state = item.get('state') item['disable'] = True if not item.get('enabled') else False if state in ('present', 'up', 'down'): item['state'] = 'present' validate_param_values(module, param_to_xpath_map, param=item) want = map_params_to_obj(module, param_to_xpath_map, param=item) requests.append(map_obj_to_ele(module, want, top, value_map=choice_to_value_map, param=item)) diff = None with locked_config(module): for req in requests: diff = load_config(module, tostring(req), warnings, action='merge') # issue commit after last configuration change is done commit = not module.check_mode if diff: if commit: commit_configuration(module) else: discard_changes(module) result['changed'] = True if module._diff: result['diff'] = {'prepared': diff} failed_conditions = [] neighbors = None for item in params: state = item.get('state') tx_rate = item.get('tx_rate') rx_rate = item.get('rx_rate') want_neighbors = item.get('neighbors') if state not in ('up', 'down') and tx_rate is None and rx_rate is None and want_neighbors is None: continue element = Element('get-interface-information') intf_name = SubElement(element, 'interface-name') intf_name.text = item.get('name') if result['changed']: sleep(item.get('delay')) reply = send_request(module, element, ignore_warning=False) if state in ('up', 'down'): admin_status = reply.xpath('interface-information/physical-interface/admin-status') if not admin_status or not conditional(state, admin_status[0].text.strip()): failed_conditions.append('state ' + 'eq(%s)' % state) if tx_rate: output_bps = reply.xpath('interface-information/physical-interface/traffic-statistics/output-bps') if not output_bps or not conditional(tx_rate, output_bps[0].text.strip(), cast=int): failed_conditions.append('tx_rate ' + tx_rate) if rx_rate: input_bps = reply.xpath('interface-information/physical-interface/traffic-statistics/input-bps') if not input_bps or not conditional(rx_rate, input_bps[0].text.strip(), cast=int): failed_conditions.append('rx_rate ' + rx_rate) if want_neighbors: if neighbors is None: element = Element('get-lldp-interface-neighbors') intf_name = SubElement(element, 'interface-device') intf_name.text = item.get('name') reply = send_request(module, element, ignore_warning=False) have_host = [item.text for item in reply.xpath('lldp-neighbors-information/lldp-neighbor-information/lldp-remote-system-name')] have_port = [item.text for item in reply.xpath('lldp-neighbors-information/lldp-neighbor-information/lldp-remote-port-id')] for neighbor in want_neighbors: host = neighbor.get('host') port = neighbor.get('port') if host and host not in have_host: failed_conditions.append('host ' + host) if port and port not in have_port: failed_conditions.append('port ' + port) if failed_conditions: msg = 'One or more conditional statements have not be satisfied' module.fail_json(msg=msg, failed_conditions=failed_conditions) module.exit_json(**result)