Exemple #1
0
class Controller(rest.RestController):
    """Version 1 API controller root."""

    isystems = system.SystemController()
    ihosts = host.HostController()
    helm_charts = helm_charts.HelmChartsController()
    inodes = node.NodeController()
    icpus = cpu.CPUController()
    imemorys = memory.MemoryController()
    iinterfaces = interface.InterfaceController()
    ports = port.PortController()
    ethernet_ports = ethernet_port.EthernetPortController()
    istors = storage.StorageController()
    ilvgs = lvg.LVGController()
    ipvs = pv.PVController()
    idisks = disk.DiskController()
    partitions = partition.PartitionController()
    iprofile = profile.ProfileController()
    itrapdest = trapdest.TrapDestController()
    icommunity = community.CommunityController()
    iuser = user.UserController()
    idns = dns.DNSController()
    intp = ntp.NTPController()
    ptp = ptp.PTPController()
    iextoam = network_oam.OAMNetworkController()
    controller_fs = controller_fs.ControllerFsController()
    storage_backend = storage_backend.StorageBackendController()
    storage_lvm = storage_lvm.StorageLVMController()
    storage_file = storage_file.StorageFileController()
    storage_external = storage_external.StorageExternalController()
    storage_ceph = storage_ceph.StorageCephController()
    storage_tiers = storage_tier.StorageTierController()
    storage_ceph_external = \
        storage_ceph_external.StorageCephExternalController()
    ceph_mon = ceph_mon.CephMonController()
    drbdconfig = drbdconfig.drbdconfigsController()
    addresses = address.AddressController()
    addrpools = address_pool.AddressPoolController()
    routes = route.RouteController()
    certificate = certificate.CertificateController()
    isensors = sensor.SensorController()
    isensorgroups = sensorgroup.SensorGroupController()
    loads = load.LoadController()
    pci_devices = pci_device.PCIDeviceController()
    upgrade = upgrade.UpgradeController()
    networks = network.NetworkController()
    interface_networks = interface_network.InterfaceNetworkController()
    service_parameter = service_parameter.ServiceParameterController()
    clusters = cluster.ClusterController()
    lldp_agents = lldp_agent.LLDPAgentController()
    lldp_neighbours = lldp_neighbour.LLDPNeighbourController()
    services = service.SMServiceController()
    servicenodes = servicenode.SMServiceNodeController()
    servicegroup = servicegroup.SMServiceGroupController()
    health = health.HealthController()
    registry_image = registry_image.RegistryImageController()
    remotelogging = remotelogging.RemoteLoggingController()
    sdn_controller = sdn_controller.SDNControllerController()
    license = license.LicenseController()
    labels = label.LabelController()
    fernet_repo = fernet_repo.FernetKeyController()
    apps = kube_app.KubeAppController()
    datanetworks = datanetwork.DataNetworkController()
    interface_datanetworks = interface_datanetwork.InterfaceDataNetworkController()
    host_fs = host_fs.HostFsController()

    @wsme_pecan.wsexpose(V1)
    def get(self):
        # NOTE: The reason why convert() it's being called for every
        #       request is because we need to get the host url from
        #       the request object to make the links.
        return V1.convert()
Exemple #2
0
class StorageTierController(rest.RestController):
    """REST controller for storage tiers."""

    istors = storage_api.StorageController(from_tier=True)
    "Expose istors as a sub-element of storage_tier"

    _custom_actions = {
        'detail': ['GET'],
    }

    def __init__(self, from_cluster=False, **kwargs):
        self._from_cluster = from_cluster
        self._ceph = ceph.CephApiOperator()

    def _get_tiers_collection(self,
                              uuid,
                              marker,
                              limit,
                              sort_key,
                              sort_dir,
                              expand=False,
                              resource_url=None):

        if self._from_cluster and not uuid:
            raise exception.InvalidParameterValue(
                _("Cluster id not specified."))

        limit = utils.validate_limit(limit)
        sort_dir = utils.validate_sort_dir(sort_dir)

        marker_obj = None
        if marker:
            marker_obj = objects.storage_tier.get_by_uuid(
                pecan.request.context, marker)

        if self._from_cluster:
            storage_tiers = pecan.request.dbapi.storage_tier_get_by_cluster(
                uuid,
                limit=limit,
                marker=marker_obj,
                sort_key=sort_key,
                sort_dir=sort_dir)

        else:
            storage_tiers = pecan.request.dbapi.storage_tier_get_list(
                limit, marker_obj, sort_key=sort_key, sort_dir=sort_dir)

        return StorageTierCollection.convert_with_links(storage_tiers,
                                                        limit,
                                                        url=resource_url,
                                                        expand=expand,
                                                        sort_key=sort_key,
                                                        sort_dir=sort_dir)

    @wsme_pecan.wsexpose(StorageTierCollection, types.uuid, types.uuid, int,
                         wtypes.text, wtypes.text)
    def get_all(self,
                uuid=None,
                marker=None,
                limit=None,
                sort_key='id',
                sort_dir='asc'):
        """Retrieve a list of storage tiers."""

        return self._get_tiers_collection(uuid, marker, limit, sort_key,
                                          sort_dir)

    @wsme_pecan.wsexpose(StorageTierCollection, types.uuid, types.uuid, int,
                         wtypes.text, wtypes.text)
    def detail(self,
               tier_uuid=None,
               marker=None,
               limit=None,
               sort_key='id',
               sort_dir='asc'):
        """Retrieve a list of storage tiers with detail."""

        parent = pecan.request.path.split('/')[:-1][-1]
        if parent != 'storage_tiers':
            raise exception.HTTPNotFound

        expand = True
        resource_url = '/'.join(['storage_tiers', 'detail'])
        return self._get_tiers_collection(tier_uuid, marker, limit, sort_key,
                                          sort_dir, expand, resource_url)

    @wsme_pecan.wsexpose(StorageTier, types.uuid)
    def get_one(self, tier_uuid):
        """Retrieve information about the given storage tier."""

        if self._from_cluster:
            raise exception.OperationNotPermitted

        rpc_tier = objects.storage_tier.get_by_uuid(pecan.request.context,
                                                    tier_uuid)
        return StorageTier.convert_with_links(rpc_tier)

    @cutils.synchronized(LOCK_NAME)
    @wsme_pecan.wsexpose(StorageTier, body=StorageTier)
    def post(self, tier):
        """Create a new storage tier."""

        if self._from_cluster:
            raise exception.OperationNotPermitted

        try:
            tier = tier.as_dict()
            LOG.debug("storage tier post dict= %s" % tier)

            new_tier = _create(self, tier)
        except exception.SysinvException as e:
            LOG.exception(e)
            raise wsme.exc.ClientSideError(
                _("Invalid data: failed to create "
                  "a storage tier object"))

        return StorageTier.convert_with_links(new_tier)

    @cutils.synchronized(LOCK_NAME)
    @wsme.validate(types.uuid, [StorageTierPatchType])
    @wsme_pecan.wsexpose(StorageTier, types.uuid, body=[StorageTierPatchType])
    def patch(self, tier_uuid, patch):
        """Update an existing storage tier."""

        if self._from_cluster:
            raise exception.OperationNotPermitted

        LOG.debug("patch_data: %s" % patch)

        rpc_tier = objects.storage_tier.get_by_uuid(pecan.request.context,
                                                    tier_uuid)

        patch_obj = jsonpatch.JsonPatch(patch)
        backend = dict(name='*unknown*')
        for p in patch_obj:
            if p['path'] == '/backend_uuid':
                p['path'] = '/forbackendid'
                backend = objects.storage_backend.get_by_uuid(
                    pecan.request.context, p['value'])
                p['value'] = backend.id
            elif p['path'] == '/cluster_uuid':
                p['path'] = '/forclusterid'
                cluster = objects.cluster.get_by_uuid(pecan.request.context,
                                                      p['value'])
                p['value'] = cluster.id
        otier = copy.deepcopy(rpc_tier)

        # Validate provided patch data meets validity checks
        _pre_patch_checks(rpc_tier, patch_obj)

        try:
            tier = StorageTier(
                **jsonpatch.apply_patch(rpc_tier.as_dict(), patch_obj))
        except utils.JSONPATCH_EXCEPTIONS as e:
            raise exception.PatchError(patch=patch, reason=e)

        # Semantic Checks
        _check(self, "modify", tier.as_dict())
        try:
            # Update only the fields that have changed
            for field in objects.storage_tier.fields:
                if rpc_tier[field] != getattr(tier, field):
                    rpc_tier[field] = getattr(tier, field)

            # Obtain the fields that have changed.
            delta = rpc_tier.obj_what_changed()
            if len(delta) == 0:
                raise wsme.exc.ClientSideError(
                    _("No changes to the existing tier settings were detected."
                      ))

            allowed_attributes = ['name']
            for d in delta:
                if d not in allowed_attributes:
                    raise wsme.exc.ClientSideError(
                        _("Cannot modify '%s' with this operation." % d))

            LOG.info("SYS_I orig    storage_tier: %s " % otier.as_dict())
            LOG.info("SYS_I new     storage_tier: %s " % rpc_tier.as_dict())

            if 'name' in delta:
                default_tier_name = constants.SB_TIER_DEFAULT_NAMES[
                    constants.SB_TIER_TYPE_CEPH]
                if rpc_tier.name == default_tier_name:
                    raise wsme.exc.ClientSideError(
                        _("Cannot modify tier '%s'. Name '%s' is used "
                          "by the default tier" % (otier.name, rpc_tier.name)))
                self._ceph.crushmap_tier_rename(otier.name, rpc_tier.name)

            # Save and return
            rpc_tier.save()
            return StorageTier.convert_with_links(rpc_tier)
        except (exception.HTTPNotFound, exception.CephFailure) as e:
            msg = _(
                "Storage Tier update failed: backend %s storage tier %s : patch %s. "
                " Reason: %s") % (backend['name'], otier['name'], patch,
                                  str(e))
            raise wsme.exc.ClientSideError(msg)

    @cutils.synchronized(LOCK_NAME)
    @wsme_pecan.wsexpose(None, types.uuid, status_code=204)
    def delete(self, tier_uuid):
        """Delete a storage tier."""

        if self._from_cluster:
            raise exception.OperationNotPermitted

        _delete(self, tier_uuid)