Ejemplo n.º 1
0
class ScaleIOConfig(object):
    """ScaleIO config manager."""

    __scheme__ = {
        "network_timeout": Integer(min=0, optional=True),
        "request_retries": Integer(min=0, optional=True),
        "volume_prefix": String(optional=True),
        "volume_name": String(optional=True),
    }

    @classmethod
    def _get_scheme(cls):
        """Returns config scheme."""

        return DictScheme(cls.__scheme__)

    def _validate(self, options):
        """Validates config."""

        try:
            return validate("config", options, self._get_scheme())
        except ValidationError as e:
            raise exceptions.ScaleIOConfigError(e)

    def apply(self, **options):
        """Applies config options to a config module."""

        self._validate(options)

        for option, value in options.items():
            setattr(pyscaleio.config, option.upper(), value)
Ejemplo n.º 2
0
def test_dict_value_modification():
    _validate_modification({
        1: "10",
        2: "20"
    }, Dict(Integer(), ToInt()), {
        1: 10,
        2: 20
    })
Ejemplo n.º 3
0
def test_dict_key_modification():
    _validate_modification({
        "1": 10,
        "2": 20
    }, Dict(ToInt(), Integer()), {
        1: 10,
        2: 20
    })
Ejemplo n.º 4
0
def test_dict_scheme_with_schema():
    _validate({
        False: "string",
        1: True,
        "integer": 10,
        4.4: 44.4,
    },
              DictScheme({
                  False: String(),
                  1: Bool(),
                  "integer": Integer(),
                  3.3: Float(optional=True),
                  4.4: Float(optional=True),
              }))
Ejemplo n.º 5
0
class ExportsInfo(Sequence):
    """Information about volume exports."""

    __scheme__ = List(DictScheme({
        "sdcId": String(),
        "sdcIp": String(),
        "limitIops": Integer(),
        "limitBwInMbps": Integer()
    }), optional=True)

    def __init__(self, data=None):
        self._data = data or []

    def __getitem__(self, index):
        return self._data[index]

    def __len__(self):
        return len(self._data)

    def __contains__(self, key):
        if isinstance(key, Sdc):
            return key["id"] in (e["sdcId"] for e in self._data)
        else:
            super(ExportsInfo, self).__contains__(key)
Ejemplo n.º 6
0
def test_dict_scheme_with_delete_unknown():
    _validate_modification({
        "known_key": 10,
        "unknown_key": 10
    }, DictScheme({"known_key": Integer()}, delete_unknown=True),
                           {"known_key": 10})
Ejemplo n.º 7
0
def test_dict_scheme_with_ignore_unknown():
    _validate({
        "known_key": 10,
        "unknown_key": 10,
    }, DictScheme({"known_key": Integer()}, ignore_unknown=True))
Ejemplo n.º 8
0
class Volume(MutableResource):
    """Volume resource model."""

    __scheme__ = {
        "name": String(optional=True),
        "mappedSdcInfo": ExportsInfo.__scheme__,
        "useRmcache": Bool(),
        "sizeInKb": Integer(),
        "storagePoolId": String(),
        "volumeType": String(choices=constants.VOLUME_TYPES),
        "ancestorVolumeId": String(optional=True),
    }
    __parents__ = frozenset([
        ("ancestorVolumeId", "Volume"),
        ("storagePoolId", "StoragePool"),
        ("vtreeId", "VTree"),
    ])

    @pyscaleio.inject
    @classmethod
    def one_by_name(cls, client, name, **kwargs):
        """Returns volume instance by name.

        :param name: volume name (required)

        :rtype: pyscaleio.Volume
        """

        volume_id = client.perform_action_on_type(
            cls._get_name(), "queryIdByKey", {"name": name})

        return cls(volume_id, **kwargs)

    @classmethod
    def create(cls, size, pool, name=None, rmcache=None, thin=True, **kwargs):
        """Creates Volume instance.

        :param size: volume size in GB (required)
        :param pool: storage pool id (required)
        :param name: volume name
        :param thin: is volume 'thin' or 'thick' provisioned
        :param rmcache: volume rmcache

        :rtype: pyscaleio.Volume
        """

        volume_size = (size * constants.GIGABYTE) // constants.KILOBYTE
        volume = {
            "volumeSizeInKb": str(volume_size),
            "storagePoolId": pool
        }
        if name:
            volume["name"] = name
        if rmcache:
            volume["useRmcache"] = rmcache

        volume["volumeType"] = constants.VOLUME_TYPE_THICK
        if thin:
            volume["volumeType"] = constants.VOLUME_TYPE_THIN

        return super(Volume, cls).create(volume, **kwargs)

    @property
    def name(self):
        return self.get("name")

    @property
    def size(self):
        return self["sizeInKb"] * constants.KILOBYTE

    @property
    def type(self):
        return self.get("volumeType")

    @property
    def exports(self):
        return ExportsInfo(self.get("mappedSdcInfo"))

    @property
    def path(self):
        device_name = config.VOLUME_NAME.format(
            system_id=self._client.system["id"],
            volume_id=self["id"]
        )
        return os.path.join(config.VOLUME_PREFIX, device_name)

    def rename(self, name):
        """Changes volume name.

        :param name: new volume name
        """

        return super(Volume, self).perform("setVolumeName", {"newName": name})

    def resize(self, size):
        """Changes volumes size.

        :param size: new volume size in GB (required)
        """

        return super(Volume, self).perform("setVolumeSize", {"sizeInGB": str(size)})

    def snapshot(self, name=None):
        """Creates snapshot of current volume.

        :param name: snapshot name
        """

        snapshot = {"volumeId": self["id"]}
        if name:
            snapshot["snapshotName"] = name

        result = self._client.system.perform(
            "snapshotVolumes", {"snapshotDefs": [snapshot]})

        return Volume(result["volumeIdList"][0])

    def throttle(self, sdc_id=None, sdc_guid=None, iops=None, mbps=None):
        """Throttles I/O on current volume.

        :param iops: I/O operations in seconds (> 10)
        :param mbps: network bandwidth as megabytes in seconds
        """

        if sdc_id and sdc_guid:
            raise exceptions.ScaleIONotBothParameters("sdc_id", "sdc_guid")

        if iops is None and mbps is None:
            raise exceptions.ScaleIORequiredParameters("iops", "mbps")

        if iops is not None and iops != 0 and iops <= 10:
            raise exceptions.ScaleIOInvalidLimit("iops", "must be greater than 10.")

        if mbps is not None:
            mbps = mbps * constants.KILOBYTE
            if bool(mbps % constants.KILOBYTE):
                raise exceptions.ScaleIOInvalidLimit("mbps", "must be granular to 1024 Kbps")

        data = {}
        if sdc_id:
            data["sdcId"] = sdc_id
        if sdc_guid:
            data["guid"] = sdc_guid
        if iops is not None:
            data["iopsLimit"] = str(iops)
        if mbps is not None:
            data["bandwidthLimitInKbps"] = str(mbps)

        return super(Volume, self).perform("setMappedSdcLimits", data)

    def export(self, sdc_id=None, sdc_guid=None, multiple=False):
        """Exports volume to specified SDC.

        :param sdc_id: id of SDC instance
        :param sdc_guid: guid of SDC instance
        :param multiple: allows export to multiple SDCs (optional)
        """

        if sdc_id and sdc_guid:
            raise exceptions.ScaleIONotBothParameters("sdc_id", "sdc_guid")

        data = {}
        if sdc_id:
            data["sdcId"] = sdc_id
        if sdc_guid:
            data["guid"] = sdc_guid

        if multiple:
            data["allowMultipleMappings"] = utils.bool_to_str(multiple)

        return super(Volume, self).perform("addMappedSdc", data)

    def unexport(self, sdc_id=None, sdc_guid=None):
        """Unexports volume from specified SDC.
        Without parameters unexports volume from all SDCs

        :param sdc_id: id of SDC instance
        :param sdc_guid: guid if SDC instance
        """

        if sdc_id and sdc_guid:
            raise exceptions.ScaleIONotBothParameters("sdc_id", "sdc_guid")

        data = {}
        if sdc_id:
            data["sdcId"] = sdc_id
        elif sdc_guid:
            data["guid"] = sdc_guid
        else:
            data["allSdcs"] = ""

        return super(Volume, self).perform("removeMappedSdc", data)

    def delete(self, mode=constants.VOLUME_REMOVE_ONLY_ME):
        """Removes volume with specified mode.

        :param mode: volume remove mode (optional)
        """

        return super(Volume, self).delete({"removeMode": mode})
Ejemplo n.º 9
0
        assert result._DictScheme__scheme == scheme

        result = BaseResource(instance={"id": "test"})._get_scheme()
        assert isinstance(result, DictScheme)
        assert result._DictScheme__scheme == scheme


@pytest.mark.parametrize(("scheme", "data"),
                         [({
                             "name": String()
                         }, {
                             "name": "test"
                         }),
                          ({
                              "name": String(),
                              "size": Integer()
                          }, {
                              "name": "test",
                              "size": 8 * constants.GIGABYTE
                          })])
def test_custom_model_scheme(client, modelklass, scheme, data):

    base_scheme = {"id": String()}
    full_scheme = base_scheme
    full_scheme.update(scheme)

    data = data
    data.update({"id": "test_id"})

    with mock.patch("pyscaleio.models.BaseResource.__scheme__", base_scheme):
        klass = modelklass("Volume", (BaseResource, ), {"__scheme__": scheme})
Ejemplo n.º 10
0
def test_integer_max_invalid():
    with pytest.raises(InvalidValueError):
        _validate(5, Integer(max=4))
Ejemplo n.º 11
0
def test_integer_min_invalid():
    with pytest.raises(InvalidValueError):
        _validate(5, Integer(min=6))
Ejemplo n.º 12
0
def test_integer_min_max_valid():
    _validate(5, Integer(min=5, max=5))
Ejemplo n.º 13
0
def test_integer_invalid_type():
    error = pytest.raises(InvalidTypeError,
                          lambda: _validate(True, Integer())).value

    assert error.object_name == ""
    assert error.object_type == bool
Ejemplo n.º 14
0
 def test_integer_long():
     _validate(long(1), Integer())
Ejemplo n.º 15
0
def test_integer_int():
    _validate(1, Integer())
Ejemplo n.º 16
0
    "dividers": [],
    "dividers_map": {},
}, {
    "id": 2,
    "name": "two",
    "value": 2.0,
    "zero": False,
    "dividers": [1, 2],
    "dividers_map": {
        1: 1.0,
        2: 2.0,
    },
}]

SCHEME = List(DictScheme({
    "id": Integer(choices=(0, 2)),
    "name": String(),
    "value": Float(),
    "zero": Bool(),
    "dividers": List(Integer()),
    "dividers_map": Dict(Integer(), Float()),
}))


def test_validate():
    _validate("items", copy.deepcopy(ITEMS), SCHEME)


def test_validate_invalid_type():
    items = copy.deepcopy(ITEMS)
    items[1]["id"] = "string"