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 ClusterController(rest.RestController): """REST controller for Clusters.""" storage_tiers = storage_tier_api.StorageTierController(from_cluster=True) "Expose storage tiers as a sub-element of clusters" def __init__(self, parent=None, **kwargs): self._parent = parent def _get_cluster_collection(self, parent_uuid, marker=None, limit=None, sort_key=None, sort_dir=None, expand=False, resource_url=None, q=None): limit = utils.validate_limit(limit) sort_dir = utils.validate_sort_dir(sort_dir) kwargs = {} if q is not None: for i in q: if i.op == 'eq': kwargs[i.field] = i.value marker_obj = None if marker: marker_obj = objects.cluster.get_by_uuid(pecan.request.context, marker) clusters = pecan.request.dbapi.clusters_get_list(limit=limit, marker=marker_obj, sort_key=sort_key, sort_dir=sort_dir) else: clusters = pecan.request.dbapi.clusters_get_all(**kwargs) return ClusterCollection.convert_with_links(clusters, limit, url=resource_url, expand=expand, sort_key=sort_key, sort_dir=sort_dir) def _query_cluster(self, cluster): try: result = pecan.request.dbapi.cluster_query(cluster) except exception.ClusterNotFoundByName: return None return result def _check_name_conflict(self, cluster): try: pool = pecan.request.dbapi.cluster_get(cluster['name']) raise exception.ClusterAlreadyExists(name=pool) except exception.ClusterNotFound: pass def _check_valid_peer(self, name, status): # TODO: check if name in valid hostnames return def _check_valid_peers(self, cluster): for name, status in cluster['peers']: self._check_valid_peer(name, status) def _check_allocated_peers(self, cluster_obj): peers = cluster_obj.peers if peers: hosts_unlocked = [] for peer in peers: hosts = peer.get('hosts') or [] for host in hosts: h = pecan.request.dbapi.ihost_get(host) if h.administrative == constants.ADMIN_UNLOCKED: hosts_unlocked.append(h.hostname) if hosts_unlocked: raise exception.ClusterInUseByPeers( hosts_unlocked=hosts_unlocked) def _set_defaults(self, cluster): cluster['uuid'] = str(uuid.uuid4()) if 'system_id' not in cluster: isystem = pecan.request.dbapi.isystem_get_one() cluster['system_id'] = isystem.id if 'type' not in cluster: cluster['type'] = constants.CINDER_BACKEND_CEPH def _validate_peer_updates(self, cluster, updates): peers = pecan.request.dbapi.peers_get_by_cluster(cluster.id) if not peers: return def _validate_updates(self, cluster, updates): if 'name' in updates: Cluster._validate_name(updates['name']) if 'peers' in updates: self._validate_peer_updates(cluster, updates) return def _create_cluster(self, cluster): cluster.validate_syntax() cluster_dict = cluster.as_dict() self._set_defaults(cluster_dict) LOG.info("Create cluster cluster_dict=%s" % cluster_dict) self._set_defaults(cluster_dict) # Check for semantic conflicts self._check_name_conflict(cluster_dict) self._check_valid_peers(cluster_dict) # Attempt to create the new cluster record return pecan.request.dbapi.cluster_create(cluster_dict) def _get_updates(self, patch): """Retrieve the updated attributes from the patch request.""" updates = {} for p in patch: attribute = p['path'] if p['path'][0] != '/' else p['path'][1:] updates[attribute] = p['value'] return updates def _get_one(self, cluster_uuid): rpc_cluster = objects.cluster.get_by_uuid(pecan.request.context, cluster_uuid) return Cluster.convert_with_links(rpc_cluster) @wsme_pecan.wsexpose(ClusterCollection, [Query], types.uuid, types.uuid, int, wtypes.text, wtypes.text) def get_all(self, q=None, parent_uuid=None, marker=None, limit=None, sort_key='id', sort_dir='asc'): """Retrieve a list of Clusters.""" if q is None: q = [] return self._get_cluster_collection(parent_uuid, marker, limit, sort_key, sort_dir, q=q) @wsme_pecan.wsexpose(Cluster, types.uuid) def get_one(self, cluster_uuid): return self._get_one(cluster_uuid) @cutils.synchronized(LOCK_NAME) @wsme_pecan.wsexpose(Cluster, body=Cluster) def post(self, cluster): """Create a new Cluster.""" if not os.path.exists(constants.SYSINV_RUNNING_IN_LAB): msg = _("Cluster cannot be created: %s") raise wsme.exc.ClientSideError(msg % cluster.as_dict()) return self._create_cluster(cluster) @cutils.synchronized(LOCK_NAME) @wsme.validate(types.uuid, [ClusterPatchType]) @wsme_pecan.wsexpose(Cluster, types.uuid, body=[ClusterPatchType]) def patch(self, cluster_uuid, patch): """Updates attributes of a Cluster.""" if not os.path.exists(constants.SYSINV_RUNNING_IN_LAB): msg = _("Cluster attributes cannot be modified: %s") raise wsme.exc.ClientSideError(msg % patch.path) cluster = self._get_one(cluster_uuid) updates = self._get_updates(patch) self._validate_updates(cluster, updates) return pecan.request.dbapi.cluster_update(cluster_uuid, updates) @cutils.synchronized(LOCK_NAME) @wsme_pecan.wsexpose(None, types.uuid, status_code=204) def delete(self, cluster_uuid): """Delete a Cluster.""" if not os.path.exists(constants.SYSINV_RUNNING_IN_LAB): msg = _("Cluster cannot be deleted: %s") raise wsme.exc.ClientSideError(msg % cluster_uuid) cluster = self._get_one(cluster_uuid) self._check_allocated_peers(cluster) pecan.request.dbapi.cluster_destroy(cluster_uuid)