Skip to content
Merged
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
53 changes: 52 additions & 1 deletion cterasdk/asynchronous/core/cloudfs.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from .base_command import BaseCommand
from . import query
from ...core.query import QueryParamBuilder, FilterBuilder
from ...core.cloudfs import ZoneQueryParams, DevicesDelta, FoldersDelta
from ...common.utils import union


Expand All @@ -14,6 +15,7 @@ class CloudFS(BaseCommand):
def __init__(self, core):
super().__init__(core)
self.drives = CloudDrives(self._core)
self.zones = Zones(self._core)


class CloudDrives(BaseCommand):
Expand All @@ -31,10 +33,59 @@ async def find(self, name, owner, include=None):

:returns: A Cloud Drive Folder
"""

user = await self._core.users.get(owner, ['uid'])
include = union(include or [], CloudDrives.default)
builder = QueryParamBuilder().include(include).ownedBy(user.uid)
builder.addFilter(FilterBuilder('name').eq(name))
param = builder.build()
return query.iterator(self._core, '/cloudDrives', param)


class Zones(BaseCommand):
"""
Portal Zones APIs
"""

async def all(self, filters=None):
"""
List Zones
:param list[],optional filters: List of additional filters, defaults to None

:return: Iterator for all Zones
:rtype: cterasdk.lib.iterator.QueryIterator
"""
builder = QueryParamBuilder().include_classname().startFrom(0).countLimit(25)
filters = filters or []
for query_filter in filters:
builder.addFilter(query_filter)
builder.orFilter((len(filters) > 1))
param = builder.build()
async for zone in query.iterator(self._core, '', param, 'getZonesDisplayInfo'):
yield zone

async def list_zones(self, filters=None, expand_zone=False):
"""
List Zones
:param list[],optional filters: List of additional filters, defaults to None
:param bool,optional expand_zone: Include Cloud Drive folders and devices

:return: Iterator for all Zones
:rtype: cterasdk.lib.iterator.QueryIterator
"""
async for zone in self.all(filters):
if expand_zone:
info = await self._core.v1.api.execute('', 'getZoneBasicInfo', zone.zoneId)
zone.devices = [device async for device in query.iterator(self._core, '',
ZoneQueryParams(info.zoneId, DevicesDelta()), 'getZoneDevices')]
if info.policyType == 'selectedFolders':
zone.cloudfolders = [
volume
async for volume in query.iterator(
self._core,
'',
ZoneQueryParams(info.zoneId, FoldersDelta()),
'getZoneFolders',
)
]
yield zone
yield zone
36 changes: 36 additions & 0 deletions cterasdk/asynchronous/core/devices.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from .base_command import BaseCommand
from . import remote
from ...core.query import QueryParamBuilder
from . import query
from ...common import union


class Devices(BaseCommand):
""" Portal Devices APIs """

async def devices(self, include=None, allPortals=False, filters=None, user=None):
"""
Get Devices

:param list[str],optional include: List of fields to retrieve, defaults to ['name', 'portal', 'deviceType']
:param bool,optional allPortals: Search in all portals, defaults to False
:param list[],optional filters: List of additional filters, defaults to None
:param cterasdk.core.types.UserAccount user: User account of the device owner

:return: Iterator for all matching Devices
:rtype: cterasdk.lib.iterator.QueryIterator
"""
include = union(include or [], ['name', 'portal', 'deviceType', 'version', 'remoteAccessUrl'])
builder = QueryParamBuilder().include(include).allPortals(allPortals)
filters = filters or []
for query_filter in filters:
builder.addFilter(query_filter)
if user:
uid = self._core.users.get(user, ['uid']).uid
builder.ownedBy(uid)
builder.orFilter((len(filters) > 1))
param = builder.build()

iterator = query.iterator(self._core, '/devices', param)
async for dev in iterator:
yield remote.remote_command(self._core, dev)
22 changes: 22 additions & 0 deletions cterasdk/asynchronous/core/remote.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from ...core.enum import DeviceType
from ...objects.asynchronous import edge, drive
from ...common import parse_base_object_ref


def remote_command(core, device):
tenant = parse_base_object_ref(device.portal).name
base = f'{core.v1.ctera.baseurl}/devicecmdnew/{tenant}/{device.name}'

ManagedDevice = None
if device.deviceType in DeviceType.Gateways:
ManagedDevice = edge.AsyncEdge(core=core, base=base)
elif device.deviceType in DeviceType.Agents:
ManagedDevice = drive.AsyncDrive(core=core, base=base)
elif device.deviceType == "Mobile":
return device
else:
return device

ManagedDevice.__dict__.update(device.__dict__.copy())

return ManagedDevice
34 changes: 34 additions & 0 deletions cterasdk/asynchronous/edge/remote.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import re
import logging

from ...common import parse_base_object_ref
from ...exceptions import CTERAException


logger = logging.getLogger('cterasdk.edge')


def remote_access(device, Portal):
device_tenant = parse_base_object_ref(device.portal).name
device_name = device.name
logger.info("Enabling remote access. %s", {'tenant': device_tenant, 'device': device_name})
token = authn_token(Portal, device_tenant, device_name)
device_object = create_device_object(device)
device_object.sso(token, {Portal._session_id_key: Portal.get_session_id()}) # pylint: disable=protected-access
logger.info("Enabled remote access. %s", {'tenant': device_tenant, 'device': device_name})
return device_object


def create_device_object(device):
device_object = device.__class__(base=re.sub(r'^http(?=:)', 'https', device.remoteAccessUrl))
return device_object


def authn_token(Portal, device_tenant, device_name):
logger.debug("Retrieving SSO Ticket. %s", {'tenant': device_tenant, 'device': device_name})
token = Portal.api.execute(f"/portals/{device_tenant}/devices/{device_name}", 'singleSignOn')
if not token:
logger.error('Failed to Retrieve SSO Ticket. %s', {'tenant': device_tenant, 'device': device_name})
raise CTERAException('Failed to Retrieve SSO Ticket.')
logger.debug("Retrieved SSO Ticket. %s", {'tenant': device_tenant, 'device': device_name})
return token
9 changes: 9 additions & 0 deletions cterasdk/clients/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@ async def delete(self, path, **kwargs):
return await response.json()


class AsyncMigrate(AsyncJSON):
"""CTERA Migrate Service"""

async def login(self):
response = await Client.get(self, '/auth/user', on_error=JSONHandler())
self.headers.persist_response_header(response, 'x-mt-x')
return response.json()


class AsyncXML(AsyncClient):

async def get(self, path, **kwargs):
Expand Down
34 changes: 33 additions & 1 deletion cterasdk/core/cloudfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from .base_command import BaseCommand
from . import query, devices
from .enum import ListFilter, PolicyType
from .types import ArchiveSettingsBuilder, ComplianceSettingsBuilder, ExtendedAttributesBuilder
from .types import ArchiveSettingsBuilder, ComplianceSettingsBuilder, ExtendedAttributesBuilder, DevicesDelta, FoldersDelta
from ..common import union, Object
from ..exceptions import CTERAException, ObjectNotFoundException

Expand Down Expand Up @@ -519,6 +519,19 @@ def delete(self, name):
return response


class ZoneQueryParams(Object):

def __init__(self, zone_id, delta):
super().__init__()
self._classname = 'ZoneQuery'
self.zoneId = zone_id
self.query = query.QueryParamBuilder().include_classname().orFilter(True).build()
self.delta = delta

def increment(self):
return self.query.increment()


class Zones(BaseCommand):
"""
Portal Zones APIs
Expand Down Expand Up @@ -565,6 +578,25 @@ def all(self, filters=None):
param = builder.build()
return query.iterator(self._core, '', param, 'getZonesDisplayInfo')

def list_zones(self, filters=None, expand_zone=False):
"""
List Zones
:param list[],optional filters: List of additional filters, defaults to None
:param bool,optional expand_zone: Include Cloud Drive folders and devices

:return: Iterator for all Zones
:rtype: cterasdk.lib.iterator.QueryIterator
"""
for zone in self.all(filters):
if expand_zone:
info = self._core.api.execute('', 'getZoneBasicInfo', zone.zoneId)
zone.devices = list(query.iterator(self._core, '', ZoneQueryParams(info.zoneId, DevicesDelta()), 'getZoneDevices'))
if info.policyType == 'selectedFolders':
zone.cloudfolders = list(query.iterator(self._core, '',
ZoneQueryParams(info.zoneId, FoldersDelta()), 'getZoneFolders'))
yield zone
yield zone

def search(self, name):
"""
Search for Zones by name
Expand Down
8 changes: 4 additions & 4 deletions cterasdk/core/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
from ..common import parse_base_object_ref


def remote_command(Portal, device):
def remote_command(core, device):
tenant = parse_base_object_ref(device.portal).name
base = f'{Portal.ctera.baseurl}/devicecmdnew/{tenant}/{device.name}'
base = f'{core.ctera.baseurl}/devicecmdnew/{tenant}/{device.name}'

ManagedDevice = None
if device.deviceType in DeviceType.Gateways:
ManagedDevice = edge.Edge(Portal=Portal, base=base)
ManagedDevice = edge.Edge(core=core, base=base)
elif device.deviceType in DeviceType.Agents:
ManagedDevice = drive.Drive(Portal=Portal, base=base)
ManagedDevice = drive.Drive(core=core, base=base)
elif device.deviceType == "Mobile":
return device
else:
Expand Down
25 changes: 25 additions & 0 deletions cterasdk/core/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -1270,3 +1270,28 @@ def __init__(self, operator, value):
@staticmethod
def contains(value):
return ContentFilter(SearchOperator.CONTAINS, value)


class ZoneDelta(Object):

def __init__(self):
super().__init__()
self._classname = 'ZoneDelta'


class FoldersDelta(ZoneDelta):

def __init__(self):
super().__init__()
self.policyDelta = []


class DevicesDelta(ZoneDelta):

def __init__(self):
super().__init__()
self.devicesDelta = Object(
_classname='ZoneDeviceDelta',
added=[],
removed=[]
)
Loading
Loading