示例#1
0
    def get_image_files_info(self):
        """
        Sends a DEFAULT_IMAGE_FILES_INFO command to the server.
        Returns a dict with:
        - (bool) status
        - (str) images_dir, path to images dir
        - (list) of (str) image_files
        - (int) scan_depth, the current scan depth
        """
        command = proto.PbCommand()
        command.operation = proto.PbOperation.DEFAULT_IMAGE_FILES_INFO
        command.params["token"] = self.token
        command.params["locale"] = self.token

        data = self.sock_cmd.send_pb_command(command.SerializeToString())
        result = proto.PbResult()
        result.ParseFromString(data)
        images_dir = result.image_files_info.default_image_folder
        image_files = result.image_files_info.image_files
        scan_depth = result.image_files_info.depth
        return {
            "status": result.status,
            "images_dir": images_dir,
            "image_files": image_files,
            "scan_depth": scan_depth,
        }
示例#2
0
    def list_images(self):
        """
        Sends a IMAGE_FILES_INFO command to the server
        Returns a (dict) with (bool) status, (str) msg, and (list) of (dict)s files

        """
        command = proto.PbCommand()
        command.operation = proto.PbOperation.DEFAULT_IMAGE_FILES_INFO
        command.params["token"] = self.token
        command.params["locale"] = self.locale

        data = self.sock_cmd.send_pb_command(command.SerializeToString())
        result = proto.PbResult()
        result.ParseFromString(data)

        # Get a list of all *.properties files in CFG_DIR
        prop_data = self.list_files(PROPERTIES_SUFFIX, CFG_DIR)
        prop_files = [PurePath(x[0]).stem for x in prop_data]

        from zipfile import ZipFile, is_zipfile
        server_info = self.ractl.get_server_info()
        files = []
        for file in result.image_files_info.image_files:
            # Add properties meta data for the image, if applicable
            if file.name in prop_files:
                process = self.read_drive_properties(
                    f"{CFG_DIR}/{file.name}.{PROPERTIES_SUFFIX}")
                prop = process["conf"]
            else:
                prop = False
            if file.name.lower().endswith(".zip"):
                zip_path = f"{server_info['image_dir']}/{file.name}"
                if is_zipfile(zip_path):
                    zipfile = ZipFile(zip_path)
                    # Get a list of (str) containing all zipfile members
                    zip_members = zipfile.namelist()
                    # Strip out directories from the list
                    zip_members = [
                        x for x in zip_members if not x.endswith("/")
                    ]
                else:
                    logging.warning("%s is an invalid zip file", zip_path)
                    zip_members = False
            else:
                zip_members = False

            size_mb = "{:,.1f}".format(file.size / 1024 / 1024)
            dtype = proto.PbDeviceType.Name(file.type)
            files.append({
                "name": file.name,
                "size": file.size,
                "size_mb": size_mb,
                "detected_type": dtype,
                "prop": prop,
                "zip_members": zip_members,
            })

        return {"status": result.status, "msg": result.msg, "files": files}
示例#3
0
    def is_token_auth(self):
        """
        Sends a CHECK_AUTHENTICATION command to the server.
        Tells you whether RaSCSI backend is protected by a token password or not.
        Returns (bool) status and (str) msg.
        """
        command = proto.PbCommand()
        command.operation = proto.PbOperation.CHECK_AUTHENTICATION

        data = self.sock_cmd.send_pb_command(command.SerializeToString())
        result = proto.PbResult()
        result.ParseFromString(data)
        return {"status": result.status, "msg": result.msg}
示例#4
0
    def detach_all(self):
        """
        Sends a DETACH_ALL command to the server.
        Returns (bool) status and (str) msg.
        """
        command = proto.PbCommand()
        command.operation = proto.PbOperation.DETACH_ALL
        command.params["token"] = self.token
        command.params["locale"] = self.locale

        data = self.sock_cmd.send_pb_command(command.SerializeToString())
        result = proto.PbResult()
        result.ParseFromString(data)
        return {"status": result.status, "msg": result.msg}
示例#5
0
    def reserve_scsi_ids(self, reserved_scsi_ids):
        """
        Sends the RESERVE_IDS command to the server to reserve SCSI IDs.
        Takes a (list) of (str) as argument.
        """
        command = proto.PbCommand()
        command.operation = proto.PbOperation.RESERVE_IDS
        command.params["ids"] = ",".join(reserved_scsi_ids)
        command.params["token"] = self.token
        command.params["locale"] = self.locale

        data = self.sock_cmd.send_pb_command(command.SerializeToString())
        result = proto.PbResult()
        result.ParseFromString(data)
        return {"status": result.status, "msg": result.msg}
示例#6
0
    def shutdown_pi(self, mode):
        """
        Sends a SHUT_DOWN command to the server.
        Takes (str) mode as an argument.
        Returns (bool) status and (str) msg.
        """
        command = proto.PbCommand()
        command.operation = proto.PbOperation.SHUT_DOWN
        command.params["mode"] = str(mode)
        command.params["token"] = self.token
        command.params["locale"] = self.locale

        data = self.sock_cmd.send_pb_command(command.SerializeToString())
        result = proto.PbResult()
        result.ParseFromString(data)
        return {"status": result.status, "msg": result.msg}
示例#7
0
    def set_log_level(self, log_level):
        """
        Sends a LOG_LEVEL command to the server.
        Takes (str) log_level as an argument.
        Returns (bool) status and (str) msg.
        """
        command = proto.PbCommand()
        command.operation = proto.PbOperation.LOG_LEVEL
        command.params["level"] = str(log_level)
        command.params["token"] = self.token
        command.params["locale"] = self.locale

        data = self.sock_cmd.send_pb_command(command.SerializeToString())
        result = proto.PbResult()
        result.ParseFromString(data)
        return {"status": result.status, "msg": result.msg}
示例#8
0
    def delete_image(self, file_name):
        """
        Takes (str) file_name
        Sends a DELETE_IMAGE command to the server
        Returns (dict) with (bool) status and (str) msg
        """
        command = proto.PbCommand()
        command.operation = proto.PbOperation.DELETE_IMAGE
        command.params["token"] = self.ractl.token
        command.params["locale"] = self.ractl.locale

        command.params["file"] = file_name

        data = self.sock_cmd.send_pb_command(command.SerializeToString())
        result = proto.PbResult()
        result.ParseFromString(data)
        return {"status": result.status, "msg": result.msg}
示例#9
0
    def get_network_info(self):
        """
        Sends a NETWORK_INTERFACES_INFO command to the server.
        Returns a dict with:
        - (bool) status
        - (list) of (str) ifs (network interfaces detected by RaSCSI)
        """
        command = proto.PbCommand()
        command.operation = proto.PbOperation.NETWORK_INTERFACES_INFO
        command.params["token"] = self.token
        command.params["locale"] = self.locale

        data = self.sock_cmd.send_pb_command(command.SerializeToString())
        result = proto.PbResult()
        result.ParseFromString(data)
        ifs = result.network_interfaces_info.name
        return {"status": result.status, "ifs": ifs}
示例#10
0
    def create_new_image(self, file_name, file_type, size):
        """
        Takes (str) file_name, (str) file_type, and (int) size
        Sends a CREATE_IMAGE command to the server
        Returns (dict) with (bool) status and (str) msg
        """
        command = proto.PbCommand()
        command.operation = proto.PbOperation.CREATE_IMAGE
        command.params["token"] = self.token
        command.params["locale"] = self.locale

        command.params["file"] = file_name + "." + file_type
        command.params["size"] = str(size)
        command.params["read_only"] = "false"

        data = self.sock_cmd.send_pb_command(command.SerializeToString())
        result = proto.PbResult()
        result.ParseFromString(data)
        return {"status": result.status, "msg": result.msg}
示例#11
0
    def get_device_types(self):
        """
        Sends a DEVICE_TYPES_INFO command to the server.
        Returns a dict with:
        - (bool) status
        - (list) of (str) device_types (device types that RaSCSI supports, ex. SCHD, SCCD, etc)
        """
        command = proto.PbCommand()
        command.operation = proto.PbOperation.DEVICE_TYPES_INFO
        command.params["token"] = self.token
        command.params["locale"] = self.locale

        data = self.sock_cmd.send_pb_command(command.SerializeToString())
        result = proto.PbResult()
        result.ParseFromString(data)
        device_types = []
        for prop in result.device_types_info.properties:
            device_types.append(proto.PbDeviceType.Name(prop.type))
        return {"status": result.status, "device_types": device_types}
示例#12
0
    def get_reserved_ids(self):
        """
        Sends a RESERVED_IDS_INFO command to the server.
        Returns a dict with:
        - (bool) status
        - (list) of (int) ids -- currently reserved SCSI IDs
        """
        command = proto.PbCommand()
        command.operation = proto.PbOperation.RESERVED_IDS_INFO
        command.params["token"] = self.token
        command.params["locale"] = self.locale

        data = self.sock_cmd.send_pb_command(command.SerializeToString())
        result = proto.PbResult()
        result.ParseFromString(data)
        scsi_ids = []
        for scsi_id in result.reserved_ids_info.ids:
            scsi_ids.append(str(scsi_id))

        return {"status": result.status, "ids": scsi_ids}
示例#13
0
    def eject_by_id(self, scsi_id, unit=None):
        """
        Takes (int) scsi_id and optional (int) unit.
        Sends an EJECT command to the server.
        Returns (bool) status and (str) msg.
        """
        devices = proto.PbDeviceDefinition()
        devices.id = int(scsi_id)
        if unit is not None:
            devices.unit = int(unit)

        command = proto.PbCommand()
        command.operation = proto.PbOperation.EJECT
        command.devices.append(devices)
        command.params["token"] = self.token
        command.params["locale"] = self.locale

        data = self.sock_cmd.send_pb_command(command.SerializeToString())
        result = proto.PbResult()
        result.ParseFromString(data)
        return {"status": result.status, "msg": result.msg}
示例#14
0
    def list_devices(self, scsi_id=None, unit=None):
        """
        Takes optional (int) scsi_id and optional (int) unit.
        Sends a DEVICES_INFO command to the server.
        If no scsi_id is provided, returns a (list) of (dict)s of all attached devices.
        If scsi_id is is provided, returns a (list) of one (dict) for the given device.
        If no attached device is found, returns an empty (list).
        Returns (bool) status, (list) of dicts device_list
        """
        command = proto.PbCommand()
        command.operation = proto.PbOperation.DEVICES_INFO
        command.params["token"] = self.token
        command.params["locale"] = self.locale

        # If method is called with scsi_id parameter, return the info on those devices
        # Otherwise, return the info on all attached devices
        if scsi_id is not None:
            device = proto.PbDeviceDefinition()
            device.id = int(scsi_id)
            if unit is not None:
                device.unit = int(unit)
            command.devices.append(device)

        data = self.sock_cmd.send_pb_command(command.SerializeToString())
        result = proto.PbResult()
        result.ParseFromString(data)

        device_list = []

        # Return an empty (list) if no devices are attached
        if not result.devices_info.devices:
            return {"status": False, "device_list": []}

        image_files_info = self.get_image_files_info()
        i = 0
        while i < len(result.devices_info.devices):
            did = result.devices_info.devices[i].id
            dunit = result.devices_info.devices[i].unit
            dtype = proto.PbDeviceType.Name(
                result.devices_info.devices[i].type)
            dstat = result.devices_info.devices[i].status
            dprop = result.devices_info.devices[i].properties

            # Building the status string
            dstat_msg = []
            if dprop.read_only:
                dstat_msg.append("Read-Only")
            if dstat.protected and dprop.protectable:
                dstat_msg.append("Write-Protected")
            if dstat.removed and dprop.removable:
                dstat_msg.append("No Media")
            if dstat.locked and dprop.lockable:
                dstat_msg.append("Locked")

            dpath = result.devices_info.devices[i].file.name
            dfile = dpath.replace(image_files_info["images_dir"] + "/", "")
            dparam = result.devices_info.devices[i].params
            dven = result.devices_info.devices[i].vendor
            dprod = result.devices_info.devices[i].product
            drev = result.devices_info.devices[i].revision
            dblock = result.devices_info.devices[i].block_size
            dsize = int(
                result.devices_info.devices[i].block_count) * int(dblock)

            device_list.append({
                "id": did,
                "unit": dunit,
                "device_type": dtype,
                "status": ", ".join(dstat_msg),
                "image": dpath,
                "file": dfile,
                "params": dparam,
                "vendor": dven,
                "product": dprod,
                "revision": drev,
                "block_size": dblock,
                "size": dsize,
            })
            i += 1

        return {
            "status": result.status,
            "msg": result.msg,
            "device_list": device_list
        }
示例#15
0
    def get_server_info(self):
        """
        Sends a SERVER_INFO command to the server.
        Returns a dict with:
        - (bool) status
        - (str) version (RaSCSI version number)
        - (list) of (str) log_levels (the log levels RaSCSI supports)
        - (str) current_log_level
        - (list) of (int) reserved_ids
        - (str) image_dir, path to the default images directory
        - (int) scan_depth, the current images directory scan depth
        - 5 distinct (list)s of (str)s with file endings recognized by RaSCSI
        """
        command = proto.PbCommand()
        command.operation = proto.PbOperation.SERVER_INFO
        command.params["token"] = self.token
        command.params["locale"] = self.locale

        data = self.sock_cmd.send_pb_command(command.SerializeToString())
        result = proto.PbResult()
        result.ParseFromString(data)
        version = (str(result.server_info.version_info.major_version) + "." +
                   str(result.server_info.version_info.minor_version) + "." +
                   str(result.server_info.version_info.patch_version))
        log_levels = result.server_info.log_level_info.log_levels
        current_log_level = result.server_info.log_level_info.current_log_level
        reserved_ids = list(result.server_info.reserved_ids_info.ids)
        image_dir = result.server_info.image_files_info.default_image_folder
        scan_depth = result.server_info.image_files_info.depth

        # Creates lists of file endings recognized by RaSCSI
        mappings = result.server_info.mapping_info.mapping
        sahd = []
        schd = []
        scrm = []
        scmo = []
        sccd = []
        for dtype in mappings:
            if mappings[dtype] == proto.PbDeviceType.SAHD:
                sahd.append(dtype)
            elif mappings[dtype] == proto.PbDeviceType.SCHD:
                schd.append(dtype)
            elif mappings[dtype] == proto.PbDeviceType.SCRM:
                scrm.append(dtype)
            elif mappings[dtype] == proto.PbDeviceType.SCMO:
                scmo.append(dtype)
            elif mappings[dtype] == proto.PbDeviceType.SCCD:
                sccd.append(dtype)

        return {
            "status": result.status,
            "version": version,
            "log_levels": log_levels,
            "current_log_level": current_log_level,
            "reserved_ids": reserved_ids,
            "image_dir": image_dir,
            "scan_depth": scan_depth,
            "sahd": sahd,
            "schd": schd,
            "scrm": scrm,
            "scmo": scmo,
            "sccd": sccd,
        }
示例#16
0
    def attach_image(self, scsi_id, **kwargs):
        """
        Takes (int) scsi_id and kwargs containing 0 or more device properties

        If the current attached device is a removable device wihout media inserted,
        this sends a INJECT command to the server.
        If there is no currently attached device, this sends the ATTACH command to the server.

        Returns (bool) status and (str) msg

        """
        command = proto.PbCommand()
        command.params["token"] = self.token
        command.params["locale"] = self.locale
        devices = proto.PbDeviceDefinition()
        devices.id = int(scsi_id)

        if "device_type" in kwargs.keys():
            if kwargs["device_type"] not in [None, ""]:
                devices.type = proto.PbDeviceType.Value(
                    str(kwargs["device_type"]))
        if "unit" in kwargs.keys():
            if kwargs["unit"] not in [None, ""]:
                devices.unit = kwargs["unit"]
        if "image" in kwargs.keys():
            if kwargs["image"] not in [None, ""]:
                devices.params["file"] = kwargs["image"]

        # Handling the inserting of media into an attached removable type device
        device_type = kwargs.get("device_type", None)
        currently_attached = self.list_devices(
            scsi_id, kwargs.get("unit"))["device_list"]
        if currently_attached:
            current_type = currently_attached[0]["device_type"]
        else:
            current_type = None

        if device_type in REMOVABLE_DEVICE_TYPES and current_type in REMOVABLE_DEVICE_TYPES:
            if current_type != device_type:
                parameters = {
                    "device_type": device_type,
                    "current_device_type": current_type
                }
                return {
                    "status": False,
                    "return_code": ReturnCodes.ATTACHIMAGE_COULD_NOT_ATTACH,
                    "parameters": parameters,
                }
            command.operation = proto.PbOperation.INSERT
        # Handling attaching a new device
        else:
            command.operation = proto.PbOperation.ATTACH
            if "interfaces" in kwargs.keys():
                if kwargs["interfaces"] not in [None, ""]:
                    devices.params["interfaces"] = kwargs["interfaces"]
            if "vendor" in kwargs.keys():
                if kwargs["vendor"] is not None:
                    devices.vendor = kwargs["vendor"]
            if "product" in kwargs.keys():
                if kwargs["product"] is not None:
                    devices.product = kwargs["product"]
            if "revision" in kwargs.keys():
                if kwargs["revision"] is not None:
                    devices.revision = kwargs["revision"]
            if "block_size" in kwargs.keys():
                if kwargs["block_size"] not in [None, ""]:
                    devices.block_size = int(kwargs["block_size"])

        command.devices.append(devices)

        data = self.sock_cmd.send_pb_command(command.SerializeToString())
        result = proto.PbResult()
        result.ParseFromString(data)
        return {"status": result.status, "msg": result.msg}