def get_bucket(self, bucket): """Retrieve specific bucket :param bucket: Bucket name :type bucket: str :return: Bucket information :rtype: dict """ try: # Retrieve buckets data = self.get_buckets() if "errors" in data: return data # Loop over buckets until filter match for bucket_info in data: if bucket_info["Name"] == bucket: # Return data return bucket_info # Return error if no bucket is found return resource_not_found() except Exception as error: return resource_error("unable_to_fetch_bucket", error)
def authorize_host_to_volume(self, **kwargs): """Authorizes hosts to File Storage Volumes :param volume_id: The File volume to authorize hosts to :type volume_id: str :param hardware_ids: A List of SoftLayer_Hardware IDs :type hardware_ids: list :param virtual_guest_ids: A List of SoftLayer_Virtual_Guest IDs :type virtual_guest_ids: list :param ip_address_ids: A List of SoftLayer_Network_Subnet_IpAddress IDs :type ip_address_ids: list :param subnet_ids: A List of SoftLayer_Network_Subnet ids """ args = ["volume_id", "hardware_ids", "virtual_guest_ids", "ip_address_ids", "subnet_ids"] check_args(args, **kwargs) # Build dict of argument and assign default value when needed args = { 'volume_id': kwargs.get('volume_id'), 'hardware_ids': kwargs.get('hardware_ids') or None, 'virtual_guest_ids': kwargs.get('virtual_guest_ids') or None, 'ip_address_ids': kwargs.get('ip_address_ids') or None, 'subnet_ids': kwargs.get('subnet_ids') or None } try: self.file.authorize_host_to_volume(args['volume_id'], args['hardware_ids'], args['virtual_guest_ids'], args['ip_address_ids'], args['subnet_ids']) except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def create_snapshot(self, **kwargs): """Creates a snapshot on the given file volume :param volume_id: The volume ID :type volume_id: int :param notes: The notes or "name" to assign the snapshot :type notes: str :return: Returns the id of the new snapshot :rtype: str """ args = ["volume_id", "notes"] check_args(args, **kwargs) # Build dict of argument and assign default value when needed args = { 'volume_id': kwargs.get('volume_id'), 'notes': kwargs.get('notes'), } try: return self.file.create_snapshot( args['volume_id'], notes=args['notes']) except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def download_file(self, **kwargs): """Download file from a S3 object :param bucket: Bucket name :type bucket: str :param path: The path to the file to download to :type path: str :param key: The name of the key to download from :type key: str :return: Download status :rtype: dict """ args = ["bucket", "path", "key"] check_args(args, **kwargs) # Build dict of argument and assign default value when needed args = { 'bucket': kwargs.get('bucket'), 'key': kwargs.get('key'), 'path': kwargs.get('path'), } try: result = self.client.download_file( args["bucket"], args["key"], args["path"]) if result is not None: return result msg = {"object": args["key"], "path": args['path'], "status": "downloaded"} return resource_created(msg) except Exception as error: return resource_error("unable_to_download_object", error)
def cancel_file_volume(self, **kwargs): """Cancels the given file storage volume :param volume_id: The volume ID :type volume_id: int :param reason: The reason for cancellation :type reason: str :param immediate: Cancel immediately or on anniversary date :type immediate: bool """ args = ["volume_id", "reason", "immediate"] check_args(args, **kwargs) # Build dict of argument and assign default value when needed args = { 'volume_id': kwargs.get('volume_id'), 'reason': kwargs.get('reason'), 'immediate': kwargs.get('immediate') } try: return self.file.cancel_file_volume(args['volume_id'], reason=args['reason'], immediate=args['immediate']) except sl.SoftLayer.exceptions.SoftLayerError: return({"msg": "Storage Volume was already cancelled"}) except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def get_operating_system(self, image, package=None): """Retrieve specific baremetal operating system :param image: Image name :type image: str :param package: Package name, defaults to `BARE_METAL_SERVER` :type package: str, optional :return: Baremetal operating system :rtype: dict """ # Package should have "os" category code. # By default BARE_METAL_SERVER will be used. pkg_name = "BARE_METAL_SERVER" if package: pkg_name = package try: # Retrieve operating systems data = self.get_operating_systems(pkg_name) # Loop over operating systems until filter match for operating_system in data["operating_systems"]: if operating_system["keyName"] == image: # Return data return operating_system # Return error if no operating system is found return resource_not_found() except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def order_modified_volume(self, **kwargs): """Places an order for modifying an existing file volume :param volume_id: The ID of the volume to be modified :type volume_id: int :param new_size: The new size/capacity for the volume :type new_size: int :param new_iops: The new IOPS for the volume :type new_iops: int :param new_tier_level: The new tier level for the volume :type new_tier_level: str :return: Returns a SoftLayer_Container_Product_Order_Receipt :rtype: dict """ args = ["volume_id", "new_size", "new_iops", "new_tier_level"] check_args(args, **kwargs) # Build dict of argument and assign default value when needed args = { 'volume_id': kwargs.get('storage_type'), 'new_size': kwargs.get('new_size'), 'new_iops': kwargs.get('new_iops'), 'new_tier_level': kwargs.get('new_tier_level') } try: return self.file.order_modified_volume( args['volume_id'], args['new_size'], args['new_iops'], args['new_tier_level']) except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def get_operating_systems(self, package=None): """Retrieve baremetal operating system list :param package: Package name, defaults to `BARE_METAL_SERVER` :type package: str, optional :return: Baremetal operating system list :rtype: dict """ # Provided package should have "os" category code. pkg_name = "BARE_METAL_SERVER" if package: pkg_name = package filter = {"items": {"categories": {"categoryCode": { "operation": "_= os"}}}} mask = ("mask[id, keyName, description, itemCategory, categories," "prices]") try: # Retrieve package ID base on package keyname pkg_id = self.order.get_package_by_key(pkg_name, mask='id')['id'] images = {} images["operating_systems"] = self.client.call( "Product_Package", "getItems", id=pkg_id, filter=filter, mask=mask, iter=True) return images except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def order_snapshot_space(self, **kwargs): """Orders snapshot space for the given file volume :param volume_id: The ID of the volume :type volume_id: int :param capacity: The capacity to order, in GB :type capacity: int :param tier: The tier level of the file volume, in IOPS per GB :type tier: int :param upgrade: Flag to indicate if this order is an upgrade :type upgrade: bool :return: Returns a SoftLayer_Container_Product_Order_Receipt :rtype: dict """ args = ["volume_id", "capacity", "tier", "upgrade"] check_args(args, **kwargs) # Build dict of argument and assign default value when needed args = { 'volume_id': kwargs.get('storage_type'), 'capacity': kwargs.get('capacity'), 'tier': kwargs.get('tier'), 'upgrade': kwargs.get('upgrade') } try: return self.file.order_snapshot_space(args['volume_id'], args['capacity'], args['tier'], args['upgrade']) except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def failover_to_replicant(self, **kwargs): """Failover to a volume replicant :param volume_id: The ID of the volume :type volume_id: int :param replicant_id: ID of replicant to failback from :type replicant_id: int :param immediate: Flag indicating if failover is immediate :type immediate: bool :return: Returns whether failover was successful or not """ args = ["volume_id", "replicant_id"] check_args(args, **kwargs) # Build dict of argument and assign default value when needed args = { 'volume_id': kwargs.get('volume_id'), 'replicant_id': kwargs.get('replicant_id'), 'immediate': kwargs.get('immediate') } try: return self.file.failover_to_replicant( args['volume_id'], args['replicant_id'], immediate=args['immediate']) except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def delete_bucket(self, bucket): """Delete bucket :param bucket: Bucket name :type bucklet: str :return: Deletion status :rtype: dict """ try: # Pagination p = self.client.get_paginator('list_objects') # Delete objects (1000 objects max at a time) for page in p.paginate(Bucket=bucket): keys = [{ 'Key': obj['Key'] } for obj in page.get('Contents', [])] if keys: self.client.delete_objects(Bucket=bucket, Delete={'Objects': keys}) result = self.client.delete_bucket(Bucket=bucket) if result["ResponseMetadata"]["HTTPStatusCode"] != 204: return result return resource_deleted() except Exception as error: return resource_error("unable_to_delete", error)
def list_file_volumes(self, **kwargs): """Returns a list of file volumes :param datacenter: Datacenter short name `(e.g.: dal09)` :type datacenter: str :param username: Name of volume :type username: str :param storage_type: Type of volume "Endurance|Performance" :type storage_type: str :param order: Volume order ID :type order: int :return: Returns a list of file volumes :rtype: list """ # Build dict of argument and assign default value when needed args = { 'datacenter': kwargs.get('datacenter') or None, 'username': kwargs.get('username') or None, 'storage_type': kwargs.get('storage_type') or None, 'order': kwargs.get('order') or None } _kwargs = {} _filter = sl_utils.NestedDict({}) result = [] _filter['nasNetworkStorage']['serviceResource']['type']['type'] = \ (sl_utils.query_filter('!~ NAS')) _filter['nasNetworkStorage']['storageType']['keyName'] = ( sl_utils.query_filter('*FILE_STORAGE*')) if args['username']: _filter['nasNetworkStorage']['username'] = \ (sl_utils.query_filter(args['username'])) if args['datacenter']: _filter['nasNetworkStorage']['serviceResource']['datacenter'][ 'name'] = (sl_utils.query_filter(args['datacenter'])) if args['storage_type']: _filter['nasNetworkStorage']['storageType']['keyName'] = \ (sl_utils.query_filter( '%s_FILE_STORAGE*' % args['storage_type'].upper())) if args['order']: _filter['nasNetworkStorage']['billingItem']['orderItem'][ 'order']['id'] = (sl_utils.query_filter(args['order'])) _kwargs['filter'] = _filter.to_dict() try: r = self.client.call('Account', 'getNasNetworkStorage', **_kwargs) for fs in r: result.append(fs) return result except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def order_file_volume(self, **kwargs): """Places an order for a file volume :param storage_type: Type of volume "Endurance|Performance" :type storage_type: str :param location: Name of the datacenter in which to order the volume :type location: str :param size: Size of the desired volume, in GB :type size: int :param iops: Number of IOPS for a "Performance" order :type iops: int :param tier_level: Tier level to use for an "Endurance" order (0.25|2|4|10) :type tier_level: int :param snapshot_size: The size of optional snapshot space, if snapshot space should also be ordered (None if not ordered) :type snapshot_size: int :param service_offering: Requested offering package to use in the order ("storage_as_a_service", "enterprise", or "performance") :type service_offering: str :param hourly_billing_flag: Billing type, monthly (False) or hourly (True), default to monthly :type hourly_billing_flag: bool :return: Created volume description :rtype: dict """ args = ["storage_type", "location", "size"] check_args(args, **kwargs) # Build dict of argument and assign default value when needed args = { 'storage_type': kwargs.get('storage_type'), 'location': kwargs.get('location'), 'size': kwargs.get('size'), 'iops': kwargs.get('iops') or None, 'tier_level': kwargs.get('tier_level') or None, 'snapshot_size': kwargs.get('snapshot_size') or None, 'service_offering': kwargs.get('service_offering', 'storage_as_a_service'), 'hourly_billing_flag': kwargs.get('hourly_billing_flag') or False } try: order = self.file.order_file_volume( args['storage_type'], args['location'], args['size'], iops=args['iops'], tier_level=args['tier_level'], snapshot_size=args['snapshot_size'], service_offering=args['service_offering'], hourly_billing_flag=args['hourly_billing_flag']) return order except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def delete_snapshot(self, snapshot_id): """Deletes the specified snapshot object :param snapshot_id: The ID of the snapshot object to delete :type snapshot_id: int """ try: return self.file.delete_snapshot(snapshot_id) except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def get_file_volume_details(self, volume_id): """Returns details about the specified volume :param volume_id: The ID of the volume :type volume_id: int :return: Returns details about the specified volume """ try: return self.file.get_file_volume_details(volume_id) except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def set_baremetal_power_state(self, **kwargs): """Set baremetal power state :param baremetal: Baremetal name or ID :type baremetal: str :parem power_state: Target power state :type power_state: str :return: Power state :rtype: dict """ args = ["baremetal", "power_state"] check_args(args, **kwargs) # Build dict of argument and assign default value when needed args = { 'baremetal': kwargs.get('baremetal'), 'power_state': kwargs.get('power_state'), } # Retrieve baremetal info and check is exists bm_info = self.get_baremetal(args["baremetal"]) if "errors" in bm_info: return bm_info switch = { "off": "powerOff", "on": "powerOn", "reboot": "powerCycle", } if args["power_state"] not in switch: return resource_error("state_not_valid", "available states: {}".format(list(switch))) try: state = self.client.call("Hardware_Server", switch.get(args["power_state"]), id=bm_info["id"]) if state: return {"power_state": args["power_state"]} except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def get_replication_locations(self, volume_id): """Acquires list of the datacenters to which a volume can be replicated :param volume_id: The ID of the volume :type volume_id: int :return: Returns an array of SoftLayer_Network_Storage objects :rtype: list """ try: return self.file.get_replication_locations(volume_id) except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def get_file_volume_snapshot_list(self, volume_id): """Returns a list of snapshots for the specified volume :param volume_id: The ID of the volume :type volume_id: int :return: Returns a list of snapshots for the specified volume :rtype: list """ try: return self.file.get_file_volume_snapshot_list(volume_id) except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def get_baremetal_by_id(self, id): """Retrieve specific baremetal by ID :param id: Baremetal ID :type id: str :return: Baremetal server information :rtype: dict """ try: return self.hw.get_hardware(id) except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def get_file_storage(self, file_storage): """Retrieve specific file storage by ID :param file_storage: File storage ID :type file_storage: int :return: File storage information :rtype: dict """ try: return self.file.get_file_volume_details(file_storage) except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def get_subnet_by_id(self, id): """Retrieve specific subnet by ID :param id: Subnet ID :type id: str :return: Subnet server information :rtype: dict """ try: return self.hw.get_subnet(id, mask=self.DEFAULT_SUBNET_MASK) except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def get_buckets(self): """Retrieve bucket list :return List of buckets :rtype dict """ try: data = self.client.list_buckets() return data['Buckets'] except Exception as error: return resource_error("unable_to_fetch_bucket_list", error)
def get_file_storages(self): """Retrieve file storage list :return: List of file storage :rtype: dict """ try: file_storage = {} file_storage["file_storages"] = self.file.list_file_volumes() return file_storage except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def get_locations(self): """Retrieve all datacenter locations :return: List of datacenter location :rtype: dict """ mask = "id,name,regions[keyname,description]" try: locations = {} locations["datacenters"] = self.client.call( "SoftLayer_Location", "getDatacenters", mask=mask) return locations except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def get_subnets(self): """Retrieve subnet list :return: List of subnet servers :rtype: dict """ # Display all the fields. mask = "" try: subnets = {} subnets = self.hw.list_subnets(mask=self.DEFAULT_SUBNET_MASK) return subnets except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def get_baremetals(self): """Retrieve baremetal list :return: List of baremetal servers :rtype: dict """ # Display all the fields. mask = "" try: baremetal = {} baremetal["baremetals"] = self.hw.list_hardware(mask=mask) return baremetal except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def place(self, **kwargs): """Place an order :param package: The package being ordered :type package: str :param location: The datacenter location string for ordering :type location: str :param items: The list of item keyname strings to order :type items: list :param complex_type: The complex type to send with the order :type complex_type: str :param hourly: If true, uses hourly billing, defaults to `True` :type hourly: bool, optional :param preset: Specifies a preset to use for that package :type preset: str, optional :param extras: The extra data for the order in dictionary format :type extras: dict :param quantity: The number of resources to order, default to `1` :type quantity: int, optional :return: The placed order :rtype: dict """ args = ["package", "location", "items", "complex_type", "extras"] check_args(args, **kwargs) # Build dict of argument and assign default value when needed args = { 'package': kwargs.get('package'), 'location': kwargs.get('location'), 'items': kwargs.get('items'), 'complex_type': kwargs.get('complex_type'), 'hourly': kwargs.get('hourly', True), 'preset': kwargs.get('preset'), 'extras': kwargs.get('extras'), 'quantity': kwargs.get('quantity', 1), } try: return self.order.place_order( args['package'], args['location'], args['items'], hourly=args['hourly'], preset_keyname=args['preset'], complex_type=args['complex_type'], extras=args['extras'], quantity=args['quantity']) except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)
def delete_objects(self, bucket, objects): """Delete objects from the bucket :param bucket: Bucket name :type bucket: str :param objects: List of objects to delete :type objects: list """ try: for object in objects: result = self.client.delete_object(Bucket=bucket, Key=object) if result["ResponseMetadata"]["HTTPStatusCode"] != 204: return result return resource_deleted() except Exception as error: return resource_error("unable_to_delete_objects", error)
def delete_object(self, bucket, object): """Delete an object from the bucket :param bucket: Bucket name :type bucket: str :param object: The name of the object to delete :type object: str :return: Deletion status :rtype: dict """ try: result = self.client.delete_object(Bucket=bucket, Key=object) if result["ResponseMetadata"]["HTTPStatusCode"] != 204: return result return resource_deleted() except Exception as error: return resource_error("unable_to_delete_object", error)
def enable_snapshots(self, **kwargs): """Enables snapshots for a specific file volume at a given schedule :param volume_id: The ID of the volume :type volume_id: int :param schedule_type: 'HOURLY'|'DAILY'|'WEEKLY' :type schedule_type: str :param retention_count: The number of snapshots to attempt to retain in this schedule :type retention_count: int :param minute: The minute of the hour at which HOURLY, DAILY, and WEEKLY snapshots should be taken :type minute: int :param hour: The hour of the day at which DAILY and WEEKLY snapshots should be taken :type hour: int :param day_of_week: The day of the week on which WEEKLY snapshots should be taken an integer ('0' is Sunday) :type day: int """ args = ["volume_id", "schedule_type", "retention_count", "minute"] check_args(args, **kwargs) # Build dict of argument and assign default value when needed args = { 'volume_id': kwargs.get('volume_id'), 'schedule_type': kwargs.get('schedule_type'), 'retention_count': kwargs.get('retention_count'), 'minute': kwargs.get('minute'), 'hour': kwargs.get('hour'), 'day_of_week': kwargs.get('day_of_week') } try: return self.file.enable_snapshots(args['volume_id'], args['schedule_type'], args['retention_count'], args['minute'], args['hour'], args['day_of_week']) except sl.SoftLayer.SoftLayerAPIError as error: return resource_error(error.faultCode, error.faultString)