Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
name: CI

on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]

jobs:
# -----------------
# Linux job (pytest + flake8 + coverage + codecov)
# -----------------
linux-tests:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [ "3.10", "3.11", "3.12" ]
steps:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools wheel
pip install -r requirements.txt
pip install -r test-requirements.txt
pip install codecov

- name: Run flake8
if: matrix.python-version == '3.11' # run lint once
run: flake8 storops storops_test storops_comptest

- name: Run pytest with coverage
run: |
pytest -n2 --cov=storops --cov-config coverage.ini \
--cov-report=xml --cov-report=term \
--junit-xml=junit-result.xml storops_test

- name: Upload coverage to Codecov
if: matrix.python-version == '3.11' # upload once
uses: codecov/codecov-action@v5
with:
files: ./coverage.xml
fail_ci_if_error: false

# -----------------
# Windows job (tox-based tests + pep8 once)
# -----------------
windows-tests:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
python-version: [ "3.10", "3.11", "3.12" ]
toxenv: [ "py310", "py311", "py312", "pep8" ]
exclude:
# map toxenv to correct python versions only
- python-version: "3.10"
toxenv: py311
- python-version: "3.10"
toxenv: py312
- python-version: "3.11"
toxenv: py310
- python-version: "3.11"
toxenv: py312
- python-version: "3.12"
toxenv: py310
- python-version: "3.12"
toxenv: py311
# only run pep8 once (Python 3.11)
- python-version: "3.10"
toxenv: pep8
- python-version: "3.12"
toxenv: pep8
env:
TOXENV: ${{ matrix.toxenv }}
steps:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
python -m pip install --upgrade pip setuptools virtualenv wheel
python -m pip install tox

- name: Run tox
run: tox
16 changes: 0 additions & 16 deletions .travis.yml

This file was deleted.

49 changes: 0 additions & 49 deletions appveyor.yml

This file was deleted.

17 changes: 9 additions & 8 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
requests>=2.32.4 # Apache-2.0, cinder, manila
PyYAML>=6.0.2 # MIT, cinder, manila
six>=1.9.0 # MIT, cinder, manila
requests # Apache-2.0, cinder, manila
PyYAML # MIT, cinder, manila
six # MIT, cinder, manila
enum34 # BSD

python-dateutil>=2.4.2 # BSD
retryz>=0.1.8 # Apache-2.0
cachez>=0.1.0 # Apache-2.0
bitmath>=1.3.0 # MIT
urllib3>=2.5.0 # MIT
python-dateutil # BSD
retryz # Apache-2.0
cachez # Apache-2.0
bitmath # MIT
urllib3 # MIT
setuptools
1 change: 1 addition & 0 deletions storops/unity/parser_configs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2060,6 +2060,7 @@ UnityReplicationSession:
- label: name
- label: networkStatus
converter: ReplicationSessionNetworkStatusEnum
- label: noAsyncSnapReplication
- label: remoteSystem
converter: UnityRemoteSystem
- label: replicationResourceType
Expand Down
69 changes: 51 additions & 18 deletions storops/unity/resource/filesystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ class UnityFileSystem(UnityResource):
def create(cls, cli, pool, nas_server, name, size, proto=None,
is_thin=None, tiering_policy=None, user_cap=False,
is_compression=None, access_policy=None,
locking_policy=None, description=None):
locking_policy=None, description=None,
is_advanced_dedup_enabled=None):
pool_clz = storops.unity.resource.pool.UnityPool
nas_server_clz = storops.unity.resource.nas_server.UnityNasServer

Expand All @@ -65,7 +66,8 @@ def create(cls, cli, pool, nas_server, name, size, proto=None,
tiering_policy=tiering_policy,
is_compression=is_compression,
access_policy=access_policy,
locking_policy=locking_policy)
locking_policy=locking_policy,
is_advanced_dedup_enabled=is_advanced_dedup_enabled)

req_body = cli.make_body(allow_empty=True, name=name,
description=description,
Expand All @@ -80,7 +82,8 @@ def create(cls, cli, pool, nas_server, name, size, proto=None,
def modify(self, size=None, is_thin=None, tiering_policy=None,
user_cap=False, is_compression=None, access_policy=None,
locking_policy=None, description=None,
cifs_fs_parameters=None, snap_schedule_parameters=None):
cifs_fs_parameters=None, snap_schedule_parameters=None,
is_advanced_dedup_enabled=None):
sr = self.storage_resource
if sr is None:
raise ValueError('storage resource for filesystem {} not found.'
Expand All @@ -94,7 +97,8 @@ def modify(self, size=None, is_thin=None, tiering_policy=None,
tiering_policy=tiering_policy,
is_compression=is_compression,
access_policy=access_policy,
locking_policy=locking_policy)
locking_policy=locking_policy,
is_advanced_dedup_enabled=is_advanced_dedup_enabled)

params = {}
if fs_param:
Expand Down Expand Up @@ -244,15 +248,19 @@ def has_snap(self, ignore_system_snap=False):
snaps = filter(lambda s: not s.is_system_snap, snaps)
return len(list(snaps)) > 0

def replicate_with_dst_resource_provisioning(self, max_time_out_of_sync,
dst_pool_id,
dst_fs_name=None,
remote_system=None,
replication_name=None,
dst_size=None,
is_dst_thin=None,
dst_tiering_policy=None,
is_dst_compression=None):
def replicate_with_dst_resource_provisioning(
self, max_time_out_of_sync,
dst_pool_id,
dst_fs_name=None,
remote_system=None,
replication_name=None,
dst_size=None,
is_dst_thin=None,
dst_tiering_policy=None,
is_dst_compression=None,
no_async_snap_replication=None,
hourly_snap_replication_policy=None,
daily_snap_replication_policy=None):
"""
Creates a replication session with destination filesystem provisioning.

Expand All @@ -274,6 +282,16 @@ def replicate_with_dst_resource_provisioning(self, max_time_out_of_sync,
destination filesystem.
:param is_dst_compression: indicates whether destination filesystem is
compression enabled or not.
:param no_async_snap_replication: whether or not snap replication is
enabled in asynchronous replication session. When enabled, snap
replication is controlled by snap replication policy setting or
user action.
:param hourly_snap_replication_policy: `UnitySnapReplicationPolicy`
object. The policy for replicating hourly scheduled snaps of the
source resource.
:param daily_snap_replication_policy: `UnitySnapReplicationPolicy`
object. The policy for replicating daily scheduled snaps of the
source resource.
:return: created replication session.
"""

Expand All @@ -294,20 +312,33 @@ def replicate_with_dst_resource_provisioning(self, max_time_out_of_sync,
return UnityReplicationSession.create_with_dst_resource_provisioning(
self._cli, self.storage_resource.get_id(),
dst_resource, max_time_out_of_sync,
remote_system=remote_system, name=replication_name)
remote_system=remote_system, name=replication_name,
no_async_snap_replication=no_async_snap_replication,
hourly_snap_replication_policy=hourly_snap_replication_policy,
daily_snap_replication_policy=daily_snap_replication_policy)

@staticmethod
def prepare_fs_parameters(**kwargs):
@version('<4.3')
def make_compression_body(is_compression=None):
def make_compression_body(is_compression=None,
is_advanced_dedup_enabled=None):
return UnityClient.make_body(
allow_empty=True, isCompressionEnabled=is_compression)

@version('>=4.3') # noqa
def make_compression_body(is_compression=None):
@version('>=4.3')
def make_compression_body(is_compression=None, # noqa: F811
is_advanced_dedup_enabled=None):
return UnityClient.make_body(
allow_empty=True, isDataReductionEnabled=is_compression)

@version('>=4.5')
def make_compression_body(is_compression=None, # noqa: F811
is_advanced_dedup_enabled=None):
return UnityClient.make_body(
allow_empty=True,
isDataReductionEnabled=is_compression,
isAdvancedDedupEnabled=is_advanced_dedup_enabled)

access_policy = kwargs.get('access_policy')
locking_policy = kwargs.get('locking_policy')
supported_protocols = kwargs.get('supported_protocols')
Expand All @@ -332,7 +363,9 @@ def make_compression_body(is_compression=None):
fs_param['fastVPParameters'] = UnityClient.make_body(
allow_empty=True, tieringPolicy=tiering_policy)

compression_body = make_compression_body(kwargs.get('is_compression'))
compression_body = make_compression_body(
kwargs.get('is_compression'),
kwargs.get('is_advanced_dedup_enabled'))
fs_param.update(compression_body)
return fs_param

Expand Down
10 changes: 8 additions & 2 deletions storops/unity/resource/replication_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,8 @@ def modify(self, max_time_out_of_sync=None, name=None,
hourly_snap_replication_policy=None,
daily_snap_replication_policy=None,
src_spa_interface=None, src_spb_interface=None,
dst_spa_interface=None, dst_spb_interface=None):
dst_spa_interface=None, dst_spb_interface=None,
no_async_snap_replication=None):
"""
Modifies properties of a replication session.

Expand All @@ -281,6 +282,10 @@ def modify(self, max_time_out_of_sync=None, name=None,
:param src_spb_interface: same as the one in `create` method.
:param dst_spa_interface: same as the one in `create` method.
:param dst_spb_interface: same as the one in `create` method.
:param no_async_snap_replication: whether or not snap replication is
enabled in asynchronous replication session. When enabled, snap
replication is controlled by snap replication policy setting or
user action.
"""
req_body = self._cli.make_body(
maxTimeOutOfSync=max_time_out_of_sync, name=name,
Expand All @@ -289,7 +294,8 @@ def modify(self, max_time_out_of_sync=None, name=None,
srcSPAInterface=src_spa_interface,
srcSPBInterface=src_spb_interface,
dstSPAInterface=dst_spa_interface,
dstSPBInterface=dst_spb_interface)
dstSPBInterface=dst_spb_interface,
noAsyncSnapReplication=no_async_snap_replication)

resp = self.action('modify', **req_body)
resp.raise_if_err()
Expand Down
23 changes: 10 additions & 13 deletions test-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
coverage>=4.0
flake8>=2.2.0
mock>=1.0.1
PyHamcrest>=1.8.5
pytest>=4.4.0,<6.0.0
pytest>=6.0.0
pytest-cov>=2.1.0,<2.10.1
pytest-cov>=2.10.1
pytest-xdist>=1.13.1,<2.0.0
pytest-xdist>=2.0.0
xmltodict>=0.9.2
fasteners>=0.12.0
ddt>=1.0.1 # MIT
coverage
flake8
mock
PyHamcrest
pytest
pytest-cov
pytest-xdist
xmltodict
fasteners
ddt # MIT
Loading
Loading