def discover(self): """ Call methods in specific order to build resources and attributes :return: """ try: enable_snmp = get_attribute_by_name('Enable SNMP').lower() == 'true' disable_snmp = get_attribute_by_name('Disable SNMP').lower() == 'true' except Exception: enable_snmp = True disable_snmp = False if enable_snmp: self.enable_snmp() if not self._is_valid_device_os(): raise Exception(self.__class__.__name__, 'Unsupported device OS') try: self._build_root() self._build_chassis() self._build_power_modules() self._build_modules() self._build_sub_modules() self._build_ports() autoload_details = self._root.get_autoload_details() self._log_autoload_details(autoload_details) finally: if disable_snmp: self.disable_snmp() return autoload_details
def get_path(self, path=''): if not path: host = get_attribute_by_name('Backup Location') if ':' not in host: scheme = get_attribute_by_name('Backup Type') scheme = re.sub('(:|/+).*$', '', scheme, re.DOTALL) host = re.sub('^/+', '', host) host = '{}://{}'.format(scheme, host) path = host url = UrlParser.parse_url(path) if UrlParser.SCHEME not in url or not url[UrlParser.SCHEME]: raise Exception('ConfigurationOperations', "Backup Type is wrong or empty") if url[UrlParser.SCHEME].lower() in self.AUTHORIZATION_REQUIRED_STORAGES: if UrlParser.USERNAME not in url or not url[UrlParser.USERNAME]: url[UrlParser.USERNAME] = get_attribute_by_name('Backup User') if UrlParser.PASSWORD not in url or not url[UrlParser.PASSWORD]: url[UrlParser.PASSWORD] = decrypt_password(get_attribute_by_name('Backup Password')) try: result = UrlParser.build_url(url) except Exception as e: self.logger.error('Failed to build url: {}'.format(e)) raise Exception('ConfigurationOperations', 'Failed to build path url to remote host') return result
def save(self, context, folder_path, configuration_type, vrf_management_name): """Save selected file to the provided destination :param ResourceCommandContext context: ResourceCommandContext object with all Resource Attributes inside :param configuration_type: source file, which will be saved :param folder_path: destination path where file will be saved :param vrf_management_name: VRF management Name :return str saved configuration file name: """ if not configuration_type: configuration_type = 'running' if not vrf_management_name: vrf_management_name = get_attribute_by_name(context=context, attribute_name='VRF Management Name') logger = get_logger_with_thread_id(context) api = get_api(context) configuration_operations = ConfigurationRunner(logger=logger, cli=self._cli, context=context, api=api) logger.info('Save started') response = configuration_operations.save(folder_path=folder_path, configuration_type=configuration_type, vrf_management_name=vrf_management_name) logger.info('Save completed') return response
def initialize(self, context): """Initialize method :type context: cloudshell.shell.core.context.driver_context.InitCommandContext """ session_pool_size = int(get_attribute_by_name(context=context, attribute_name='Sessions Concurrency Limit')) self._cli = get_cli(session_pool_size) return 'Finished initializing'
def restore(self, context, path, configuration_type, restore_method, vrf_management_name): """Restore selected file to the provided destination :param ResourceCommandContext context: ResourceCommandContext object with all Resource Attributes inside :param path: source config file :param configuration_type: running or startup configs :param restore_method: append or override methods :param vrf_management_name: VRF management Name """ if not configuration_type: configuration_type = 'running' if not restore_method: restore_method = 'override' if not vrf_management_name: vrf_management_name = get_attribute_by_name(context=context, attribute_name='VRF Management Name') logger = get_logger_with_thread_id(context) api = get_api(context) configuration_operations = ConfigurationRunner(logger=logger, api=api, cli=self._cli, context=context) logger.info('Restore started') configuration_operations.restore(path=path, restore_method=restore_method, configuration_type=configuration_type, vrf_management_name=vrf_management_name) logger.info('Restore completed')
def discover(self): try: self._enable_snmp = (get_attribute_by_name('Enable SNMP') or 'true').lower() == 'true' self._disable_snmp = (get_attribute_by_name('Disable SNMP') or 'false').lower() == 'true' except: pass if self._enable_snmp: self.enable_snmp() try: result = self.get_autoload_details() except Exception as e: self.logger.error('Autoload failed: {0}'.format(e.message)) raise Exception('EricssonGenericSNMPAutoload', e.message) finally: if self._disable_snmp: self.disable_snmp() return result
def save_configuration(self, destination_host, source_filename, vrf=None): system_name = self.context.resource.fullname system_name = re.sub(r'[\.\s]', '_', system_name) if source_filename and source_filename.lower() == 'running': config_type = 'config' else: raise Exception(self.__class__.__name__, 'Device does not support saving \"{}\" configuration type, \"running\" ' 'is only supported'.format(source_filename or 'None')) file_name = "{0}-{1}-{2}".format(system_name, source_filename, time.strftime("%d%m%y-%H%M%S", time.localtime())) if not destination_host: backup_location = get_attribute_by_name('Backup Location') if not backup_location: raise Exception('AireOSOperations', "Backup location or path is empty") else: backup_location = destination_host if not backup_location.endswith('/'): backup_location += '/' destination_dict = UrlParser.parse_url(backup_location) if not destination_dict: raise Exception('AireOSOperations', 'Incorrect Backup location') self.logger.debug('Connection dict: ' + str(destination_dict)) save_flow = OrderedDict() save_flow[save_restore.SAVE_CONFIGURATION_DATATYPE] = config_type save_flow[save_restore.SAVE_CONFIGURATION_FILENAME] = file_name template_flow = OrderedDict() template_flow[save_restore.SAVE_CONFIGURATION_MODE] = UrlParser.SCHEME template_flow[save_restore.SAVE_CONFIGURATION_SERVERIP] = UrlParser.HOSTNAME template_flow[save_restore.SAVE_CONFIGURATION_PATH] = UrlParser.PATH template_flow[save_restore.SAVE_CONFIGURATION_USER] = UrlParser.USERNAME template_flow[save_restore.SAVE_CONFIGURATION_PASSWORD] = UrlParser.PASSWORD template_flow[save_restore.SAVE_CONFIGURATION_PORT] = UrlParser.PORT generated_flow = self._generate_flow(template_flow, destination_dict) if save_restore.SAVE_CONFIGURATION_PATH not in generated_flow: generated_flow[save_restore.SAVE_CONFIGURATION_PATH] = '/' save_flow.update(generated_flow) execute_command_map(save_flow, self.cli_service.send_command) expected_map = OrderedDict({r'[yY]/[nN]': lambda session: session.send_line('y')}) error_map = OrderedDict({r'[Ee]rror:': 'Save configuration error, see logs for details'}) self.cli_service.send_command(save_restore.SAVE_CONFIGURATION_START.get_command(), expected_map=expected_map, error_map=error_map) return file_name
def copy(self, source_file='', destination_file='', vrf=None, timeout=600, retries=5): """Copy file from device to tftp or vice versa, as well as copying inside devices filesystem :param source_file: source file. :param destination_file: destination file. :return tuple(True or False, 'Success or Error message') """ if not vrf: vrf = get_attribute_by_name('VRF Management Name') host = None expected_map = OrderedDict() if '://' in source_file: source_file_data_list = re.sub('/+', '/', source_file).split('/') host = source_file_data_list[1] expected_map[r'[^/]{}'.format(source_file_data_list[-1])] = lambda session: session.send_line('') expected_map[r'[^/]{}'.format(destination_file)] = lambda session: session.send_line('') elif '://' in destination_file: destination_file_data_list = re.sub('/+', '/', destination_file).split('/') host = destination_file_data_list[1] expected_map[r'[^/]{}'.format(destination_file_data_list[-1])] = lambda session: session.send_line('') expected_map[r'[^/]{}'.format(source_file)] = lambda session: session.send_line('') else: expected_map[r'[^/]{}'.format(destination_file)] = lambda session: session.send_line('') expected_map[r'[^/]{}'.format(source_file)] = lambda session: session.send_line('') if host and not validateIP(host): raise Exception('Cisco OS', 'Copy method: \'{}\' is not valid remote ip.'.format(host)) copy_command_str = 'copy {0} {1}'.format(source_file, destination_file) if vrf: copy_command_str += ' vrf {}'.format(vrf) if host: expected_map[r"[^/]{}".format(host)] = lambda session: session.send_line('') expected_map[r'\s+[Vv][Rr][Ff]\s+'] = lambda session: session.send_line('') expected_map[r'\[confirm\]'] = lambda session: session.send_line('') expected_map[r'\(y/n\)'] = lambda session: session.send_line('y') expected_map[r'\([Yy]es/[Nn]o\)'] = lambda session: session.send_line('yes') expected_map[r'\?'] = lambda session: session.send_line('') expected_map[r'bytes'] = lambda session: session.send_line('') output = self.cli.send_command(command=copy_command_str, expected_map=expected_map, timeout=60) output += self.cli.send_command('') return self._check_download_from_tftp(output)
def save_configuration(self, destination_host, source_filename, vrf=None): """Backup 'startup-config' or 'running-config' from device to provided file_system [ftp|tftp] Also possible to backup config to localhost :param destination_host: tftp/ftp server where file be saved :param source_filename: what file to backup :return: status message / exception """ if source_filename == '': source_filename = 'running-config' if '-config' not in source_filename: source_filename = source_filename.lower() + '-config' if ('startup' not in source_filename) and ('running' not in source_filename): raise Exception('Cisco OS', "Source filename must be 'startup' or 'running'!") if not destination_host: destination_host = get_attribute_by_name('Backup Location') if not destination_host: raise Exception('Cisco OS', "Backup location or path is empty") system_name = re.sub('\s+', '_', self.resource_name) if len(system_name) > 23: system_name = system_name[:23] destination_filename = '{0}-{1}-{2}'.format(system_name, source_filename.replace('-config', ''), _get_time_stamp()) self.logger.info('destination filename is {0}'.format(destination_filename)) if len(destination_host) <= 0: destination_host = self._get_resource_attribute(self.resource_name, 'Backup Location') if len(destination_host) <= 0: raise Exception('Folder path and Backup Location are empty.') if destination_host.endswith('/'): destination_file = destination_host + destination_filename else: destination_file = destination_host + '/' + destination_filename is_uploaded = self.copy(destination_file=destination_file, source_file=source_filename, vrf=vrf) if is_uploaded[0] is True: self.logger.info('Save configuration completed.') return '{0},'.format(destination_filename) else: # self.logger.info('is_uploaded = {}'.format(is_uploaded)) self.logger.info('Save configuration failed with errors: {0}'.format(is_uploaded[1])) raise Exception(is_uploaded[1])
def update_firmware(self, context, remote_host, file_path): """Upload and updates firmware on the resource :param remote_host: path to firmware file location on ftp or tftp server :param file_path: firmware file name :return: result :rtype: str """ logger = get_logger_with_thread_id(context) api = get_api(context) vrf_management_name = get_attribute_by_name(context=context, attribute_name='VRF Management Name') logger.info('Start Update Firmware') firmware_operations = FirmwareRunner(cli=self._cli, logger=logger, context=context, api=api) response = firmware_operations.load_firmware(path=remote_host, vrf_management_name=vrf_management_name) logger.info('Finish Update Firmware: {}'.format(response))
def load_firmware(self, context, path, vrf_management_name): """Upload and updates firmware on the resource :param ResourceCommandContext context: ResourceCommandContext object with all Resource Attributes inside :param path: full path to firmware file, i.e. tftp://10.10.10.1/firmware.tar :param vrf_management_name: VRF management Name """ logger = get_logger_with_thread_id(context) api = get_api(context) if not vrf_management_name: vrf_management_name = get_attribute_by_name(context=context, attribute_name='VRF Management Name') logger.info('Start Load Firmware') firmware_operations = FirmwareRunner(cli=self._cli, logger=logger, context=context, api=api) response = firmware_operations.load_firmware(path=path, vrf_management_name=vrf_management_name) logger.info('Finish Load Firmware: {}'.format(response))
def __init__(self, snmp_handler=None, logger=None, supported_os=None, cli=None, snmp_community=None): """Basic init with injected snmp handler and logger :param snmp_handler: :param logger: :return: """ EricssonGenericSNMPAutoload.__init__(self, snmp_handler, logger, supported_os) self.port_ethernet_vendor_type_pattern = r'port.*\d+ge|\S+.1.193.218.6.10.251|\S+Port.251' self._cli = cli self.snmp_view = 'qualiview' self.snmp_community = snmp_community self._enable_snmp = True self._disable_snmp = False self.vendor_type_exclusion_pattern = ['port.*mgmt'] self.interface_mapping_key = 'eriRouterIpBindIfIndex' self.interface_mapping_mib = 'ERICSSON-ROUTER-IP-BIND-MIB' self.load_mib_list = ['ERICSSON-ROUTER-PRODUCT-MIB'] if not self.snmp_community: self.snmp_community = get_attribute_by_name('SNMP Read Community') or 'qualicommunity'
def save_configuration(self, destination_host, source_filename='running', vrf=None): system_name = self.context.resource.fullname system_name = re.sub(r'[\.\s]', '_', system_name) if source_filename.lower() != 'running': raise Exception(self.__class__.__name__, 'Device does not support saving \"{}\" ' 'configuration type, \"running\" is only supported'.format( source_filename or 'None')) file_name = "{0}-{1}-{2}".format(system_name, source_filename, time.strftime("%d%m%y-%H%M%S", time.localtime())) if not destination_host: backup_location = get_attribute_by_name('Backup Location', context=self.context) if backup_location: destination_host = backup_location else: raise Exception(self.__class__.__name__, "Backup location or path is empty") if destination_host.endswith('/'): destination_host = destination_host[:-1] full_path = "{0}/{1}".format(destination_host, file_name) self.logger.info("Save configuration to file {0}".format(full_path)) self.execute_command_map({save_restore.SAVE: full_path}) return full_path
from cloudshell.configuration.cloudshell_cli_configuration import CONNECTION_TYPE_SSH from cloudshell.networking.cisco.aireos.cli.aireos_ssh_session import AireOSSSHSession from cloudshell.shell.core.context_utils import get_attribute_by_name_wrapper, \ get_resource_address, get_attribute_by_name, get_decrypted_password_by_attribute_name_wrapper from cloudshell.shell.core.dependency_injection.context_based_logger import get_logger_with_thread_id from cloudshell.configuration.cloudshell_cli_configuration import CONNECTION_MAP """Definition for SSH session""" ssh_session = SessionCreator(AireOSSSHSession) ssh_session.proxy = ReturnToPoolProxy ssh_session.kwargs = {'username': get_attribute_by_name_wrapper('User'), 'password': get_decrypted_password_by_attribute_name_wrapper('Password'), 'host': get_resource_address} CONNECTION_MAP[CONNECTION_TYPE_SSH] = ssh_session CONNECTION_EXPECTED_MAP = OrderedDict({r'[Uu]ser:': lambda session: session.send_line(get_attribute_by_name('User')), r'[Pp]assword:': lambda session: session.send_line( get_decrypted_password_by_attribute_name_wrapper('Password')())}) GET_LOGGER_FUNCTION = get_logger_with_thread_id DEFAULT_PROMPT = r'[>$#]\s*$' CONFIG_MODE_PROMPT = DEFAULT_PROMPT ENTER_CONFIG_MODE_PROMPT_COMMAND = '' EXIT_CONFIG_MODE_PROMPT_COMMAND = '' COMMIT_COMMAND = '' ROLLBACK_COMMAND = '' HE_MAX_READ_RETRIES = 10
def decrypt_password_from_attribute(api, password_attribute_name, context=None): """Uses api to decrypt password.""" password = get_attribute_by_name(password_attribute_name, context) return api.DecryptPassword(password).Value
def __init__(self, context): api = inject.instance('api') password = get_attribute_by_name('Password', context) self._password = api.DecryptPassword(password).Value self._user = get_attribute_by_name('User', context) self._host = context.resource.address
from cloudshell.shell.core.context_utils import get_attribute_by_name_wrapper, get_resource_address, \ get_attribute_by_name from cloudshell.configuration.cloudshell_cli_configuration import CONNECTION_MAP ssh_session = SessionCreator(AireOSSSHSession) ssh_session.proxy = ReturnToPoolProxy ssh_session.kwargs = { 'username': get_attribute_by_name_wrapper('User'), 'password': get_attribute_by_name_wrapper('Password'), 'host': get_resource_address } CONNECTION_MAP[CONNECTION_TYPE_SSH] = ssh_session CONNECTION_EXPECTED_MAP = OrderedDict({ r'[Uu]ser:': lambda session: session.send_line(get_attribute_by_name('User')), r'[Pp]assword:': lambda session: session.send_line(get_attribute_by_name('Password')) }) """Definition for Telnet session""" telnet_session = SessionCreator(TelnetSession) telnet_session.proxy = ReturnToPoolProxy telnet_session.kwargs = { 'username': get_attribute_by_name_wrapper('User'), # 'password': get_decrypted_password_by_attribute_name_wrapper('Password'), 'password': get_attribute_by_name_wrapper('Password'), 'host': get_resource_address } CONNECTION_MAP[CONNECTION_TYPE_TELNET] = telnet_session HE_MAX_LOOP_RETRIES = 5
def username(self): return get_attribute_by_name('User', self._context)
def snmp_community(self): if self._snmp_community is None: self._snmp_community = get_attribute_by_name("SNMP Read Community") or "quali" return self._snmp_community