def _fork_snapshot( self, base_name, name=None, overwrite=False, background=False, deactivate_interfaces=None, deactivate_nodes=None, restore_interfaces=None, restore_nodes=None, add_files=None, extra_args=None, ): # type: (str, Optional[str], bool, bool, Optional[List[Interface]], Optional[List[str]], Optional[List[Interface]], Optional[List[str]], Optional[str], Optional[Dict[str, Any]]) -> Union[str, Dict, None] self._check_network() if name is None: name = Options.default_snapshot_prefix + get_uuid() validate_name(name) if name in self.list_snapshots(): if overwrite: self.delete_snapshot(name) else: raise ValueError( "A snapshot named " "{}" " already exists in network " "{}" ". " "Use overwrite = True if you want to overwrite the " "existing snapshot".format(name, self.network) ) encoded_file = None if add_files is not None: file_to_send = add_files if os.path.isdir(add_files): temp_zip_file = tempfile.NamedTemporaryFile() zip_dir(add_files, temp_zip_file) file_to_send = temp_zip_file.name if os.path.isfile(file_to_send): with open(file_to_send, "rb") as f: encoded_file = base64.b64encode(f.read()).decode("ascii") json_data = { "snapshotBase": base_name, "snapshotNew": name, "deactivateInterfaces": deactivate_interfaces, "deactivateNodes": deactivate_nodes, "restoreInterfaces": restore_interfaces, "restoreNodes": restore_nodes, "zipFile": encoded_file, } restv2helper.fork_snapshot(self, json_data) return self._parse_snapshot(name, background, extra_args)
def bf_init_snapshot(upload, name=None, overwrite=False, background=False, extra_args=None): # type: (str, Optional[str], bool, bool, Optional[Dict[str, Any]]) -> Union[str, Dict[str, str]] """Initialize a new snapshot. :param upload: snapshot to upload :type upload: zip file or directory :param name: name of the snapshot to initialize :type name: string :param overwrite: whether or not to overwrite an existing snapshot with the same name :type overwrite: bool :param background: whether or not to run the task in the background :type background: bool :param extra_args: extra arguments to be passed to the parse command. See bf_session.additionalArgs. :type extra_args: dict :return: name of initialized snapshot, or JSON dictionary of task status if background=True :rtype: Union[str, Dict] """ if bf_session.network is None: bf_set_network() if name is None: name = Options.default_snapshot_prefix + get_uuid() validate_name(name) if name in bf_list_snapshots(): if overwrite: bf_delete_snapshot(name) else: raise ValueError('A snapshot named ' '{}' ' already exists in network ' '{}' ''.format(name, bf_session.network)) file_to_send = upload if os.path.isdir(upload): temp_zip_file = tempfile.NamedTemporaryFile() zip_dir(upload, temp_zip_file) file_to_send = temp_zip_file.name json_data = workhelper.get_data_upload_snapshot(bf_session, name, file_to_send) resthelper.get_json_response(bf_session, CoordConsts.SVC_RSC_UPLOAD_SNAPSHOT, json_data) return _parse_snapshot(name, background, extra_args)
def _init_snapshot(self, upload, name=None, overwrite=False, background=False, extra_args=None): # type: (str, Optional[str], bool, bool, Optional[Dict[str, Any]]) -> Union[str, Dict[str, str]] if self.network is None: self.set_network() if name is None: name = Options.default_snapshot_prefix + get_uuid() validate_name(name) if name in self.list_snapshots(): if overwrite: self.delete_snapshot(name) else: raise ValueError( 'A snapshot named ' '{}' ' already exists in network ' '{}' '. ' 'Use overwrite = True if you want to overwrite the ' 'existing snapshot'.format(name, self.network)) file_to_send = upload tmp_file_name = None # type: Optional[Text] if os.path.isdir(upload): # delete=False because we re-open for reading with tempfile.NamedTemporaryFile(delete=False) as temp_zip_file: zip_dir(upload, temp_zip_file) tmp_file_name = file_to_send = temp_zip_file.name with open(file_to_send, 'rb') as fd: json_data = workhelper.get_data_upload_snapshot(self, name, fd) resthelper.get_json_response(self, CoordConsts.SVC_RSC_UPLOAD_SNAPSHOT, json_data) # Cleanup tmp file if we made one if tmp_file_name is not None: try: os.remove(tmp_file_name) except (OSError, IOError): # If we can't delete the file for some reason, let it be, # no need to crash initialization pass return self._parse_snapshot(name, background, extra_args)
def test_zip_dir(tmpdir): """Make sure zipping dir works.""" dirname = 'dirname' filename = 'filename' contents = 'file contents' in_dir_path = str(tmpdir.mkdir(dirname)) _make_config(in_dir_path, filename, contents) zip_file = str(tmpdir.join('file.zip')) zip_dir(in_dir_path, zip_file) # Make sure the zip contains the file with the correct contents _assert_zip_contents(zip_file, os.path.join(dirname, filename), contents, tmpdir)
def _bf_init_snapshot(upload, name, overwrite, background): if bf_session.network is None: bf_set_network() if name is None: name = Options.default_snapshot_prefix + get_uuid() validate_name(name) if name in bf_list_snapshots(): if overwrite: bf_delete_snapshot(name) else: raise ValueError('A snapshot named ' '{}' ' already exists in network ' '{}' ''.format(name, bf_session.network)) file_to_send = upload if os.path.isdir(upload): tempFile = tempfile.NamedTemporaryFile() zip_dir(upload, tempFile) file_to_send = tempFile.name json_data = workhelper.get_data_upload_snapshot(bf_session, name, file_to_send) resthelper.get_json_response(bf_session, CoordConsts.SVC_RSC_UPLOAD_SNAPSHOT, json_data) bf_session.baseSnapshot = name work_item = workhelper.get_workitem_parse(bf_session, name) parse_execute = workhelper.execute(work_item, bf_session, background=background) if not background: status = parse_execute["status"] if WorkStatusCode(status) != WorkStatusCode.TERMINATEDNORMALLY: bf_session.baseSnapshot = None bf_logger.info("Default snapshot is now unset") else: bf_logger.info("Default snapshot is now set to %s", bf_session.baseSnapshot) return parse_execute
def test_zip_dir_bad_file_time(tmpdir): """ Make sure zipping pre-1980 file works - even though zip format doesn't support files that old. See issue here https://bugs.python.org/issue34097 """ dirname = 'dirname' filename = 'filename' contents = 'file contents' in_dir_path = str(tmpdir.mkdir(dirname)) _make_config(in_dir_path, filename, contents) in_file_path = os.path.join(in_dir_path, filename) zip_file = str(tmpdir.join('file.zip')) # Set accessed and modified time of file we're about to zip to some time pre-1980 _1960_01_01 = -315590400.0 os.utime(in_file_path, (_1960_01_01, _1960_01_01)) zip_dir(in_dir_path, zip_file) # Make sure the zip contains the file with the correct contents _assert_zip_contents(zip_file, os.path.join(dirname, filename), contents, tmpdir)
def __init_snapshot_from_file(self, name, file_to_send): # type: (str, str) -> None tmp_file_name = None # type: Optional[Text] if os.path.isdir(file_to_send): # delete=False because we re-open for reading with tempfile.NamedTemporaryFile(delete=False) as temp_zip_file: zip_dir(file_to_send, temp_zip_file) tmp_file_name = file_to_send = temp_zip_file.name elif os.path.isfile(file_to_send): if not zipfile.is_zipfile(file_to_send): raise ValueError("{} is not a valid zip file".format(file_to_send)) with open(file_to_send, "rb") as fd: self.__init_snapshot_from_io(name, fd) # Cleanup tmp file if we made one if tmp_file_name is not None: try: os.remove(tmp_file_name) except (OSError, IOError): # If we can't delete the file for some reason, let it be, # no need to crash initialization pass
def bf_init_snapshot(upload, name=None, overwrite=False, background=False): # type: (str, Optional[str], bool, bool) -> Union[str, Dict[str, str]] """Initialize a new snapshot. :param upload: snapshot to upload :type upload: zip file or directory :param name: name of the snapshot to initialize :type name: string :param overwrite: whether or not to overwrite an existing snapshot with the same name :type overwrite: bool :param background: whether or not to run the task in the background :type background: bool :return: name of initialized snapshot, or JSON dictionary of task status if background=True :rtype: Union[str, Dict] """ if bf_session.network is None: bf_set_network() if name is None: name = Options.default_snapshot_prefix + get_uuid() validate_name(name) if name in bf_list_snapshots(): if overwrite: bf_delete_snapshot(name) else: raise ValueError('A snapshot named ' '{}' ' already exists in network ' '{}' ''.format(name, bf_session.network)) file_to_send = upload if os.path.isdir(upload): temp_zip_file = tempfile.NamedTemporaryFile() zip_dir(upload, temp_zip_file) file_to_send = temp_zip_file.name json_data = workhelper.get_data_upload_snapshot(bf_session, name, file_to_send) resthelper.get_json_response(bf_session, CoordConsts.SVC_RSC_UPLOAD_SNAPSHOT, json_data) work_item = workhelper.get_workitem_parse(bf_session, name) answer_dict = workhelper.execute(work_item, bf_session, background=background) if background: bf_session.baseSnapshot = name return answer_dict status = WorkStatusCode(answer_dict["status"]) if status != WorkStatusCode.TERMINATEDNORMALLY: raise BatfishException( 'Initializing snapshot {ss} failed with status {status}'.format( ss=name, status=status)) else: bf_session.baseSnapshot = name bf_logger.info("Default snapshot is now set to %s", bf_session.baseSnapshot) return bf_session.baseSnapshot
def bf_fork_snapshot(base_name, name=None, overwrite=False, background=False, deactivate_interfaces=None, deactivate_links=None, deactivate_nodes=None, restore_interfaces=None, restore_links=None, restore_nodes=None, add_files=None): # type: (str, Optional[str], bool, bool, Optional[List[Interface]], Optional[List[Edge]], Optional[List[str]], Optional[List[Interface]], Optional[List[Edge]], Optional[List[str]], Optional[str]) -> Union[str, Dict, None] """Copy an existing snapshot and deactivate or reactivate specified interfaces, nodes, and links on the copy. :param base_name: name of the snapshot to copy :type base_name: string :param name: name of the snapshot to initialize :type name: string :param overwrite: whether or not to overwrite an existing snapshot with the same name :type overwrite: bool :param background: whether or not to run the task in the background :type background: bool :param deactivate_interfaces: list of interfaces to deactivate in new snapshot :type deactivate_interfaces: list[Interface] :param deactivate_links: list of links to deactivate in new snapshot :type deactivate_links: list[Edge] :param deactivate_nodes: list of names of nodes to deactivate in new snapshot :type deactivate_nodes: list[str] :param restore_interfaces: list of interfaces to reactivate :type restore_interfaces: list[Interface] :param restore_links: list of links to reactivate :type restore_links: list[Edge] :param restore_nodes: list of names of nodes to reactivate :type restore_nodes: list[str] :param add_files: path to zip file or directory containing files to add :type add_files: str :return: name of initialized snapshot, JSON dictionary of task status if background=True, or None if the call fails :rtype: Union[str, Dict, None] """ if bf_session.network is None: raise ValueError('Network must be set to fork a snapshot.') if name is None: name = Options.default_snapshot_prefix + get_uuid() validate_name(name) if name in bf_list_snapshots(): if overwrite: bf_delete_snapshot(name) else: raise ValueError('A snapshot named ' '{}' ' already exists in network ' '{}' ''.format(name, bf_session.network)) encoded_file = None if add_files is not None: file_to_send = add_files if os.path.isdir(add_files): temp_zip_file = tempfile.NamedTemporaryFile() zip_dir(add_files, temp_zip_file) file_to_send = temp_zip_file.name if os.path.isfile(file_to_send): with open(file_to_send, "rb") as f: encoded_file = base64.b64encode(f.read()).decode('ascii') json_data = { "snapshotBase": base_name, "snapshotNew": name, "deactivateInterfaces": deactivate_interfaces, "deactivateLinks": deactivate_links, "deactivateNodes": deactivate_nodes, "restoreInterfaces": restore_interfaces, "restoreLinks": restore_links, "restoreNodes": restore_nodes, "zipFile": encoded_file } restv2helper.fork_snapshot(bf_session, json_data) work_item = workhelper.get_workitem_parse(bf_session, name) answer_dict = workhelper.execute(work_item, bf_session, background=background) if background: bf_session.baseSnapshot = name return answer_dict status = WorkStatusCode(answer_dict['status']) if status != WorkStatusCode.TERMINATEDNORMALLY: raise BatfishException( 'Forking snapshot {ss} from {base} failed with status {status}'. format(ss=name, base=base_name, status=status)) else: bf_session.baseSnapshot = name bf_logger.info("Default snapshot is now set to %s", bf_session.baseSnapshot) return bf_session.baseSnapshot
def bf_fork_snapshot(base_name, name=None, overwrite=False, background=False, deactivate_interfaces=None, deactivate_links=None, deactivate_nodes=None, restore_interfaces=None, restore_links=None, restore_nodes=None, add_files=None, extra_args=None): # type: (str, Optional[str], bool, bool, Optional[List[Interface]], Optional[List[Edge]], Optional[List[str]], Optional[List[Interface]], Optional[List[Edge]], Optional[List[str]], Optional[str], Optional[Dict[str, Any]]) -> Union[str, Dict, None] """Copy an existing snapshot and deactivate or reactivate specified interfaces, nodes, and links on the copy. :param base_name: name of the snapshot to copy :type base_name: string :param name: name of the snapshot to initialize :type name: string :param overwrite: whether or not to overwrite an existing snapshot with the same name :type overwrite: bool :param background: whether or not to run the task in the background :type background: bool :param deactivate_interfaces: list of interfaces to deactivate in new snapshot :type deactivate_interfaces: list[Interface] :param deactivate_links: list of links to deactivate in new snapshot :type deactivate_links: list[Edge] :param deactivate_nodes: list of names of nodes to deactivate in new snapshot :type deactivate_nodes: list[str] :param restore_interfaces: list of interfaces to reactivate :type restore_interfaces: list[Interface] :param restore_links: list of links to reactivate :type restore_links: list[Edge] :param restore_nodes: list of names of nodes to reactivate :type restore_nodes: list[str] :param add_files: path to zip file or directory containing files to add :type add_files: str :param extra_args: extra arguments to be passed to the parse command. See bf_session.additionalArgs. :type extra_args: dict :return: name of initialized snapshot, JSON dictionary of task status if background=True, or None if the call fails :rtype: Union[str, Dict, None] """ if bf_session.network is None: raise ValueError('Network must be set to fork a snapshot.') if name is None: name = Options.default_snapshot_prefix + get_uuid() validate_name(name) if name in bf_list_snapshots(): if overwrite: bf_delete_snapshot(name) else: raise ValueError('A snapshot named ' '{}' ' already exists in network ' '{}' ''.format(name, bf_session.network)) encoded_file = None if add_files is not None: file_to_send = add_files if os.path.isdir(add_files): temp_zip_file = tempfile.NamedTemporaryFile() zip_dir(add_files, temp_zip_file) file_to_send = temp_zip_file.name if os.path.isfile(file_to_send): with open(file_to_send, "rb") as f: encoded_file = base64.b64encode(f.read()).decode('ascii') json_data = { "snapshotBase": base_name, "snapshotNew": name, "deactivateInterfaces": deactivate_interfaces, "deactivateLinks": deactivate_links, "deactivateNodes": deactivate_nodes, "restoreInterfaces": restore_interfaces, "restoreLinks": restore_links, "restoreNodes": restore_nodes, "zipFile": encoded_file } restv2helper.fork_snapshot(bf_session, json_data) return _parse_snapshot(name, background, extra_args)