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()
class LVGController(rest.RestController): """REST controller for ilvgs.""" ipvs = pv_api.PVController(from_ihosts=True, from_ilvg=True) "Expose ipvs as a sub-element of ilvgs" _custom_actions = { 'detail': ['GET'], } def __init__(self, from_ihosts=False): self._from_ihosts = from_ihosts def _get_lvgs_collection(self, ihost_uuid, marker, limit, sort_key, sort_dir, expand=False, resource_url=None): if self._from_ihosts and not ihost_uuid: raise exception.InvalidParameterValue(_("Host id not specified.")) limit = utils.validate_limit(limit) sort_dir = utils.validate_sort_dir(sort_dir) marker_obj = None if marker: marker_obj = objects.lvg.get_by_uuid(pecan.request.context, marker) if ihost_uuid: lvgs = pecan.request.dbapi.ilvg_get_by_ihost(ihost_uuid, limit, marker_obj, sort_key=sort_key, sort_dir=sort_dir) else: lvgs = pecan.request.dbapi.ilvg_get_list(limit, marker_obj, sort_key=sort_key, sort_dir=sort_dir) return LVGCollection.convert_with_links(lvgs, limit, url=resource_url, expand=expand, sort_key=sort_key, sort_dir=sort_dir) @wsme_pecan.wsexpose(LVGCollection, types.uuid, types.uuid, int, wtypes.text, wtypes.text) def get_all(self, ihost_uuid=None, marker=None, limit=None, sort_key='id', sort_dir='asc'): """Retrieve a list of lvgs.""" return self._get_lvgs_collection(ihost_uuid, marker, limit, sort_key, sort_dir) @wsme_pecan.wsexpose(LVGCollection, types.uuid, types.uuid, int, wtypes.text, wtypes.text) def detail(self, ihost_uuid=None, marker=None, limit=None, sort_key='id', sort_dir='asc'): """Retrieve a list of lvgs with detail.""" # NOTE: /detail should only work against collections parent = pecan.request.path.split('/')[:-1][-1] if parent != "ilvgs": raise exception.HTTPNotFound expand = True resource_url = '/'.join(['lvgs', 'detail']) return self._get_lvgs_collection(ihost_uuid, marker, limit, sort_key, sort_dir, expand, resource_url) @wsme_pecan.wsexpose(LVG, types.uuid) def get_one(self, lvg_uuid): """Retrieve information about the given lvg.""" if self._from_ihosts: raise exception.OperationNotPermitted rpc_lvg = objects.lvg.get_by_uuid(pecan.request.context, lvg_uuid) return LVG.convert_with_links(rpc_lvg) @cutils.synchronized(LOCK_NAME) @wsme_pecan.wsexpose(LVG, body=LVG) def post(self, lvg): """Create a new lvg.""" if self._from_ihosts: raise exception.OperationNotPermitted try: lvg = lvg.as_dict() LOG.debug("lvg post dict= %s" % lvg) new_lvg = _create(lvg) except exception.SysinvException as e: LOG.exception(e) raise wsme.exc.ClientSideError( _("Invalid data: failed to create a" " local volume group object")) return LVG.convert_with_links(new_lvg) @cutils.synchronized(LOCK_NAME) @wsme.validate(types.uuid, [LVGPatchType]) @wsme_pecan.wsexpose(LVG, types.uuid, body=[LVGPatchType]) def patch(self, lvg_uuid, patch): """Update an existing lvg.""" if self._from_ihosts: raise exception.OperationNotPermitted LOG.debug("patch_data: %s" % patch) rpc_lvg = objects.lvg.get_by_uuid(pecan.request.context, lvg_uuid) # replace ihost_uuid and ilvg_uuid with corresponding patch_obj = jsonpatch.JsonPatch(patch) for p in patch_obj: if p['path'] == '/ihost_uuid': p['path'] = '/forihostid' ihost = objects.host.get_by_uuid(pecan.request.context, p['value']) p['value'] = ihost.id elif p['path'] == '/capabilities': p['value'] = jsonutils.loads(p['value']) # perform checks based on the current vs.requested modifications _lvg_pre_patch_checks(rpc_lvg, patch_obj) try: lvg = LVG(**jsonpatch.apply_patch(rpc_lvg.as_dict(), patch_obj)) except utils.JSONPATCH_EXCEPTIONS as e: raise exception.PatchError(patch=patch, reason=e) # Semantic Checks _check("modify", lvg.as_dict()) try: # Update only the fields that have changed for field in objects.lvg.fields: if rpc_lvg[field] != getattr(lvg, field): rpc_lvg[field] = getattr(lvg, field) # Update mate controller LVG type for cinder-volumes if lvg.lvm_vg_name == constants.LVG_CINDER_VOLUMES: mate_lvg = _get_mate_ctrl_lvg(lvg.as_dict()) lvm_type = lvg.capabilities.get( constants.LVG_CINDER_PARAM_LVM_TYPE) if mate_lvg and lvm_type: mate_lvg_caps = mate_lvg['capabilities'] mate_type = mate_lvg_caps.get( constants.LVG_CINDER_PARAM_LVM_TYPE) if lvm_type != mate_type: mate_lvg_caps[ constants.LVG_CINDER_PARAM_LVM_TYPE] = lvm_type pecan.request.dbapi.ilvg_update( mate_lvg['uuid'], {'capabilities': mate_lvg_caps}) # Save rpc_lvg.save() return LVG.convert_with_links(rpc_lvg) except exception.HTTPNotFound: msg = _("LVG update failed: host %s vg %s : patch %s" % (ihost['hostname'], lvg.lvm_vg_name, patch)) raise wsme.exc.ClientSideError(msg) @cutils.synchronized(LOCK_NAME) @wsme_pecan.wsexpose(None, types.uuid, status_code=204) def delete(self, lvg_uuid): """Delete a lvg.""" if self._from_ihosts: raise exception.OperationNotPermitted lvg = objects.lvg.get_by_uuid(pecan.request.context, lvg_uuid).as_dict() _delete(lvg)