Skip to content
3 changes: 1 addition & 2 deletions cterasdk/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# pylint: disable=wrong-import-position
import cterasdk.settings # noqa: E402, F401
import cterasdk.logging # noqa: E402, F401

from .common import Object, PolicyRule # noqa: E402, F401
from .convert import fromjsonstr, tojsonstr, fromxmlstr, toxmlstr # noqa: E402, F401
Expand All @@ -12,5 +11,5 @@
from .core import enum as core_enum # noqa: E402, F401
from .common import types as common_types # noqa: E402, F401
from .common import enum as common_enum # noqa: E402, F401
from .objects import GlobalAdmin, ServicesPortal, Edge, Drive, AsyncGlobalAdmin, AsyncServicesPortal # noqa: E402, F401
from .objects import GlobalAdmin, ServicesPortal, Edge, Drive, AsyncGlobalAdmin, AsyncServicesPortal, AsyncEdge # noqa: E402, F401
from . import direct as ctera_direct # noqa: E402, F401
6 changes: 3 additions & 3 deletions cterasdk/asynchronous/core/files/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ async def handle(self, path):

:param str path: Path to a file
"""
handle_function = await io.handle(self.normalize(path))
handle_function = io.handle(self.normalize(path))
return await handle_function(self._core)

async def handle_many(self, directory, *objects):
Expand All @@ -26,7 +26,7 @@ async def handle_many(self, directory, *objects):
:param str directory: Path to a folder
:param args objects: List of files and folders
"""
handle_many_function = await io.handle_many(self.normalize(directory), *objects)
handle_many_function = io.handle_many(self.normalize(directory), *objects)
return await handle_many_function(self._core)

async def download(self, path, destination=None):
Expand Down Expand Up @@ -136,7 +136,7 @@ async def upload(self, name, size, destination, handle):
:param str destination: Path to remote directory.
:param object handle: Handle.
"""
upload_function = await io.upload(name, size, self.normalize(destination), handle)
upload_function = io.upload(name, size, self.normalize(destination), handle)
return await upload_function(self._core)

async def upload_file(self, path, destination):
Expand Down
6 changes: 3 additions & 3 deletions cterasdk/asynchronous/core/files/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ async def retrieve_remote_dir(core, directory):
return str(resource.cloudFolderInfo.uid)


async def handle(path):
def handle(path):
"""
Create function to retrieve file handle.

Expand All @@ -106,7 +106,7 @@ async def wrapper(core):
return wrapper


async def handle_many(directory, *objects):
def handle_many(directory, *objects):
"""
Create function to retrieve zip archive

Expand All @@ -128,7 +128,7 @@ async def wrapper(core):
return wrapper


async def upload(name, size, destination, fd):
def upload(name, size, destination, fd):
"""
Create upload function

Expand Down
8 changes: 8 additions & 0 deletions cterasdk/asynchronous/edge/base_command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class BaseCommand:
"""Base Class for CTERA Edge Filer API Commands"""

def __init__(self, edge):
self._edge = edge

def session(self):
return self._edge.session()
1 change: 1 addition & 0 deletions cterasdk/asynchronous/edge/files/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .browser import FileBrowser # noqa: E402, F401
142 changes: 142 additions & 0 deletions cterasdk/asynchronous/edge/files/browser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
from ..base_command import BaseCommand
from ....cio.edge import EdgePath
from ....lib.storage import asynfs, commonfs
from . import io


class FileBrowser(BaseCommand):
""" Edge Filer File Browser APIs """

async def listdir(self, path):
"""
List Directory

:param str path: Path
"""
return await io.listdir(self._edge, path)

async def handle(self, path):
"""
Get File Handle.

:param str path: Path to a file
"""
handle_function = io.handle(self.normalize(path))
return await handle_function(self._edge)

async def handle_many(self, directory, *objects):
"""
Get a Zip Archive File Handle.

:param str directory: Path to a folder
:param args objects: List of files and folders
"""
handle_many_function = io.handle_many(self.normalize(directory), *objects)
return await handle_many_function(self._edge)

async def download(self, path, destination=None):
"""
Download a file

:param str path: The file path on the Edge Filer
:param str,optional destination:
File destination, if it is a directory, the original filename will be kept, defaults to the default directory
"""
directory, name = commonfs.determine_directory_and_filename(path, destination=destination)
handle = await self.handle(path)
return await asynfs.write(directory, name, handle)

async def download_many(self, target, objects, destination=None):
"""
Download selected files and/or directories as a ZIP archive.

.. warning::
The provided list of objects is not validated. Only existing files and directories
will be included in the resulting ZIP file.

:param str target:
Path to the cloud folder containing the files and directories to download.
:param list[str] objects:
List of file and/or directory names to include in the download.
:param str destination:
Optional. Path to the destination file or directory. If a directory is provided,
the original filename will be preserved. Defaults to the default download directory.
"""
directory, name = commonfs.determine_directory_and_filename(target, objects, destination=destination, archive=True)
handle = await self.handle_many(target, *objects)
return await asynfs.write(directory, name, handle)

async def upload(self, name, destination, handle):
"""
Upload from file handle.

:param str name: File name.
:param str destination: Path to remote directory.
:param object handle: Handle.
"""
upload_function = io.upload(name, self.normalize(destination), handle)
return await upload_function(self._edge)

async def upload_file(self, path, destination):
"""
Upload a file.

:param str path: Local path
:param str destination: Remote path
"""
metadata = commonfs.properties(path)
with open(path, 'rb') as handle:
response = await self.upload(metadata['name'], destination, handle)
return response

async def mkdir(self, path):
"""
Create a new directory

:param str path: Directory path
"""
return await io.mkdir(self._edge, self.normalize(path))

async def makedirs(self, path):
"""
Create a directory recursively

:param str path: Directory path
"""
return await io.makedirs(self._edge, self.normalize(path))

async def copy(self, path, destination=None, overwrite=False):
"""
Copy a file or a folder

:param str path: Source file or folder path
:param str destination: Destination folder path
:param bool,optional overwrite: Overwrite on conflict, defaults to False
"""
if destination is None:
raise ValueError('Copy destination was not specified.')
return await io.copy(self._edge, self.normalize(path), self.normalize(destination), overwrite)

async def move(self, path, destination=None, overwrite=False):
"""
Move a file or a folder

:param str path: Source file or folder path
:param str destination: Destination folder path
:param bool,optional overwrite: Overwrite on conflict, defaults to False
"""
if destination is None:
raise ValueError('Move destination was not specified.')
return await io.move(self._edge, self.normalize(path), self.normalize(destination), overwrite)

async def delete(self, path):
"""
Delete a file

:param str path: File path
"""
return await io.remove(self._edge, self.normalize(path))

@staticmethod
def normalize(path):
return EdgePath('/', path)
105 changes: 105 additions & 0 deletions cterasdk/asynchronous/edge/files/io.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import logging
from ....cio.common import encode_request_parameter
from ....cio import edge as fs
from ....cio import exceptions


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


async def listdir(edge, path):
with fs.listdir(path) as param:
return await edge.api.execute('/status/fileManager', 'listPhysicalFolders', param)


async def mkdir(edge, path):
with fs.makedir(path) as param:
await edge.io.mkdir(param)
return path.absolute


async def makedirs(edge, path):
directories = path.parts
for i in range(1, len(directories) + 1):
path = fs.EdgePath(path.scope, '/'.join(directories[:i]))
try:
await mkdir(edge, path)
except exceptions.RestrictedPathError:
logger.warning('Creating a folder in the specified location is forbidden: %s', path.reference.as_posix())


async def copy(edge, path, destination=None, overwrite=False):
with fs.copy(path, destination) as (src, dst):
await edge.io.copy(src, dst, overwrite=overwrite)


async def move(edge, path, destination=None, overwrite=False):
with fs.move(path, destination) as (src, dst):
await edge.io.move(src, dst, overwrite=overwrite)


async def remove(edge, *paths):
for path in fs.delete_generator(*paths):
await edge.io.delete(path.absolute)


def handle(path):
"""
Create function to retrieve file handle.

:param cterasdk.cio.edge.EdgePath path: Path to file.
:returns: Callable function to retrieve file handle.
:rtype: callable
"""
async def wrapper(edge):
"""
Get file handle.

:param cterasdk.objects.synchronous.edge.Edge edge: Edge Filer object.
"""
with fs.handle(path) as param:
return await edge.io.download(param)
return wrapper


def handle_many(directory, *objects):
"""
Create function to retrieve zip archive

:param cterasdk.cio.edge.EdgePath directory: Path to directory.
:param args objects: List of files and folders.
:returns: Callable function to retrieve file handle.
:rtype: callable
"""
async def wrapper(edge):
"""
Upload file from metadata and file handle.

:param cterasdk.objects.synchronous.edge.Edge edge: Edge Filer object.
:param str name: File name.
:param object handle: File handle.
"""
with fs.handle_many(directory, objects) as param:
return await edge.io.download_zip('/admingui/api/status/fileManager/zip', encode_request_parameter(param))
return wrapper


def upload(name, destination, fd):
"""
Create upload function

:param str name: File name.
:param cterasdk.cio.edge.EdgePath destination: Path to directory.
:param object fd: File handle.
:returns: Callable function to start the upload.
:rtype: callable
"""
async def wrapper(edge):
"""
Upload file from metadata and file handle.

:param cterasdk.objects.synchronous.edge.Edge edge: Edge Filer object.
"""
with fs.upload(name, destination, fd) as param:
return await edge.io.upload('/actions/upload', param)
return wrapper
35 changes: 35 additions & 0 deletions cterasdk/asynchronous/edge/login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import logging

from .base_command import BaseCommand
from ...exceptions import CTERAException


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


class Login(BaseCommand):
"""
CTERA Edge Filer Login APIs
"""

async def login(self, username, password):
host = self._edge.host()
try:
await self._edge.api.form_data('/login', {'username': username, 'password': password})
logging.getLogger('cterasdk.edge').info("User logged in. %s", {'host': host, 'user': username})
except CTERAException:
logging.getLogger('cterasdk.edge').error("Login failed. %s", {'host': host, 'user': username})
raise

async def logout(self):
"""
Log out of the portal
"""
host = self._edge.host()
user = self._edge.session().account.name
try:
await self._edge.api.form_data('/logout', {'foo': 'bar'})
logging.getLogger('cterasdk.edge').info("User logged out. %s", {'host': host, 'user': user})
except CTERAException:
logging.getLogger('cterasdk.edge').error("Logout failed. %s", {'host': host, 'user': user})
raise
13 changes: 6 additions & 7 deletions cterasdk/audit/postman.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import atexit
import logging
import cterasdk.settings
from ..lib import FileSystem
from ..lib.storage import synfs, commonfs
from ..common import Object, utf8_decode, utf8_encode
from ..convert import fromjsonstr, fromxmlstr, tojsonstr, toxmlstr
from ..objects import uri
Expand Down Expand Up @@ -227,14 +227,13 @@ def __init__(self, raw, protocol, host, port, path, query):

@atexit.register
def audit():
if cterasdk.settings.sessions.management.audit.postman.enabled:
fs = FileSystem.instance()
if cterasdk.settings.audit.enabled:
collection = Collection.instance()
name = cterasdk.settings.sessions.management.audit.postman.name
name = cterasdk.settings.audit.filename
collection.info.name = name if name is not None else str(uuid.uuid4())
filename = f'{collection.info.name}.json'
logging.getLogger('cterasdk.http.trace').info('Saving Postman audit file. %s', {
'directory': fs.downloads_directory(),
logging.getLogger('cterasdk.http').info('Saving Postman audit file. %s', {
'directory': commonfs.downloads(),
'name': filename
})
fs.save(fs.downloads_directory(), filename, utf8_encode(collection.serialize()))
synfs.write(commonfs.downloads(), filename, utf8_encode(collection.serialize()))
Loading