# AUTO-GENERATED file from IFMapApiGenerator. Do Not Edit! from bottle import abort, request, response import gevent import json import uuid from pprint import pformat import cfgm_common from cfgm_common.rest import LinkObject, hdr_server_tenant from cfgm_common.exceptions import * from resource_xsd import * from resource_common import * from resource_server import * import cStringIO from lxml import etree all_resource_types = set([ 'domain', 'global-vrouter-config', 'instance-ip', 'network-policy', 'loadbalancer-pool', 'virtual-DNS-record', 'route-target', 'floating-ip', 'floating-ip-pool', 'physical-router', 'bgp-router', 'virtual-router', 'config-root', 'subnet', 'global-system-config', 'service-appliance', 'service-instance', 'namespace', 'logical-interface', 'route-table', 'physical-interface', 'access-control-list', 'analytics-node', 'virtual-DNS', 'customer-attachment', 'service-appliance-set', 'config-node', 'qos-queue', 'virtual-machine', 'interface-route-table', 'service-template', 'virtual-ip', 'loadbalancer-member', 'security-group', 'provider-attachment', 'virtual-machine-interface', 'loadbalancer-healthmonitor', 'virtual-network', 'project', 'qos-forwarding-class', 'database-node', 'routing-instance', 'network-ipam', 'logical-router', ]) class VncApiServerGen(object): def __new__(cls, *args, **kwargs): obj = super(VncApiServerGen, cls).__new__(cls, *args, **kwargs) # leaf resource obj.route('/domain/', 'GET', obj.domain_http_get) obj.route('/domain/', 'PUT', obj.domain_http_put) obj.route('/domain/', 'DELETE', obj.domain_http_delete) # collections obj.route('/domains', 'POST', obj.domains_http_post) obj.route('/domains', 'GET', obj.domains_http_get) # leaf resource obj.route('/global-vrouter-config/', 'GET', obj.global_vrouter_config_http_get) obj.route('/global-vrouter-config/', 'PUT', obj.global_vrouter_config_http_put) obj.route('/global-vrouter-config/', 'DELETE', obj.global_vrouter_config_http_delete) # collections obj.route('/global-vrouter-configs', 'POST', obj.global_vrouter_configs_http_post) obj.route('/global-vrouter-configs', 'GET', obj.global_vrouter_configs_http_get) # leaf resource obj.route('/instance-ip/', 'GET', obj.instance_ip_http_get) obj.route('/instance-ip/', 'PUT', obj.instance_ip_http_put) obj.route('/instance-ip/', 'DELETE', obj.instance_ip_http_delete) # collections obj.route('/instance-ips', 'POST', obj.instance_ips_http_post) obj.route('/instance-ips', 'GET', obj.instance_ips_http_get) # leaf resource obj.route('/network-policy/', 'GET', obj.network_policy_http_get) obj.route('/network-policy/', 'PUT', obj.network_policy_http_put) obj.route('/network-policy/', 'DELETE', obj.network_policy_http_delete) # collections obj.route('/network-policys', 'POST', obj.network_policys_http_post) obj.route('/network-policys', 'GET', obj.network_policys_http_get) # leaf resource obj.route('/loadbalancer-pool/', 'GET', obj.loadbalancer_pool_http_get) obj.route('/loadbalancer-pool/', 'PUT', obj.loadbalancer_pool_http_put) obj.route('/loadbalancer-pool/', 'DELETE', obj.loadbalancer_pool_http_delete) # collections obj.route('/loadbalancer-pools', 'POST', obj.loadbalancer_pools_http_post) obj.route('/loadbalancer-pools', 'GET', obj.loadbalancer_pools_http_get) # leaf resource obj.route('/virtual-DNS-record/', 'GET', obj.virtual_DNS_record_http_get) obj.route('/virtual-DNS-record/', 'PUT', obj.virtual_DNS_record_http_put) obj.route('/virtual-DNS-record/', 'DELETE', obj.virtual_DNS_record_http_delete) # collections obj.route('/virtual-DNS-records', 'POST', obj.virtual_DNS_records_http_post) obj.route('/virtual-DNS-records', 'GET', obj.virtual_DNS_records_http_get) # leaf resource obj.route('/route-target/', 'GET', obj.route_target_http_get) obj.route('/route-target/', 'PUT', obj.route_target_http_put) obj.route('/route-target/', 'DELETE', obj.route_target_http_delete) # collections obj.route('/route-targets', 'POST', obj.route_targets_http_post) obj.route('/route-targets', 'GET', obj.route_targets_http_get) # leaf resource obj.route('/floating-ip/', 'GET', obj.floating_ip_http_get) obj.route('/floating-ip/', 'PUT', obj.floating_ip_http_put) obj.route('/floating-ip/', 'DELETE', obj.floating_ip_http_delete) # collections obj.route('/floating-ips', 'POST', obj.floating_ips_http_post) obj.route('/floating-ips', 'GET', obj.floating_ips_http_get) # leaf resource obj.route('/floating-ip-pool/', 'GET', obj.floating_ip_pool_http_get) obj.route('/floating-ip-pool/', 'PUT', obj.floating_ip_pool_http_put) obj.route('/floating-ip-pool/', 'DELETE', obj.floating_ip_pool_http_delete) # collections obj.route('/floating-ip-pools', 'POST', obj.floating_ip_pools_http_post) obj.route('/floating-ip-pools', 'GET', obj.floating_ip_pools_http_get) # leaf resource obj.route('/physical-router/', 'GET', obj.physical_router_http_get) obj.route('/physical-router/', 'PUT', obj.physical_router_http_put) obj.route('/physical-router/', 'DELETE', obj.physical_router_http_delete) # collections obj.route('/physical-routers', 'POST', obj.physical_routers_http_post) obj.route('/physical-routers', 'GET', obj.physical_routers_http_get) # leaf resource obj.route('/bgp-router/', 'GET', obj.bgp_router_http_get) obj.route('/bgp-router/', 'PUT', obj.bgp_router_http_put) obj.route('/bgp-router/', 'DELETE', obj.bgp_router_http_delete) # collections obj.route('/bgp-routers', 'POST', obj.bgp_routers_http_post) obj.route('/bgp-routers', 'GET', obj.bgp_routers_http_get) # leaf resource obj.route('/virtual-router/', 'GET', obj.virtual_router_http_get) obj.route('/virtual-router/', 'PUT', obj.virtual_router_http_put) obj.route('/virtual-router/', 'DELETE', obj.virtual_router_http_delete) # collections obj.route('/virtual-routers', 'POST', obj.virtual_routers_http_post) obj.route('/virtual-routers', 'GET', obj.virtual_routers_http_get) # leaf resource obj.route('/subnet/', 'GET', obj.subnet_http_get) obj.route('/subnet/', 'PUT', obj.subnet_http_put) obj.route('/subnet/', 'DELETE', obj.subnet_http_delete) # collections obj.route('/subnets', 'POST', obj.subnets_http_post) obj.route('/subnets', 'GET', obj.subnets_http_get) # leaf resource obj.route('/global-system-config/', 'GET', obj.global_system_config_http_get) obj.route('/global-system-config/', 'PUT', obj.global_system_config_http_put) obj.route('/global-system-config/', 'DELETE', obj.global_system_config_http_delete) # collections obj.route('/global-system-configs', 'POST', obj.global_system_configs_http_post) obj.route('/global-system-configs', 'GET', obj.global_system_configs_http_get) # leaf resource obj.route('/service-appliance/', 'GET', obj.service_appliance_http_get) obj.route('/service-appliance/', 'PUT', obj.service_appliance_http_put) obj.route('/service-appliance/', 'DELETE', obj.service_appliance_http_delete) # collections obj.route('/service-appliances', 'POST', obj.service_appliances_http_post) obj.route('/service-appliances', 'GET', obj.service_appliances_http_get) # leaf resource obj.route('/service-instance/', 'GET', obj.service_instance_http_get) obj.route('/service-instance/', 'PUT', obj.service_instance_http_put) obj.route('/service-instance/', 'DELETE', obj.service_instance_http_delete) # collections obj.route('/service-instances', 'POST', obj.service_instances_http_post) obj.route('/service-instances', 'GET', obj.service_instances_http_get) # leaf resource obj.route('/namespace/', 'GET', obj.namespace_http_get) obj.route('/namespace/', 'PUT', obj.namespace_http_put) obj.route('/namespace/', 'DELETE', obj.namespace_http_delete) # collections obj.route('/namespaces', 'POST', obj.namespaces_http_post) obj.route('/namespaces', 'GET', obj.namespaces_http_get) # leaf resource obj.route('/logical-interface/', 'GET', obj.logical_interface_http_get) obj.route('/logical-interface/', 'PUT', obj.logical_interface_http_put) obj.route('/logical-interface/', 'DELETE', obj.logical_interface_http_delete) # collections obj.route('/logical-interfaces', 'POST', obj.logical_interfaces_http_post) obj.route('/logical-interfaces', 'GET', obj.logical_interfaces_http_get) # leaf resource obj.route('/route-table/', 'GET', obj.route_table_http_get) obj.route('/route-table/', 'PUT', obj.route_table_http_put) obj.route('/route-table/', 'DELETE', obj.route_table_http_delete) # collections obj.route('/route-tables', 'POST', obj.route_tables_http_post) obj.route('/route-tables', 'GET', obj.route_tables_http_get) # leaf resource obj.route('/physical-interface/', 'GET', obj.physical_interface_http_get) obj.route('/physical-interface/', 'PUT', obj.physical_interface_http_put) obj.route('/physical-interface/', 'DELETE', obj.physical_interface_http_delete) # collections obj.route('/physical-interfaces', 'POST', obj.physical_interfaces_http_post) obj.route('/physical-interfaces', 'GET', obj.physical_interfaces_http_get) # leaf resource obj.route('/access-control-list/', 'GET', obj.access_control_list_http_get) obj.route('/access-control-list/', 'PUT', obj.access_control_list_http_put) obj.route('/access-control-list/', 'DELETE', obj.access_control_list_http_delete) # collections obj.route('/access-control-lists', 'POST', obj.access_control_lists_http_post) obj.route('/access-control-lists', 'GET', obj.access_control_lists_http_get) # leaf resource obj.route('/analytics-node/', 'GET', obj.analytics_node_http_get) obj.route('/analytics-node/', 'PUT', obj.analytics_node_http_put) obj.route('/analytics-node/', 'DELETE', obj.analytics_node_http_delete) # collections obj.route('/analytics-nodes', 'POST', obj.analytics_nodes_http_post) obj.route('/analytics-nodes', 'GET', obj.analytics_nodes_http_get) # leaf resource obj.route('/virtual-DNS/', 'GET', obj.virtual_DNS_http_get) obj.route('/virtual-DNS/', 'PUT', obj.virtual_DNS_http_put) obj.route('/virtual-DNS/', 'DELETE', obj.virtual_DNS_http_delete) # collections obj.route('/virtual-DNSs', 'POST', obj.virtual_DNSs_http_post) obj.route('/virtual-DNSs', 'GET', obj.virtual_DNSs_http_get) # leaf resource obj.route('/customer-attachment/', 'GET', obj.customer_attachment_http_get) obj.route('/customer-attachment/', 'PUT', obj.customer_attachment_http_put) obj.route('/customer-attachment/', 'DELETE', obj.customer_attachment_http_delete) # collections obj.route('/customer-attachments', 'POST', obj.customer_attachments_http_post) obj.route('/customer-attachments', 'GET', obj.customer_attachments_http_get) # leaf resource obj.route('/service-appliance-set/', 'GET', obj.service_appliance_set_http_get) obj.route('/service-appliance-set/', 'PUT', obj.service_appliance_set_http_put) obj.route('/service-appliance-set/', 'DELETE', obj.service_appliance_set_http_delete) # collections obj.route('/service-appliance-sets', 'POST', obj.service_appliance_sets_http_post) obj.route('/service-appliance-sets', 'GET', obj.service_appliance_sets_http_get) # leaf resource obj.route('/config-node/', 'GET', obj.config_node_http_get) obj.route('/config-node/', 'PUT', obj.config_node_http_put) obj.route('/config-node/', 'DELETE', obj.config_node_http_delete) # collections obj.route('/config-nodes', 'POST', obj.config_nodes_http_post) obj.route('/config-nodes', 'GET', obj.config_nodes_http_get) # leaf resource obj.route('/qos-queue/', 'GET', obj.qos_queue_http_get) obj.route('/qos-queue/', 'PUT', obj.qos_queue_http_put) obj.route('/qos-queue/', 'DELETE', obj.qos_queue_http_delete) # collections obj.route('/qos-queues', 'POST', obj.qos_queues_http_post) obj.route('/qos-queues', 'GET', obj.qos_queues_http_get) # leaf resource obj.route('/virtual-machine/', 'GET', obj.virtual_machine_http_get) obj.route('/virtual-machine/', 'PUT', obj.virtual_machine_http_put) obj.route('/virtual-machine/', 'DELETE', obj.virtual_machine_http_delete) # collections obj.route('/virtual-machines', 'POST', obj.virtual_machines_http_post) obj.route('/virtual-machines', 'GET', obj.virtual_machines_http_get) # leaf resource obj.route('/interface-route-table/', 'GET', obj.interface_route_table_http_get) obj.route('/interface-route-table/', 'PUT', obj.interface_route_table_http_put) obj.route('/interface-route-table/', 'DELETE', obj.interface_route_table_http_delete) # collections obj.route('/interface-route-tables', 'POST', obj.interface_route_tables_http_post) obj.route('/interface-route-tables', 'GET', obj.interface_route_tables_http_get) # leaf resource obj.route('/service-template/', 'GET', obj.service_template_http_get) obj.route('/service-template/', 'PUT', obj.service_template_http_put) obj.route('/service-template/', 'DELETE', obj.service_template_http_delete) # collections obj.route('/service-templates', 'POST', obj.service_templates_http_post) obj.route('/service-templates', 'GET', obj.service_templates_http_get) # leaf resource obj.route('/virtual-ip/', 'GET', obj.virtual_ip_http_get) obj.route('/virtual-ip/', 'PUT', obj.virtual_ip_http_put) obj.route('/virtual-ip/', 'DELETE', obj.virtual_ip_http_delete) # collections obj.route('/virtual-ips', 'POST', obj.virtual_ips_http_post) obj.route('/virtual-ips', 'GET', obj.virtual_ips_http_get) # leaf resource obj.route('/loadbalancer-member/', 'GET', obj.loadbalancer_member_http_get) obj.route('/loadbalancer-member/', 'PUT', obj.loadbalancer_member_http_put) obj.route('/loadbalancer-member/', 'DELETE', obj.loadbalancer_member_http_delete) # collections obj.route('/loadbalancer-members', 'POST', obj.loadbalancer_members_http_post) obj.route('/loadbalancer-members', 'GET', obj.loadbalancer_members_http_get) # leaf resource obj.route('/security-group/', 'GET', obj.security_group_http_get) obj.route('/security-group/', 'PUT', obj.security_group_http_put) obj.route('/security-group/', 'DELETE', obj.security_group_http_delete) # collections obj.route('/security-groups', 'POST', obj.security_groups_http_post) obj.route('/security-groups', 'GET', obj.security_groups_http_get) # leaf resource obj.route('/provider-attachment/', 'GET', obj.provider_attachment_http_get) obj.route('/provider-attachment/', 'PUT', obj.provider_attachment_http_put) obj.route('/provider-attachment/', 'DELETE', obj.provider_attachment_http_delete) # collections obj.route('/provider-attachments', 'POST', obj.provider_attachments_http_post) obj.route('/provider-attachments', 'GET', obj.provider_attachments_http_get) # leaf resource obj.route('/virtual-machine-interface/', 'GET', obj.virtual_machine_interface_http_get) obj.route('/virtual-machine-interface/', 'PUT', obj.virtual_machine_interface_http_put) obj.route('/virtual-machine-interface/', 'DELETE', obj.virtual_machine_interface_http_delete) # collections obj.route('/virtual-machine-interfaces', 'POST', obj.virtual_machine_interfaces_http_post) obj.route('/virtual-machine-interfaces', 'GET', obj.virtual_machine_interfaces_http_get) # leaf resource obj.route('/loadbalancer-healthmonitor/', 'GET', obj.loadbalancer_healthmonitor_http_get) obj.route('/loadbalancer-healthmonitor/', 'PUT', obj.loadbalancer_healthmonitor_http_put) obj.route('/loadbalancer-healthmonitor/', 'DELETE', obj.loadbalancer_healthmonitor_http_delete) # collections obj.route('/loadbalancer-healthmonitors', 'POST', obj.loadbalancer_healthmonitors_http_post) obj.route('/loadbalancer-healthmonitors', 'GET', obj.loadbalancer_healthmonitors_http_get) # leaf resource obj.route('/virtual-network/', 'GET', obj.virtual_network_http_get) obj.route('/virtual-network/', 'PUT', obj.virtual_network_http_put) obj.route('/virtual-network/', 'DELETE', obj.virtual_network_http_delete) # collections obj.route('/virtual-networks', 'POST', obj.virtual_networks_http_post) obj.route('/virtual-networks', 'GET', obj.virtual_networks_http_get) # leaf resource obj.route('/project/', 'GET', obj.project_http_get) obj.route('/project/', 'PUT', obj.project_http_put) obj.route('/project/', 'DELETE', obj.project_http_delete) # collections obj.route('/projects', 'POST', obj.projects_http_post) obj.route('/projects', 'GET', obj.projects_http_get) # leaf resource obj.route('/qos-forwarding-class/', 'GET', obj.qos_forwarding_class_http_get) obj.route('/qos-forwarding-class/', 'PUT', obj.qos_forwarding_class_http_put) obj.route('/qos-forwarding-class/', 'DELETE', obj.qos_forwarding_class_http_delete) # collections obj.route('/qos-forwarding-classs', 'POST', obj.qos_forwarding_classs_http_post) obj.route('/qos-forwarding-classs', 'GET', obj.qos_forwarding_classs_http_get) # leaf resource obj.route('/database-node/', 'GET', obj.database_node_http_get) obj.route('/database-node/', 'PUT', obj.database_node_http_put) obj.route('/database-node/', 'DELETE', obj.database_node_http_delete) # collections obj.route('/database-nodes', 'POST', obj.database_nodes_http_post) obj.route('/database-nodes', 'GET', obj.database_nodes_http_get) # leaf resource obj.route('/routing-instance/', 'GET', obj.routing_instance_http_get) obj.route('/routing-instance/', 'PUT', obj.routing_instance_http_put) obj.route('/routing-instance/', 'DELETE', obj.routing_instance_http_delete) # collections obj.route('/routing-instances', 'POST', obj.routing_instances_http_post) obj.route('/routing-instances', 'GET', obj.routing_instances_http_get) # leaf resource obj.route('/network-ipam/', 'GET', obj.network_ipam_http_get) obj.route('/network-ipam/', 'PUT', obj.network_ipam_http_put) obj.route('/network-ipam/', 'DELETE', obj.network_ipam_http_delete) # collections obj.route('/network-ipams', 'POST', obj.network_ipams_http_post) obj.route('/network-ipams', 'GET', obj.network_ipams_http_get) # leaf resource obj.route('/logical-router/', 'GET', obj.logical_router_http_get) obj.route('/logical-router/', 'PUT', obj.logical_router_http_put) obj.route('/logical-router/', 'DELETE', obj.logical_router_http_delete) # collections obj.route('/logical-routers', 'POST', obj.logical_routers_http_post) obj.route('/logical-routers', 'GET', obj.logical_routers_http_get) return obj #end __new__ def __init__(self): self._db_conn = None self._get_common = None self._post_common = None self._resource_classes = {} self._resource_classes['domain'] = DomainServerGen self._resource_classes['global-vrouter-config'] = GlobalVrouterConfigServerGen self._resource_classes['instance-ip'] = InstanceIpServerGen self._resource_classes['network-policy'] = NetworkPolicyServerGen self._resource_classes['loadbalancer-pool'] = LoadbalancerPoolServerGen self._resource_classes['virtual-DNS-record'] = VirtualDnsRecordServerGen self._resource_classes['route-target'] = RouteTargetServerGen self._resource_classes['floating-ip'] = FloatingIpServerGen self._resource_classes['floating-ip-pool'] = FloatingIpPoolServerGen self._resource_classes['physical-router'] = PhysicalRouterServerGen self._resource_classes['bgp-router'] = BgpRouterServerGen self._resource_classes['virtual-router'] = VirtualRouterServerGen self._resource_classes['config-root'] = ConfigRootServerGen self._resource_classes['subnet'] = SubnetServerGen self._resource_classes['global-system-config'] = GlobalSystemConfigServerGen self._resource_classes['service-appliance'] = ServiceApplianceServerGen self._resource_classes['service-instance'] = ServiceInstanceServerGen self._resource_classes['namespace'] = NamespaceServerGen self._resource_classes['logical-interface'] = LogicalInterfaceServerGen self._resource_classes['route-table'] = RouteTableServerGen self._resource_classes['physical-interface'] = PhysicalInterfaceServerGen self._resource_classes['access-control-list'] = AccessControlListServerGen self._resource_classes['analytics-node'] = AnalyticsNodeServerGen self._resource_classes['virtual-DNS'] = VirtualDnsServerGen self._resource_classes['customer-attachment'] = CustomerAttachmentServerGen self._resource_classes['service-appliance-set'] = ServiceApplianceSetServerGen self._resource_classes['config-node'] = ConfigNodeServerGen self._resource_classes['qos-queue'] = QosQueueServerGen self._resource_classes['virtual-machine'] = VirtualMachineServerGen self._resource_classes['interface-route-table'] = InterfaceRouteTableServerGen self._resource_classes['service-template'] = ServiceTemplateServerGen self._resource_classes['virtual-ip'] = VirtualIpServerGen self._resource_classes['loadbalancer-member'] = LoadbalancerMemberServerGen self._resource_classes['security-group'] = SecurityGroupServerGen self._resource_classes['provider-attachment'] = ProviderAttachmentServerGen self._resource_classes['virtual-machine-interface'] = VirtualMachineInterfaceServerGen self._resource_classes['loadbalancer-healthmonitor'] = LoadbalancerHealthmonitorServerGen self._resource_classes['virtual-network'] = VirtualNetworkServerGen self._resource_classes['project'] = ProjectServerGen self._resource_classes['qos-forwarding-class'] = QosForwardingClassServerGen self._resource_classes['database-node'] = DatabaseNodeServerGen self._resource_classes['routing-instance'] = RoutingInstanceServerGen self._resource_classes['network-ipam'] = NetworkIpamServerGen self._resource_classes['logical-router'] = LogicalRouterServerGen # Generate LinkObjects for all entities links = [] # Link for root links.append(LinkObject('root', self._base_url , '/config-root', 'config-root')) # Link for collections link = LinkObject('collection', self._base_url , '/domains', 'domain') links.append(link) link = LinkObject('collection', self._base_url , '/global-vrouter-configs', 'global-vrouter-config') links.append(link) link = LinkObject('collection', self._base_url , '/instance-ips', 'instance-ip') links.append(link) link = LinkObject('collection', self._base_url , '/network-policys', 'network-policy') links.append(link) link = LinkObject('collection', self._base_url , '/loadbalancer-pools', 'loadbalancer-pool') links.append(link) link = LinkObject('collection', self._base_url , '/virtual-DNS-records', 'virtual-DNS-record') links.append(link) link = LinkObject('collection', self._base_url , '/route-targets', 'route-target') links.append(link) link = LinkObject('collection', self._base_url , '/floating-ips', 'floating-ip') links.append(link) link = LinkObject('collection', self._base_url , '/floating-ip-pools', 'floating-ip-pool') links.append(link) link = LinkObject('collection', self._base_url , '/physical-routers', 'physical-router') links.append(link) link = LinkObject('collection', self._base_url , '/bgp-routers', 'bgp-router') links.append(link) link = LinkObject('collection', self._base_url , '/virtual-routers', 'virtual-router') links.append(link) link = LinkObject('collection', self._base_url , '/subnets', 'subnet') links.append(link) link = LinkObject('collection', self._base_url , '/global-system-configs', 'global-system-config') links.append(link) link = LinkObject('collection', self._base_url , '/service-appliances', 'service-appliance') links.append(link) link = LinkObject('collection', self._base_url , '/service-instances', 'service-instance') links.append(link) link = LinkObject('collection', self._base_url , '/namespaces', 'namespace') links.append(link) link = LinkObject('collection', self._base_url , '/logical-interfaces', 'logical-interface') links.append(link) link = LinkObject('collection', self._base_url , '/route-tables', 'route-table') links.append(link) link = LinkObject('collection', self._base_url , '/physical-interfaces', 'physical-interface') links.append(link) link = LinkObject('collection', self._base_url , '/access-control-lists', 'access-control-list') links.append(link) link = LinkObject('collection', self._base_url , '/analytics-nodes', 'analytics-node') links.append(link) link = LinkObject('collection', self._base_url , '/virtual-DNSs', 'virtual-DNS') links.append(link) link = LinkObject('collection', self._base_url , '/customer-attachments', 'customer-attachment') links.append(link) link = LinkObject('collection', self._base_url , '/service-appliance-sets', 'service-appliance-set') links.append(link) link = LinkObject('collection', self._base_url , '/config-nodes', 'config-node') links.append(link) link = LinkObject('collection', self._base_url , '/qos-queues', 'qos-queue') links.append(link) link = LinkObject('collection', self._base_url , '/virtual-machines', 'virtual-machine') links.append(link) link = LinkObject('collection', self._base_url , '/interface-route-tables', 'interface-route-table') links.append(link) link = LinkObject('collection', self._base_url , '/service-templates', 'service-template') links.append(link) link = LinkObject('collection', self._base_url , '/virtual-ips', 'virtual-ip') links.append(link) link = LinkObject('collection', self._base_url , '/loadbalancer-members', 'loadbalancer-member') links.append(link) link = LinkObject('collection', self._base_url , '/security-groups', 'security-group') links.append(link) link = LinkObject('collection', self._base_url , '/provider-attachments', 'provider-attachment') links.append(link) link = LinkObject('collection', self._base_url , '/virtual-machine-interfaces', 'virtual-machine-interface') links.append(link) link = LinkObject('collection', self._base_url , '/loadbalancer-healthmonitors', 'loadbalancer-healthmonitor') links.append(link) link = LinkObject('collection', self._base_url , '/virtual-networks', 'virtual-network') links.append(link) link = LinkObject('collection', self._base_url , '/projects', 'project') links.append(link) link = LinkObject('collection', self._base_url , '/qos-forwarding-classs', 'qos-forwarding-class') links.append(link) link = LinkObject('collection', self._base_url , '/database-nodes', 'database-node') links.append(link) link = LinkObject('collection', self._base_url , '/routing-instances', 'routing-instance') links.append(link) link = LinkObject('collection', self._base_url , '/network-ipams', 'network-ipam') links.append(link) link = LinkObject('collection', self._base_url , '/logical-routers', 'logical-router') links.append(link) # Link for Resources Base link = LinkObject('resource-base', self._base_url , '/domain', 'domain') links.append(link) link = LinkObject('resource-base', self._base_url , '/global-vrouter-config', 'global-vrouter-config') links.append(link) link = LinkObject('resource-base', self._base_url , '/instance-ip', 'instance-ip') links.append(link) link = LinkObject('resource-base', self._base_url , '/network-policy', 'network-policy') links.append(link) link = LinkObject('resource-base', self._base_url , '/loadbalancer-pool', 'loadbalancer-pool') links.append(link) link = LinkObject('resource-base', self._base_url , '/virtual-DNS-record', 'virtual-DNS-record') links.append(link) link = LinkObject('resource-base', self._base_url , '/route-target', 'route-target') links.append(link) link = LinkObject('resource-base', self._base_url , '/floating-ip', 'floating-ip') links.append(link) link = LinkObject('resource-base', self._base_url , '/floating-ip-pool', 'floating-ip-pool') links.append(link) link = LinkObject('resource-base', self._base_url , '/physical-router', 'physical-router') links.append(link) link = LinkObject('resource-base', self._base_url , '/bgp-router', 'bgp-router') links.append(link) link = LinkObject('resource-base', self._base_url , '/virtual-router', 'virtual-router') links.append(link) link = LinkObject('resource-base', self._base_url , '/config-root', 'config-root') links.append(link) link = LinkObject('resource-base', self._base_url , '/subnet', 'subnet') links.append(link) link = LinkObject('resource-base', self._base_url , '/global-system-config', 'global-system-config') links.append(link) link = LinkObject('resource-base', self._base_url , '/service-appliance', 'service-appliance') links.append(link) link = LinkObject('resource-base', self._base_url , '/service-instance', 'service-instance') links.append(link) link = LinkObject('resource-base', self._base_url , '/namespace', 'namespace') links.append(link) link = LinkObject('resource-base', self._base_url , '/logical-interface', 'logical-interface') links.append(link) link = LinkObject('resource-base', self._base_url , '/route-table', 'route-table') links.append(link) link = LinkObject('resource-base', self._base_url , '/physical-interface', 'physical-interface') links.append(link) link = LinkObject('resource-base', self._base_url , '/access-control-list', 'access-control-list') links.append(link) link = LinkObject('resource-base', self._base_url , '/analytics-node', 'analytics-node') links.append(link) link = LinkObject('resource-base', self._base_url , '/virtual-DNS', 'virtual-DNS') links.append(link) link = LinkObject('resource-base', self._base_url , '/customer-attachment', 'customer-attachment') links.append(link) link = LinkObject('resource-base', self._base_url , '/service-appliance-set', 'service-appliance-set') links.append(link) link = LinkObject('resource-base', self._base_url , '/config-node', 'config-node') links.append(link) link = LinkObject('resource-base', self._base_url , '/qos-queue', 'qos-queue') links.append(link) link = LinkObject('resource-base', self._base_url , '/virtual-machine', 'virtual-machine') links.append(link) link = LinkObject('resource-base', self._base_url , '/interface-route-table', 'interface-route-table') links.append(link) link = LinkObject('resource-base', self._base_url , '/service-template', 'service-template') links.append(link) link = LinkObject('resource-base', self._base_url , '/virtual-ip', 'virtual-ip') links.append(link) link = LinkObject('resource-base', self._base_url , '/loadbalancer-member', 'loadbalancer-member') links.append(link) link = LinkObject('resource-base', self._base_url , '/security-group', 'security-group') links.append(link) link = LinkObject('resource-base', self._base_url , '/provider-attachment', 'provider-attachment') links.append(link) link = LinkObject('resource-base', self._base_url , '/virtual-machine-interface', 'virtual-machine-interface') links.append(link) link = LinkObject('resource-base', self._base_url , '/loadbalancer-healthmonitor', 'loadbalancer-healthmonitor') links.append(link) link = LinkObject('resource-base', self._base_url , '/virtual-network', 'virtual-network') links.append(link) link = LinkObject('resource-base', self._base_url , '/project', 'project') links.append(link) link = LinkObject('resource-base', self._base_url , '/qos-forwarding-class', 'qos-forwarding-class') links.append(link) link = LinkObject('resource-base', self._base_url , '/database-node', 'database-node') links.append(link) link = LinkObject('resource-base', self._base_url , '/routing-instance', 'routing-instance') links.append(link) link = LinkObject('resource-base', self._base_url , '/network-ipam', 'network-ipam') links.append(link) link = LinkObject('resource-base', self._base_url , '/logical-router', 'logical-router') links.append(link) self._homepage_links = links #end __init__ def is_admin_request(self): env = request.headers.environ for field in ('HTTP_X_API_ROLE', 'HTTP_X_ROLE'): if field in env: roles = env[field].split(',') return 'admin' in [x.lower() for x in roles] return False def domain_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_domain_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'domain': abort(404, 'No domain object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'domain', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('domain') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'domain', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'domain_limits', u'api_access_list', u'id_perms', u'display_name'] references = [] back_references = [u'config_root_back_refs'] children = [u'projects', u'namespaces', 'service_templates', u'virtual_DNSs'] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('domain', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'domain', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'domain', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('domain', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_domain_read', id, rsp_body) except Exception as e: pass return {'domain': rsp_body} #end domain_http_get def domain_http_put(self, id): key = 'domain' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_domain_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'domain': abort(404, 'No domain object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('domain_limits') if prop_dict: buf = cStringIO.StringIO() xx_domain_limits = DomainLimitsType(**prop_dict) xx_domain_limits.export(buf) node = etree.fromstring(buf.getvalue()) xx_domain_limits = DomainLimitsType() try: xx_domain_limits.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('api_access_list') if prop_dict: buf = cStringIO.StringIO() xx_api_access_list = ApiAccessListType(**prop_dict) xx_api_access_list.export(buf) node = etree.fromstring(buf.getvalue()) xx_api_access_list = ApiAccessListType() try: xx_api_access_list.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'domain', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'domain', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = [u'project', u'namespace', 'service_template', u'virtual_DNS'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('domain') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'domain', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('domain', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'domain', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('domain', id) try: self._extension_mgrs['resourceApi'].map_method('post_domain_update', id, obj_dict) except Exception as e: pass return {'domain': rsp_body} #end domain_http_put def domain_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'domain': abort(404, 'No domain object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_domain_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'config_root_back_refs'] children = [u'projects', u'namespaces', 'service_templates', u'virtual_DNSs'] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('domain', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'domain', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'domain', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'domain', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('domain', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('domain') if r_class: if read_ok: # fail if non-default children or backrefs exist projects = read_result.get('projects', None) if projects: has_infos = read_result['projects'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-project')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'domain', 'http_delete', err_msg) abort(409, err_msg) namespaces = read_result.get('namespaces', None) if namespaces: has_infos = read_result['namespaces'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-namespace')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'domain', 'http_delete', err_msg) abort(409, err_msg) service_templates = read_result.get('service_templates', None) if service_templates: has_infos = read_result['service_templates'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-service-template')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'domain', 'http_delete', err_msg) abort(409, err_msg) virtual_DNSs = read_result.get('virtual_DNSs', None) if virtual_DNSs: has_infos = read_result['virtual_DNSs'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-virtual-DNS')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'domain', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._domain_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'domain', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('domain', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'domain', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_domain_delete', id, read_result) except Exception as e: pass #end domain_http_delete def domains_http_post(self): key = 'domain' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_domain_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('domain_limits') if prop_dict: buf = cStringIO.StringIO() xx_domain_limits = DomainLimitsType(**prop_dict) xx_domain_limits.export(buf) node = etree.fromstring(buf.getvalue()) xx_domain_limits = DomainLimitsType() try: xx_domain_limits.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('api_access_list') if prop_dict: buf = cStringIO.StringIO() xx_api_access_list = ApiAccessListType(**prop_dict) xx_api_access_list.export(buf) node = etree.fromstring(buf.getvalue()) xx_api_access_list = ApiAccessListType() try: xx_api_access_list.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'domain', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'domain', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'domain', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = [u'project', u'namespace', 'service_template', u'virtual_DNS'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('domain', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'domain', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['domain', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('domain') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'domain', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('domain', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'domain', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('domain', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_domain_create', obj_dict) except Exception as e: pass return {'domain': rsp_body} #end domains_http_post def domains_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'domains', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('domain', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'domains', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'domains': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('domain', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('domain', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('domain', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'domain_limits', u'api_access_list', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('domain', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('domain', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'domain': obj_dict}) return {'domains': obj_dicts} #end domains_http_get def _domain_create_default_children(self, parent_obj): # Create a default child only if provisioned for r_class = self.get_resource_class('project') if r_class and r_class.generate_default_instance: child_obj = Project(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('project') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('project', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('project', obj_ids, child_dict) self._project_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('namespace') if r_class and r_class.generate_default_instance: child_obj = Namespace(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('namespace') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('namespace', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('namespace', obj_ids, child_dict) self._namespace_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('service-template') if r_class and r_class.generate_default_instance: child_obj = ServiceTemplate(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('service-template') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('service-template', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('service-template', obj_ids, child_dict) self._service_template_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('virtual-DNS') if r_class and r_class.generate_default_instance: child_obj = VirtualDns(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('virtual-DNS') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('virtual-DNS', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('virtual-DNS', obj_ids, child_dict) self._virtual_DNS_create_default_children(child_obj) pass #end _domain_create_default_children def _domain_delete_default_children(self, parent_dict): # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-DNS') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('projects') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-project': default_child_id = has_info['href'].split('/')[-1] self.project_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-DNS') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('namespaces') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-namespace': default_child_id = has_info['href'].split('/')[-1] self.namespace_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-DNS') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('service_templates') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-service-template': default_child_id = has_info['href'].split('/')[-1] self.service_template_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-DNS') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('virtual_DNSs') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-virtual-DNS': default_child_id = has_info['href'].split('/')[-1] self.virtual_DNS_http_delete(default_child_id) break pass #end _domain_delete_default_children def global_vrouter_config_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_global_vrouter_config_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'global_vrouter_config': abort(404, 'No global-vrouter-config object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'global_vrouter_config', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('global-vrouter-config') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'global_vrouter_config', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'linklocal_services', u'encapsulation_priorities', u'vxlan_network_identifier_mode', u'id_perms', u'display_name'] references = [] back_references = [u'global_system_config_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('global-vrouter-config', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'global_vrouter_config', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'global_vrouter_config', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('global-vrouter-config', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_global_vrouter_config_read', id, rsp_body) except Exception as e: pass return {'global-vrouter-config': rsp_body} #end global_vrouter_config_http_get def global_vrouter_config_http_put(self, id): key = 'global-vrouter-config' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_global_vrouter_config_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'global_vrouter_config': abort(404, 'No global-vrouter-config object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('linklocal_services') if prop_dict: buf = cStringIO.StringIO() xx_linklocal_services = LinklocalServicesTypes(**prop_dict) xx_linklocal_services.export(buf) node = etree.fromstring(buf.getvalue()) xx_linklocal_services = LinklocalServicesTypes() try: xx_linklocal_services.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('encapsulation_priorities') if prop_dict: buf = cStringIO.StringIO() xx_encapsulation_priorities = EncapsulationPrioritiesType(**prop_dict) xx_encapsulation_priorities.export(buf) node = etree.fromstring(buf.getvalue()) xx_encapsulation_priorities = EncapsulationPrioritiesType() try: xx_encapsulation_priorities.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'global_vrouter_config', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'global_vrouter_config', 'http_put', msg) abort(code, msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('global-vrouter-config') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'global_vrouter_config', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('global-vrouter-config', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'global_vrouter_config', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('global-vrouter-config', id) try: self._extension_mgrs['resourceApi'].map_method('post_global_vrouter_config_update', id, obj_dict) except Exception as e: pass return {'global-vrouter-config': rsp_body} #end global_vrouter_config_http_put def global_vrouter_config_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'global_vrouter_config': abort(404, 'No global-vrouter-config object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_global_vrouter_config_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'global_system_config_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('global-vrouter-config', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'global_vrouter_config', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'global_vrouter_config', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'global_vrouter_config', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('global-vrouter-config', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('global-vrouter-config') if r_class: if read_ok: # fail if non-default children or backrefs exist # Delete default children first self._global_vrouter_config_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'global_vrouter_config', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('global-vrouter-config', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'global_vrouter_config', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_global_vrouter_config_delete', id, read_result) except Exception as e: pass #end global_vrouter_config_http_delete def global_vrouter_configs_http_post(self): key = 'global-vrouter-config' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_global_vrouter_config_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('linklocal_services') if prop_dict: buf = cStringIO.StringIO() xx_linklocal_services = LinklocalServicesTypes(**prop_dict) xx_linklocal_services.export(buf) node = etree.fromstring(buf.getvalue()) xx_linklocal_services = LinklocalServicesTypes() try: xx_linklocal_services.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('encapsulation_priorities') if prop_dict: buf = cStringIO.StringIO() xx_encapsulation_priorities = EncapsulationPrioritiesType(**prop_dict) xx_encapsulation_priorities.export(buf) node = etree.fromstring(buf.getvalue()) xx_encapsulation_priorities = EncapsulationPrioritiesType() try: xx_encapsulation_priorities.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'global-vrouter-config', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'global_vrouter_config', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'global_vrouter_config', 'http_post', err_msg) abort(400, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('global-vrouter-config', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'global_vrouter_config', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['global_vrouter_config', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('global-vrouter-config') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'global_vrouter_config', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('global-vrouter-config', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'global_vrouter_config', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('global-vrouter-config', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_global_vrouter_config_create', obj_dict) except Exception as e: pass return {'global-vrouter-config': rsp_body} #end global_vrouter_configs_http_post def global_vrouter_configs_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'global_vrouter_configs', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('global-vrouter-config', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'global_vrouter_configs', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'global-vrouter-configs': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('global-vrouter-config', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('global-vrouter-config', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('global-vrouter-config', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'linklocal_services', u'encapsulation_priorities', u'vxlan_network_identifier_mode', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('global-vrouter-config', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('global-vrouter-config', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'global-vrouter-config': obj_dict}) return {'global-vrouter-configs': obj_dicts} #end global_vrouter_configs_http_get def _global_vrouter_config_create_default_children(self, parent_obj): pass #end _global_vrouter_config_create_default_children def _global_vrouter_config_delete_default_children(self, parent_dict): pass #end _global_vrouter_config_delete_default_children def instance_ip_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_instance_ip_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'instance_ip': abort(404, 'No instance-ip object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'instance_ip', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('instance-ip') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'instance_ip', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'instance_ip_address', u'instance_ip_family', u'instance_ip_mode', u'subnet_uuid', u'id_perms', u'display_name'] references = [u'virtual_network_refs', 'virtual_machine_interface_refs'] back_references = [] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('instance-ip', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'instance_ip', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'instance_ip', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('instance-ip', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_instance_ip_read', id, rsp_body) except Exception as e: pass return {'instance-ip': rsp_body} #end instance_ip_http_get def instance_ip_http_put(self, id): key = 'instance-ip' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_instance_ip_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'instance_ip': abort(404, 'No instance-ip object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'instance_ip', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'instance_ip', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = [u'virtual_network', 'virtual_machine_interface'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('instance-ip') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'instance_ip', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('instance-ip', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'instance_ip', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('instance-ip', id) try: self._extension_mgrs['resourceApi'].map_method('post_instance_ip_update', id, obj_dict) except Exception as e: pass return {'instance-ip': rsp_body} #end instance_ip_http_put def instance_ip_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'instance_ip': abort(404, 'No instance-ip object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_instance_ip_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('instance-ip', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'instance_ip', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'instance_ip', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'instance_ip', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('instance-ip', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('instance-ip') if r_class: if read_ok: # fail if non-default children or backrefs exist # Delete default children first self._instance_ip_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'instance_ip', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('instance-ip', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'instance_ip', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_instance_ip_delete', id, read_result) except Exception as e: pass #end instance_ip_http_delete def instance_ips_http_post(self): key = 'instance-ip' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_instance_ip_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'instance-ip', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'instance_ip', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # Validate perms objtype_list = [u'virtual_network', 'virtual_machine_interface'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('instance-ip', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'instance_ip', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['instance_ip', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('instance-ip') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'instance_ip', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('instance-ip', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'instance_ip', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('instance-ip', obj_ids['uuid']) try: self._extension_mgrs['resourceApi'].map_method('post_instance_ip_create', obj_dict) except Exception as e: pass return {'instance-ip': rsp_body} #end instance_ips_http_post def instance_ips_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'instance_ips', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('instance-ip', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'instance_ips', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'instance-ips': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('instance-ip', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('instance-ip', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('instance-ip', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'instance_ip_address', u'instance_ip_family', u'instance_ip_mode', u'subnet_uuid', u'id_perms', u'display_name'] + [u'virtual_network_refs', 'virtual_machine_interface_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('instance-ip', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('instance-ip', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'instance-ip': obj_dict}) return {'instance-ips': obj_dicts} #end instance_ips_http_get def _instance_ip_create_default_children(self, parent_obj): pass #end _instance_ip_create_default_children def _instance_ip_delete_default_children(self, parent_dict): pass #end _instance_ip_delete_default_children def network_policy_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_network_policy_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'network_policy': abort(404, 'No network-policy object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'network_policy', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('network-policy') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'network_policy', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'network_policy_entries', u'id_perms', u'display_name'] references = [] back_references = [u'project_back_refs', u'virtual_network_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('network-policy', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'network_policy', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'network_policy', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('network-policy', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_network_policy_read', id, rsp_body) except Exception as e: pass return {'network-policy': rsp_body} #end network_policy_http_get def network_policy_http_put(self, id): key = 'network-policy' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_network_policy_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'network_policy': abort(404, 'No network-policy object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('network_policy_entries') if prop_dict: buf = cStringIO.StringIO() xx_network_policy_entries = PolicyEntriesType(**prop_dict) xx_network_policy_entries.export(buf) node = etree.fromstring(buf.getvalue()) xx_network_policy_entries = PolicyEntriesType() try: xx_network_policy_entries.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'network_policy', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'network_policy', 'http_put', msg) abort(code, msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('network-policy') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'network_policy', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('network-policy', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'network_policy', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('network-policy', id) try: self._extension_mgrs['resourceApi'].map_method('post_network_policy_update', id, obj_dict) except Exception as e: pass return {'network-policy': rsp_body} #end network_policy_http_put def network_policy_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'network_policy': abort(404, 'No network-policy object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_network_policy_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'project_back_refs', u'virtual_network_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('network-policy', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'network_policy', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'network_policy', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'network_policy', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('network-policy', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('network-policy') if r_class: if read_ok: # fail if non-default children or backrefs exist virtual_network_back_refs = read_result.get('virtual_network_back_refs', None) if virtual_network_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['virtual_network_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'network_policy', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._network_policy_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'network_policy', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('network-policy', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'network_policy', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_network_policy_delete', id, read_result) except Exception as e: pass #end network_policy_http_delete def network_policys_http_post(self): key = 'network-policy' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_network_policy_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('network_policy_entries') if prop_dict: buf = cStringIO.StringIO() xx_network_policy_entries = PolicyEntriesType(**prop_dict) xx_network_policy_entries.export(buf) node = etree.fromstring(buf.getvalue()) xx_network_policy_entries = PolicyEntriesType() try: xx_network_policy_entries.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'network-policy', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'network_policy', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'network_policy', 'http_post', err_msg) abort(400, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('network-policy', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'network_policy', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['network_policy', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('network-policy') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'network_policy', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('network-policy', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'network_policy', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('network-policy', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_network_policy_create', obj_dict) except Exception as e: pass return {'network-policy': rsp_body} #end network_policys_http_post def network_policys_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'network_policys', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('network-policy', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'network_policys', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'network-policys': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('network-policy', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('network-policy', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('network-policy', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'network_policy_entries', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('network-policy', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('network-policy', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'network-policy': obj_dict}) return {'network-policys': obj_dicts} #end network_policys_http_get def _network_policy_create_default_children(self, parent_obj): pass #end _network_policy_create_default_children def _network_policy_delete_default_children(self, parent_dict): pass #end _network_policy_delete_default_children def loadbalancer_pool_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_loadbalancer_pool_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'loadbalancer_pool': abort(404, 'No loadbalancer-pool object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'loadbalancer_pool', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('loadbalancer-pool') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'loadbalancer_pool', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'loadbalancer_pool_properties', u'loadbalancer_pool_provider', u'id_perms', u'display_name'] references = [u'service_instance_refs', 'virtual_machine_interface_refs', u'service_appliance_set_refs', u'loadbalancer_healthmonitor_refs'] back_references = [u'project_back_refs', u'virtual_ip_back_refs'] children = [u'loadbalancer_members'] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('loadbalancer-pool', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'loadbalancer_pool', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'loadbalancer_pool', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('loadbalancer-pool', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_loadbalancer_pool_read', id, rsp_body) except Exception as e: pass return {'loadbalancer-pool': rsp_body} #end loadbalancer_pool_http_get def loadbalancer_pool_http_put(self, id): key = 'loadbalancer-pool' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_loadbalancer_pool_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'loadbalancer_pool': abort(404, 'No loadbalancer-pool object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('loadbalancer_pool_properties') if prop_dict: buf = cStringIO.StringIO() xx_loadbalancer_pool_properties = LoadbalancerPoolType(**prop_dict) xx_loadbalancer_pool_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_loadbalancer_pool_properties = LoadbalancerPoolType() try: xx_loadbalancer_pool_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'loadbalancer_pool', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'loadbalancer_pool', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = [u'service_instance', 'virtual_machine_interface', u'service_appliance_set', u'loadbalancer_member', u'loadbalancer_healthmonitor'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('loadbalancer-pool') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'loadbalancer_pool', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('loadbalancer-pool', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'loadbalancer_pool', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('loadbalancer-pool', id) try: self._extension_mgrs['resourceApi'].map_method('post_loadbalancer_pool_update', id, obj_dict) except Exception as e: pass return {'loadbalancer-pool': rsp_body} #end loadbalancer_pool_http_put def loadbalancer_pool_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'loadbalancer_pool': abort(404, 'No loadbalancer-pool object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_loadbalancer_pool_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'project_back_refs', u'virtual_ip_back_refs'] children = [u'loadbalancer_members'] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('loadbalancer-pool', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'loadbalancer_pool', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'loadbalancer_pool', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'loadbalancer_pool', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('loadbalancer-pool', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('loadbalancer-pool') if r_class: if read_ok: # fail if non-default children or backrefs exist loadbalancer_members = read_result.get('loadbalancer_members', None) if loadbalancer_members: has_infos = read_result['loadbalancer_members'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-loadbalancer-member')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'loadbalancer_pool', 'http_delete', err_msg) abort(409, err_msg) virtual_ip_back_refs = read_result.get('virtual_ip_back_refs', None) if virtual_ip_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['virtual_ip_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'loadbalancer_pool', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._loadbalancer_pool_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'loadbalancer_pool', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('loadbalancer-pool', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'loadbalancer_pool', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_loadbalancer_pool_delete', id, read_result) except Exception as e: pass #end loadbalancer_pool_http_delete def loadbalancer_pools_http_post(self): key = 'loadbalancer-pool' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_loadbalancer_pool_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('loadbalancer_pool_properties') if prop_dict: buf = cStringIO.StringIO() xx_loadbalancer_pool_properties = LoadbalancerPoolType(**prop_dict) xx_loadbalancer_pool_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_loadbalancer_pool_properties = LoadbalancerPoolType() try: xx_loadbalancer_pool_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'loadbalancer-pool', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'loadbalancer_pool', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'loadbalancer_pool', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = [u'service_instance', 'virtual_machine_interface', u'service_appliance_set', u'loadbalancer_member', u'loadbalancer_healthmonitor'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('loadbalancer-pool', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'loadbalancer_pool', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['loadbalancer_pool', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('loadbalancer-pool') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'loadbalancer_pool', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('loadbalancer-pool', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'loadbalancer_pool', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('loadbalancer-pool', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_loadbalancer_pool_create', obj_dict) except Exception as e: pass return {'loadbalancer-pool': rsp_body} #end loadbalancer_pools_http_post def loadbalancer_pools_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'loadbalancer_pools', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('loadbalancer-pool', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'loadbalancer_pools', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'loadbalancer-pools': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('loadbalancer-pool', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('loadbalancer-pool', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('loadbalancer-pool', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'loadbalancer_pool_properties', u'loadbalancer_pool_provider', u'id_perms', u'display_name'] + [u'service_instance_refs', 'virtual_machine_interface_refs', u'service_appliance_set_refs', u'loadbalancer_healthmonitor_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('loadbalancer-pool', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('loadbalancer-pool', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'loadbalancer-pool': obj_dict}) return {'loadbalancer-pools': obj_dicts} #end loadbalancer_pools_http_get def _loadbalancer_pool_create_default_children(self, parent_obj): # Create a default child only if provisioned for r_class = self.get_resource_class('loadbalancer-member') if r_class and r_class.generate_default_instance: child_obj = LoadbalancerMember(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('loadbalancer-member') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('loadbalancer-member', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('loadbalancer-member', obj_ids, child_dict) self._loadbalancer_member_create_default_children(child_obj) pass #end _loadbalancer_pool_create_default_children def _loadbalancer_pool_delete_default_children(self, parent_dict): # Delete a default child only if provisioned for r_class = self.get_resource_class('loadbalancer-member') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('loadbalancer_members') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-loadbalancer-member': default_child_id = has_info['href'].split('/')[-1] self.loadbalancer_member_http_delete(default_child_id) break pass #end _loadbalancer_pool_delete_default_children def virtual_DNS_record_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_DNS_record_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'virtual_DNS_record': abort(404, 'No virtual-DNS-record object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'virtual_DNS_record', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('virtual-DNS-record') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'virtual_DNS_record', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'virtual_DNS_record_data', u'id_perms', u'display_name'] references = [] back_references = [u'virtual_DNS_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('virtual-DNS-record', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'virtual_DNS_record', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'virtual_DNS_record', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('virtual-DNS-record', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_virtual_DNS_record_read', id, rsp_body) except Exception as e: pass return {'virtual-DNS-record': rsp_body} #end virtual_DNS_record_http_get def virtual_DNS_record_http_put(self, id): key = 'virtual-DNS-record' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_DNS_record_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'virtual_DNS_record': abort(404, 'No virtual-DNS-record object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('virtual_DNS_record_data') if prop_dict: buf = cStringIO.StringIO() xx_virtual_DNS_record_data = VirtualDnsRecordType(**prop_dict) xx_virtual_DNS_record_data.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_DNS_record_data = VirtualDnsRecordType() try: xx_virtual_DNS_record_data.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'virtual_DNS_record', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'virtual_DNS_record', 'http_put', msg) abort(code, msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('virtual-DNS-record') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'virtual_DNS_record', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('virtual-DNS-record', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'virtual_DNS_record', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('virtual-DNS-record', id) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_DNS_record_update', id, obj_dict) except Exception as e: pass return {'virtual-DNS-record': rsp_body} #end virtual_DNS_record_http_put def virtual_DNS_record_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'virtual_DNS_record': abort(404, 'No virtual-DNS-record object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_DNS_record_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'virtual_DNS_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('virtual-DNS-record', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'virtual_DNS_record', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'virtual_DNS_record', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'virtual_DNS_record', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('virtual-DNS-record', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('virtual-DNS-record') if r_class: if read_ok: # fail if non-default children or backrefs exist # Delete default children first self._virtual_DNS_record_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'virtual_DNS_record', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('virtual-DNS-record', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'virtual_DNS_record', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_DNS_record_delete', id, read_result) except Exception as e: pass #end virtual_DNS_record_http_delete def virtual_DNS_records_http_post(self): key = 'virtual-DNS-record' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_DNS_record_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('virtual_DNS_record_data') if prop_dict: buf = cStringIO.StringIO() xx_virtual_DNS_record_data = VirtualDnsRecordType(**prop_dict) xx_virtual_DNS_record_data.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_DNS_record_data = VirtualDnsRecordType() try: xx_virtual_DNS_record_data.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'virtual-DNS-record', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'virtual_DNS_record', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'virtual_DNS_record', 'http_post', err_msg) abort(400, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('virtual-DNS-record', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'virtual_DNS_record', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['virtual_DNS_record', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('virtual-DNS-record') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'virtual_DNS_record', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('virtual-DNS-record', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'virtual_DNS_record', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('virtual-DNS-record', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_DNS_record_create', obj_dict) except Exception as e: pass return {'virtual-DNS-record': rsp_body} #end virtual_DNS_records_http_post def virtual_DNS_records_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'virtual_DNS_records', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('virtual-DNS-record', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'virtual_DNS_records', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'virtual-DNS-records': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('virtual-DNS-record', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('virtual-DNS-record', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('virtual-DNS-record', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'virtual_DNS_record_data', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('virtual-DNS-record', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('virtual-DNS-record', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'virtual-DNS-record': obj_dict}) return {'virtual-DNS-records': obj_dicts} #end virtual_DNS_records_http_get def _virtual_DNS_record_create_default_children(self, parent_obj): pass #end _virtual_DNS_record_create_default_children def _virtual_DNS_record_delete_default_children(self, parent_dict): pass #end _virtual_DNS_record_delete_default_children def route_target_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_route_target_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'route_target': abort(404, 'No route-target object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'route_target', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('route-target') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'route_target', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'id_perms', u'display_name'] references = [] back_references = [u'logical_router_back_refs', 'routing_instance_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('route-target', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'route_target', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'route_target', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('route-target', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_route_target_read', id, rsp_body) except Exception as e: pass return {'route-target': rsp_body} #end route_target_http_get def route_target_http_put(self, id): key = 'route-target' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_route_target_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'route_target': abort(404, 'No route-target object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'route_target', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'route_target', 'http_put', msg) abort(code, msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('route-target') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'route_target', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('route-target', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'route_target', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('route-target', id) try: self._extension_mgrs['resourceApi'].map_method('post_route_target_update', id, obj_dict) except Exception as e: pass return {'route-target': rsp_body} #end route_target_http_put def route_target_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'route_target': abort(404, 'No route-target object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_route_target_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'logical_router_back_refs', 'routing_instance_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('route-target', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'route_target', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'route_target', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'route_target', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('route-target', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('route-target') if r_class: if read_ok: # fail if non-default children or backrefs exist logical_router_back_refs = read_result.get('logical_router_back_refs', None) if logical_router_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['logical_router_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'route_target', 'http_delete', err_msg) abort(409, err_msg) routing_instance_back_refs = read_result.get('routing_instance_back_refs', None) if routing_instance_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['routing_instance_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'route_target', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._route_target_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'route_target', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('route-target', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'route_target', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_route_target_delete', id, read_result) except Exception as e: pass #end route_target_http_delete def route_targets_http_post(self): key = 'route-target' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_route_target_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'route-target', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'route_target', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('route-target', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'route_target', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['route_target', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('route-target') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'route_target', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('route-target', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'route_target', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('route-target', obj_ids['uuid']) try: self._extension_mgrs['resourceApi'].map_method('post_route_target_create', obj_dict) except Exception as e: pass return {'route-target': rsp_body} #end route_targets_http_post def route_targets_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'route_targets', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('route-target', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'route_targets', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'route-targets': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('route-target', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('route-target', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('route-target', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('route-target', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('route-target', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'route-target': obj_dict}) return {'route-targets': obj_dicts} #end route_targets_http_get def _route_target_create_default_children(self, parent_obj): pass #end _route_target_create_default_children def _route_target_delete_default_children(self, parent_dict): pass #end _route_target_delete_default_children def floating_ip_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_floating_ip_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'floating_ip': abort(404, 'No floating-ip object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'floating_ip', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('floating-ip') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'floating_ip', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'floating_ip_address', u'floating_ip_is_virtual_ip', u'floating_ip_fixed_ip_address', u'floating_ip_address_family', u'id_perms', u'display_name'] references = [u'project_refs', 'virtual_machine_interface_refs'] back_references = [u'floating_ip_pool_back_refs', 'customer_attachment_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('floating-ip', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'floating_ip', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'floating_ip', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('floating-ip', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_floating_ip_read', id, rsp_body) except Exception as e: pass return {'floating-ip': rsp_body} #end floating_ip_http_get def floating_ip_http_put(self, id): key = 'floating-ip' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_floating_ip_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'floating_ip': abort(404, 'No floating-ip object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'floating_ip', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'floating_ip', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = [u'project', 'virtual_machine_interface'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('floating-ip') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'floating_ip', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('floating-ip', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'floating_ip', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('floating-ip', id) try: self._extension_mgrs['resourceApi'].map_method('post_floating_ip_update', id, obj_dict) except Exception as e: pass return {'floating-ip': rsp_body} #end floating_ip_http_put def floating_ip_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'floating_ip': abort(404, 'No floating-ip object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_floating_ip_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'floating_ip_pool_back_refs', 'customer_attachment_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('floating-ip', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'floating_ip', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'floating_ip', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'floating_ip', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('floating-ip', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('floating-ip') if r_class: if read_ok: # fail if non-default children or backrefs exist customer_attachment_back_refs = read_result.get('customer_attachment_back_refs', None) if customer_attachment_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['customer_attachment_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'floating_ip', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._floating_ip_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'floating_ip', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('floating-ip', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'floating_ip', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_floating_ip_delete', id, read_result) except Exception as e: pass #end floating_ip_http_delete def floating_ips_http_post(self): key = 'floating-ip' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_floating_ip_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'floating-ip', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'floating_ip', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'floating_ip', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = [u'project', 'virtual_machine_interface'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('floating-ip', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'floating_ip', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['floating_ip', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('floating-ip') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'floating_ip', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('floating-ip', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'floating_ip', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('floating-ip', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_floating_ip_create', obj_dict) except Exception as e: pass return {'floating-ip': rsp_body} #end floating_ips_http_post def floating_ips_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'floating_ips', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('floating-ip', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'floating_ips', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'floating-ips': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('floating-ip', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('floating-ip', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('floating-ip', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'floating_ip_address', u'floating_ip_is_virtual_ip', u'floating_ip_fixed_ip_address', u'floating_ip_address_family', u'id_perms', u'display_name'] + [u'project_refs', 'virtual_machine_interface_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('floating-ip', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('floating-ip', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'floating-ip': obj_dict}) return {'floating-ips': obj_dicts} #end floating_ips_http_get def _floating_ip_create_default_children(self, parent_obj): pass #end _floating_ip_create_default_children def _floating_ip_delete_default_children(self, parent_dict): pass #end _floating_ip_delete_default_children def floating_ip_pool_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_floating_ip_pool_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'floating_ip_pool': abort(404, 'No floating-ip-pool object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'floating_ip_pool', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('floating-ip-pool') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'floating_ip_pool', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'floating_ip_pool_prefixes', u'id_perms', u'display_name'] references = [] back_references = [u'virtual_network_back_refs', u'project_back_refs'] children = [u'floating_ips'] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('floating-ip-pool', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'floating_ip_pool', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'floating_ip_pool', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('floating-ip-pool', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_floating_ip_pool_read', id, rsp_body) except Exception as e: pass return {'floating-ip-pool': rsp_body} #end floating_ip_pool_http_get def floating_ip_pool_http_put(self, id): key = 'floating-ip-pool' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_floating_ip_pool_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'floating_ip_pool': abort(404, 'No floating-ip-pool object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('floating_ip_pool_prefixes') if prop_dict: buf = cStringIO.StringIO() xx_floating_ip_pool_prefixes = FloatingIpPoolType(**prop_dict) xx_floating_ip_pool_prefixes.export(buf) node = etree.fromstring(buf.getvalue()) xx_floating_ip_pool_prefixes = FloatingIpPoolType() try: xx_floating_ip_pool_prefixes.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'floating_ip_pool', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'floating_ip_pool', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = [u'floating_ip'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('floating-ip-pool') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'floating_ip_pool', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('floating-ip-pool', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'floating_ip_pool', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('floating-ip-pool', id) try: self._extension_mgrs['resourceApi'].map_method('post_floating_ip_pool_update', id, obj_dict) except Exception as e: pass return {'floating-ip-pool': rsp_body} #end floating_ip_pool_http_put def floating_ip_pool_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'floating_ip_pool': abort(404, 'No floating-ip-pool object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_floating_ip_pool_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'virtual_network_back_refs', u'project_back_refs'] children = [u'floating_ips'] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('floating-ip-pool', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'floating_ip_pool', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'floating_ip_pool', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'floating_ip_pool', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('floating-ip-pool', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('floating-ip-pool') if r_class: if read_ok: # fail if non-default children or backrefs exist floating_ips = read_result.get('floating_ips', None) if floating_ips: has_infos = read_result['floating_ips'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-floating-ip')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'floating_ip_pool', 'http_delete', err_msg) abort(409, err_msg) project_back_refs = read_result.get('project_back_refs', None) if project_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['project_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'floating_ip_pool', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._floating_ip_pool_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'floating_ip_pool', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('floating-ip-pool', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'floating_ip_pool', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_floating_ip_pool_delete', id, read_result) except Exception as e: pass #end floating_ip_pool_http_delete def floating_ip_pools_http_post(self): key = 'floating-ip-pool' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_floating_ip_pool_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('floating_ip_pool_prefixes') if prop_dict: buf = cStringIO.StringIO() xx_floating_ip_pool_prefixes = FloatingIpPoolType(**prop_dict) xx_floating_ip_pool_prefixes.export(buf) node = etree.fromstring(buf.getvalue()) xx_floating_ip_pool_prefixes = FloatingIpPoolType() try: xx_floating_ip_pool_prefixes.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'floating-ip-pool', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'floating_ip_pool', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'floating_ip_pool', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = [u'floating_ip'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('floating-ip-pool', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'floating_ip_pool', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['floating_ip_pool', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('floating-ip-pool') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'floating_ip_pool', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('floating-ip-pool', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'floating_ip_pool', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('floating-ip-pool', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_floating_ip_pool_create', obj_dict) except Exception as e: pass return {'floating-ip-pool': rsp_body} #end floating_ip_pools_http_post def floating_ip_pools_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'floating_ip_pools', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('floating-ip-pool', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'floating_ip_pools', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'floating-ip-pools': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('floating-ip-pool', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('floating-ip-pool', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('floating-ip-pool', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'floating_ip_pool_prefixes', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('floating-ip-pool', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('floating-ip-pool', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'floating-ip-pool': obj_dict}) return {'floating-ip-pools': obj_dicts} #end floating_ip_pools_http_get def _floating_ip_pool_create_default_children(self, parent_obj): # Create a default child only if provisioned for r_class = self.get_resource_class('floating-ip') if r_class and r_class.generate_default_instance: child_obj = FloatingIp(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('floating-ip') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('floating-ip', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('floating-ip', obj_ids, child_dict) self._floating_ip_create_default_children(child_obj) pass #end _floating_ip_pool_create_default_children def _floating_ip_pool_delete_default_children(self, parent_dict): # Delete a default child only if provisioned for r_class = self.get_resource_class('floating-ip') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('floating_ips') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-floating-ip': default_child_id = has_info['href'].split('/')[-1] self.floating_ip_http_delete(default_child_id) break pass #end _floating_ip_pool_delete_default_children def physical_router_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_physical_router_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'physical_router': abort(404, 'No physical-router object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'physical_router', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('physical-router') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'physical_router', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'physical_router_management_ip', u'physical_router_dataplane_ip', u'physical_router_vendor_name', u'physical_router_product_name', u'physical_router_vnc_managed', u'physical_router_user_credentials', u'physical_router_snmp_credentials', u'physical_router_junos_service_ports', u'id_perms', u'display_name'] references = ['virtual_router_refs', 'bgp_router_refs', u'virtual_network_refs'] back_references = [u'global_system_config_back_refs'] children = [u'physical_interfaces', u'logical_interfaces'] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('physical-router', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'physical_router', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'physical_router', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('physical-router', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_physical_router_read', id, rsp_body) except Exception as e: pass return {'physical-router': rsp_body} #end physical_router_http_get def physical_router_http_put(self, id): key = 'physical-router' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_physical_router_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'physical_router': abort(404, 'No physical-router object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('physical_router_user_credentials') if prop_dict: buf = cStringIO.StringIO() xx_physical_router_user_credentials = UserCredentials(**prop_dict) xx_physical_router_user_credentials.export(buf) node = etree.fromstring(buf.getvalue()) xx_physical_router_user_credentials = UserCredentials() try: xx_physical_router_user_credentials.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('physical_router_snmp_credentials') if prop_dict: buf = cStringIO.StringIO() xx_physical_router_snmp_credentials = SNMPCredentials(**prop_dict) xx_physical_router_snmp_credentials.export(buf) node = etree.fromstring(buf.getvalue()) xx_physical_router_snmp_credentials = SNMPCredentials() try: xx_physical_router_snmp_credentials.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('physical_router_junos_service_ports') if prop_dict: buf = cStringIO.StringIO() xx_physical_router_junos_service_ports = JunosServicePorts(**prop_dict) xx_physical_router_junos_service_ports.export(buf) node = etree.fromstring(buf.getvalue()) xx_physical_router_junos_service_ports = JunosServicePorts() try: xx_physical_router_junos_service_ports.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'physical_router', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'physical_router', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = ['virtual_router', 'bgp_router', u'virtual_network', u'physical_interface', u'logical_interface'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('physical-router') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'physical_router', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('physical-router', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'physical_router', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('physical-router', id) try: self._extension_mgrs['resourceApi'].map_method('post_physical_router_update', id, obj_dict) except Exception as e: pass return {'physical-router': rsp_body} #end physical_router_http_put def physical_router_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'physical_router': abort(404, 'No physical-router object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_physical_router_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'global_system_config_back_refs'] children = [u'physical_interfaces', u'logical_interfaces'] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('physical-router', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'physical_router', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'physical_router', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'physical_router', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('physical-router', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('physical-router') if r_class: if read_ok: # fail if non-default children or backrefs exist physical_interfaces = read_result.get('physical_interfaces', None) if physical_interfaces: has_infos = read_result['physical_interfaces'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-physical-interface')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'physical_router', 'http_delete', err_msg) abort(409, err_msg) logical_interfaces = read_result.get('logical_interfaces', None) if logical_interfaces: has_infos = read_result['logical_interfaces'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-logical-interface')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'physical_router', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._physical_router_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'physical_router', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('physical-router', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'physical_router', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_physical_router_delete', id, read_result) except Exception as e: pass #end physical_router_http_delete def physical_routers_http_post(self): key = 'physical-router' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_physical_router_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('physical_router_user_credentials') if prop_dict: buf = cStringIO.StringIO() xx_physical_router_user_credentials = UserCredentials(**prop_dict) xx_physical_router_user_credentials.export(buf) node = etree.fromstring(buf.getvalue()) xx_physical_router_user_credentials = UserCredentials() try: xx_physical_router_user_credentials.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('physical_router_snmp_credentials') if prop_dict: buf = cStringIO.StringIO() xx_physical_router_snmp_credentials = SNMPCredentials(**prop_dict) xx_physical_router_snmp_credentials.export(buf) node = etree.fromstring(buf.getvalue()) xx_physical_router_snmp_credentials = SNMPCredentials() try: xx_physical_router_snmp_credentials.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('physical_router_junos_service_ports') if prop_dict: buf = cStringIO.StringIO() xx_physical_router_junos_service_ports = JunosServicePorts(**prop_dict) xx_physical_router_junos_service_ports.export(buf) node = etree.fromstring(buf.getvalue()) xx_physical_router_junos_service_ports = JunosServicePorts() try: xx_physical_router_junos_service_ports.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'physical-router', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'physical_router', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'physical_router', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = ['virtual_router', 'bgp_router', u'virtual_network', u'physical_interface', u'logical_interface'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('physical-router', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'physical_router', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['physical_router', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('physical-router') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'physical_router', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('physical-router', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'physical_router', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('physical-router', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_physical_router_create', obj_dict) except Exception as e: pass return {'physical-router': rsp_body} #end physical_routers_http_post def physical_routers_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'physical_routers', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('physical-router', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'physical_routers', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'physical-routers': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('physical-router', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('physical-router', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('physical-router', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'physical_router_management_ip', u'physical_router_dataplane_ip', u'physical_router_vendor_name', u'physical_router_product_name', u'physical_router_vnc_managed', u'physical_router_user_credentials', u'physical_router_snmp_credentials', u'physical_router_junos_service_ports', u'id_perms', u'display_name'] + ['virtual_router_refs', 'bgp_router_refs', u'virtual_network_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('physical-router', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('physical-router', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'physical-router': obj_dict}) return {'physical-routers': obj_dicts} #end physical_routers_http_get def _physical_router_create_default_children(self, parent_obj): # Create a default child only if provisioned for r_class = self.get_resource_class('physical-interface') if r_class and r_class.generate_default_instance: child_obj = PhysicalInterface(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('physical-interface') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('physical-interface', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('physical-interface', obj_ids, child_dict) self._physical_interface_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('logical-interface') if r_class and r_class.generate_default_instance: child_obj = LogicalInterface(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('logical-interface') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('logical-interface', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('logical-interface', obj_ids, child_dict) self._logical_interface_create_default_children(child_obj) pass #end _physical_router_create_default_children def _physical_router_delete_default_children(self, parent_dict): # Delete a default child only if provisioned for r_class = self.get_resource_class('logical-interface') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('physical_interfaces') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-physical-interface': default_child_id = has_info['href'].split('/')[-1] self.physical_interface_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('logical-interface') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('logical_interfaces') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-logical-interface': default_child_id = has_info['href'].split('/')[-1] self.logical_interface_http_delete(default_child_id) break pass #end _physical_router_delete_default_children def bgp_router_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_bgp_router_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'bgp_router': abort(404, 'No bgp-router object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'bgp_router', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('bgp-router') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'bgp_router', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'bgp_router_parameters', u'id_perms', u'display_name'] references = ['bgp_router_refs'] back_references = [u'global_system_config_back_refs', u'physical_router_back_refs', 'virtual_router_back_refs', 'routing_instance_back_refs', 'bgp_router_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('bgp-router', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'bgp_router', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'bgp_router', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('bgp-router', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_bgp_router_read', id, rsp_body) except Exception as e: pass return {'bgp-router': rsp_body} #end bgp_router_http_get def bgp_router_http_put(self, id): key = 'bgp-router' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_bgp_router_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'bgp_router': abort(404, 'No bgp-router object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('bgp_router_parameters') if prop_dict: buf = cStringIO.StringIO() xx_bgp_router_parameters = BgpRouterParams(**prop_dict) xx_bgp_router_parameters.export(buf) node = etree.fromstring(buf.getvalue()) xx_bgp_router_parameters = BgpRouterParams() try: xx_bgp_router_parameters.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) for ref_dict in obj_dict.get('bgp_router_refs') or []: if fq_name == ref_dict['to']: abort(404, 'Cannot add reference to self') buf = cStringIO.StringIO() xx_bgp_router = BgpPeeringAttributes(**ref_dict['attr']) xx_bgp_router.export(buf) node = etree.fromstring(buf.getvalue()) try: xx_bgp_router.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'bgp_router', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'bgp_router', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = ['bgp_router'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('bgp-router') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'bgp_router', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('bgp-router', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'bgp_router', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('bgp-router', id) try: self._extension_mgrs['resourceApi'].map_method('post_bgp_router_update', id, obj_dict) except Exception as e: pass return {'bgp-router': rsp_body} #end bgp_router_http_put def bgp_router_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'bgp_router': abort(404, 'No bgp-router object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_bgp_router_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'global_system_config_back_refs', u'physical_router_back_refs', 'virtual_router_back_refs', 'routing_instance_back_refs', 'bgp_router_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('bgp-router', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'bgp_router', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'bgp_router', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'bgp_router', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('bgp-router', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('bgp-router') if r_class: if read_ok: # fail if non-default children or backrefs exist global_system_config_back_refs = read_result.get('global_system_config_back_refs', None) if global_system_config_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['global_system_config_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'bgp_router', 'http_delete', err_msg) abort(409, err_msg) physical_router_back_refs = read_result.get('physical_router_back_refs', None) if physical_router_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['physical_router_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'bgp_router', 'http_delete', err_msg) abort(409, err_msg) virtual_router_back_refs = read_result.get('virtual_router_back_refs', None) if virtual_router_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['virtual_router_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'bgp_router', 'http_delete', err_msg) abort(409, err_msg) bgp_router_back_refs = read_result.get('bgp_router_back_refs', None) if bgp_router_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['bgp_router_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'bgp_router', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._bgp_router_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'bgp_router', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('bgp-router', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'bgp_router', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_bgp_router_delete', id, read_result) except Exception as e: pass #end bgp_router_http_delete def bgp_routers_http_post(self): key = 'bgp-router' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_bgp_router_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('bgp_router_parameters') if prop_dict: buf = cStringIO.StringIO() xx_bgp_router_parameters = BgpRouterParams(**prop_dict) xx_bgp_router_parameters.export(buf) node = etree.fromstring(buf.getvalue()) xx_bgp_router_parameters = BgpRouterParams() try: xx_bgp_router_parameters.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) for ref_dict in obj_dict.get('bgp_router_refs') or []: if fq_name == ref_dict['to']: abort(404, 'Cannot add reference to self') buf = cStringIO.StringIO() xx_bgp_router = BgpPeeringAttributes(**ref_dict['attr']) xx_bgp_router.export(buf) node = etree.fromstring(buf.getvalue()) try: xx_bgp_router.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'bgp-router', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'bgp_router', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'bgp_router', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = ['bgp_router'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('bgp-router', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'bgp_router', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['bgp_router', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('bgp-router') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'bgp_router', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('bgp-router', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'bgp_router', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('bgp-router', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_bgp_router_create', obj_dict) except Exception as e: pass return {'bgp-router': rsp_body} #end bgp_routers_http_post def bgp_routers_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'bgp_routers', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('bgp-router', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'bgp_routers', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'bgp-routers': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('bgp-router', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('bgp-router', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('bgp-router', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'bgp_router_parameters', u'id_perms', u'display_name'] + ['bgp_router_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('bgp-router', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('bgp-router', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'bgp-router': obj_dict}) return {'bgp-routers': obj_dicts} #end bgp_routers_http_get def _bgp_router_create_default_children(self, parent_obj): pass #end _bgp_router_create_default_children def _bgp_router_delete_default_children(self, parent_dict): pass #end _bgp_router_delete_default_children def virtual_router_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_router_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'virtual_router': abort(404, 'No virtual-router object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'virtual_router', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('virtual-router') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'virtual_router', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'virtual_router_type', u'virtual_router_ip_address', u'id_perms', u'display_name'] references = ['bgp_router_refs', u'virtual_machine_refs'] back_references = [u'physical_router_back_refs', u'global_system_config_back_refs', 'provider_attachment_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('virtual-router', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'virtual_router', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'virtual_router', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('virtual-router', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_virtual_router_read', id, rsp_body) except Exception as e: pass return {'virtual-router': rsp_body} #end virtual_router_http_get def virtual_router_http_put(self, id): key = 'virtual-router' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_router_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'virtual_router': abort(404, 'No virtual-router object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'virtual_router', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'virtual_router', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = ['bgp_router', u'virtual_machine'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('virtual-router') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'virtual_router', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('virtual-router', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'virtual_router', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('virtual-router', id) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_router_update', id, obj_dict) except Exception as e: pass return {'virtual-router': rsp_body} #end virtual_router_http_put def virtual_router_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'virtual_router': abort(404, 'No virtual-router object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_router_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'physical_router_back_refs', u'global_system_config_back_refs', 'provider_attachment_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('virtual-router', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'virtual_router', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'virtual_router', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'virtual_router', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('virtual-router', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('virtual-router') if r_class: if read_ok: # fail if non-default children or backrefs exist physical_router_back_refs = read_result.get('physical_router_back_refs', None) if physical_router_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['physical_router_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_router', 'http_delete', err_msg) abort(409, err_msg) provider_attachment_back_refs = read_result.get('provider_attachment_back_refs', None) if provider_attachment_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['provider_attachment_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_router', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._virtual_router_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'virtual_router', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('virtual-router', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'virtual_router', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_router_delete', id, read_result) except Exception as e: pass #end virtual_router_http_delete def virtual_routers_http_post(self): key = 'virtual-router' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_router_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'virtual-router', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'virtual_router', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'virtual_router', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = ['bgp_router', u'virtual_machine'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('virtual-router', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'virtual_router', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['virtual_router', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('virtual-router') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'virtual_router', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('virtual-router', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'virtual_router', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('virtual-router', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_router_create', obj_dict) except Exception as e: pass return {'virtual-router': rsp_body} #end virtual_routers_http_post def virtual_routers_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'virtual_routers', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('virtual-router', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'virtual_routers', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'virtual-routers': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('virtual-router', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('virtual-router', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('virtual-router', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'virtual_router_type', u'virtual_router_ip_address', u'id_perms', u'display_name'] + ['bgp_router_refs', u'virtual_machine_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('virtual-router', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('virtual-router', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'virtual-router': obj_dict}) return {'virtual-routers': obj_dicts} #end virtual_routers_http_get def _virtual_router_create_default_children(self, parent_obj): pass #end _virtual_router_create_default_children def _virtual_router_delete_default_children(self, parent_dict): pass #end _virtual_router_delete_default_children def config_root_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_config_root_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'config_root': abort(404, 'No config-root object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'config_root', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('config-root') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'config_root', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'id_perms', u'display_name'] references = [] back_references = [] children = [u'global_system_configs', u'domains'] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('config-root', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'config_root', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'config_root', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('config-root', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_config_root_read', id, rsp_body) except Exception as e: pass return {'config-root': rsp_body} #end config_root_http_get def config_root_http_put(self, id): key = 'config-root' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_config_root_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'config_root': abort(404, 'No config-root object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'config_root', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'config_root', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = [u'global_system_config', u'domain'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('config-root') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'config_root', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('config-root', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'config_root', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('config-root', id) try: self._extension_mgrs['resourceApi'].map_method('post_config_root_update', id, obj_dict) except Exception as e: pass return {'config-root': rsp_body} #end config_root_http_put def config_root_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'config_root': abort(404, 'No config-root object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_config_root_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [] children = [u'global_system_configs', u'domains'] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('config-root', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'config_root', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'config_root', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'config_root', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('config-root', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('config-root') if r_class: if read_ok: # fail if non-default children or backrefs exist global_system_configs = read_result.get('global_system_configs', None) if global_system_configs: has_infos = read_result['global_system_configs'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-global-system-config')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'config_root', 'http_delete', err_msg) abort(409, err_msg) domains = read_result.get('domains', None) if domains: has_infos = read_result['domains'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-domain')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'config_root', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._config_root_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'config_root', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('config-root', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'config_root', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_config_root_delete', id, read_result) except Exception as e: pass #end config_root_http_delete def config_roots_http_post(self): key = 'config-root' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_config_root_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'config-root', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'config_root', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # Validate perms objtype_list = [u'global_system_config', u'domain'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('config-root', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'config_root', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['config_root', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('config-root') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'config_root', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('config-root', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'config_root', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('config-root', obj_ids['uuid']) try: self._extension_mgrs['resourceApi'].map_method('post_config_root_create', obj_dict) except Exception as e: pass return {'config-root': rsp_body} #end config_roots_http_post def config_roots_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'config_roots', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('config-root', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'config_roots', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'config-roots': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('config-root', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('config-root', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('config-root', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('config-root', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('config-root', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'config-root': obj_dict}) return {'config-roots': obj_dicts} #end config_roots_http_get def _config_root_create_default_children(self, parent_obj): # Create a default child only if provisioned for r_class = self.get_resource_class('global-system-config') if r_class and r_class.generate_default_instance: child_obj = GlobalSystemConfig(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('global-system-config') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('global-system-config', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('global-system-config', obj_ids, child_dict) self._global_system_config_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('domain') if r_class and r_class.generate_default_instance: child_obj = Domain(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('domain') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('domain', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('domain', obj_ids, child_dict) self._domain_create_default_children(child_obj) pass #end _config_root_create_default_children def _config_root_delete_default_children(self, parent_dict): # Delete a default child only if provisioned for r_class = self.get_resource_class('domain') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('global_system_configs') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-global-system-config': default_child_id = has_info['href'].split('/')[-1] self.global_system_config_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('domain') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('domains') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-domain': default_child_id = has_info['href'].split('/')[-1] self.domain_http_delete(default_child_id) break pass #end _config_root_delete_default_children def subnet_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_subnet_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'subnet': abort(404, 'No subnet object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'subnet', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('subnet') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'subnet', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'subnet_ip_prefix', u'id_perms', u'display_name'] references = ['virtual_machine_interface_refs'] back_references = [] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('subnet', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'subnet', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'subnet', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('subnet', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_subnet_read', id, rsp_body) except Exception as e: pass return {'subnet': rsp_body} #end subnet_http_get def subnet_http_put(self, id): key = 'subnet' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_subnet_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'subnet': abort(404, 'No subnet object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('subnet_ip_prefix') if prop_dict: buf = cStringIO.StringIO() xx_subnet_ip_prefix = SubnetType(**prop_dict) xx_subnet_ip_prefix.export(buf) node = etree.fromstring(buf.getvalue()) xx_subnet_ip_prefix = SubnetType() try: xx_subnet_ip_prefix.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'subnet', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'subnet', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = ['virtual_machine_interface'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('subnet') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'subnet', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('subnet', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'subnet', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('subnet', id) try: self._extension_mgrs['resourceApi'].map_method('post_subnet_update', id, obj_dict) except Exception as e: pass return {'subnet': rsp_body} #end subnet_http_put def subnet_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'subnet': abort(404, 'No subnet object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_subnet_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('subnet', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'subnet', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'subnet', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'subnet', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('subnet', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('subnet') if r_class: if read_ok: # fail if non-default children or backrefs exist # Delete default children first self._subnet_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'subnet', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('subnet', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'subnet', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_subnet_delete', id, read_result) except Exception as e: pass #end subnet_http_delete def subnets_http_post(self): key = 'subnet' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_subnet_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('subnet_ip_prefix') if prop_dict: buf = cStringIO.StringIO() xx_subnet_ip_prefix = SubnetType(**prop_dict) xx_subnet_ip_prefix.export(buf) node = etree.fromstring(buf.getvalue()) xx_subnet_ip_prefix = SubnetType() try: xx_subnet_ip_prefix.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'subnet', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'subnet', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # Validate perms objtype_list = ['virtual_machine_interface'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('subnet', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'subnet', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['subnet', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('subnet') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'subnet', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('subnet', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'subnet', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('subnet', obj_ids['uuid']) try: self._extension_mgrs['resourceApi'].map_method('post_subnet_create', obj_dict) except Exception as e: pass return {'subnet': rsp_body} #end subnets_http_post def subnets_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'subnets', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('subnet', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'subnets', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'subnets': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('subnet', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('subnet', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('subnet', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'subnet_ip_prefix', u'id_perms', u'display_name'] + ['virtual_machine_interface_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('subnet', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('subnet', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'subnet': obj_dict}) return {'subnets': obj_dicts} #end subnets_http_get def _subnet_create_default_children(self, parent_obj): pass #end _subnet_create_default_children def _subnet_delete_default_children(self, parent_dict): pass #end _subnet_delete_default_children def global_system_config_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_global_system_config_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'global_system_config': abort(404, 'No global-system-config object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'global_system_config', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('global-system-config') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'global_system_config', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'autonomous_system', u'config_version', u'plugin_tuning', u'ibgp_auto_mesh', u'ip_fabric_subnets', u'id_perms', u'display_name'] references = ['bgp_router_refs'] back_references = [u'config_root_back_refs'] children = [u'global_vrouter_configs', u'physical_routers', 'virtual_routers', u'config_nodes', u'analytics_nodes', u'database_nodes', u'service_appliance_sets'] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('global-system-config', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'global_system_config', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'global_system_config', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('global-system-config', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_global_system_config_read', id, rsp_body) except Exception as e: pass return {'global-system-config': rsp_body} #end global_system_config_http_get def global_system_config_http_put(self, id): key = 'global-system-config' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_global_system_config_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'global_system_config': abort(404, 'No global-system-config object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('plugin_tuning') if prop_dict: buf = cStringIO.StringIO() xx_plugin_tuning = PluginProperties(**prop_dict) xx_plugin_tuning.export(buf) node = etree.fromstring(buf.getvalue()) xx_plugin_tuning = PluginProperties() try: xx_plugin_tuning.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('ip_fabric_subnets') if prop_dict: buf = cStringIO.StringIO() xx_ip_fabric_subnets = SubnetListType(**prop_dict) xx_ip_fabric_subnets.export(buf) node = etree.fromstring(buf.getvalue()) xx_ip_fabric_subnets = SubnetListType() try: xx_ip_fabric_subnets.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'global_system_config', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'global_system_config', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = ['bgp_router', u'global_vrouter_config', u'physical_router', 'virtual_router', u'config_node', u'analytics_node', u'database_node', u'service_appliance_set'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('global-system-config') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'global_system_config', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('global-system-config', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'global_system_config', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('global-system-config', id) try: self._extension_mgrs['resourceApi'].map_method('post_global_system_config_update', id, obj_dict) except Exception as e: pass return {'global-system-config': rsp_body} #end global_system_config_http_put def global_system_config_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'global_system_config': abort(404, 'No global-system-config object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_global_system_config_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'config_root_back_refs'] children = [u'global_vrouter_configs', u'physical_routers', 'virtual_routers', u'config_nodes', u'analytics_nodes', u'database_nodes', u'service_appliance_sets'] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('global-system-config', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'global_system_config', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'global_system_config', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'global_system_config', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('global-system-config', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('global-system-config') if r_class: if read_ok: # fail if non-default children or backrefs exist global_vrouter_configs = read_result.get('global_vrouter_configs', None) if global_vrouter_configs: has_infos = read_result['global_vrouter_configs'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-global-vrouter-config')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'global_system_config', 'http_delete', err_msg) abort(409, err_msg) physical_routers = read_result.get('physical_routers', None) if physical_routers: has_infos = read_result['physical_routers'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-physical-router')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'global_system_config', 'http_delete', err_msg) abort(409, err_msg) virtual_routers = read_result.get('virtual_routers', None) if virtual_routers: has_infos = read_result['virtual_routers'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-virtual-router')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'global_system_config', 'http_delete', err_msg) abort(409, err_msg) config_nodes = read_result.get('config_nodes', None) if config_nodes: has_infos = read_result['config_nodes'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-config-node')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'global_system_config', 'http_delete', err_msg) abort(409, err_msg) analytics_nodes = read_result.get('analytics_nodes', None) if analytics_nodes: has_infos = read_result['analytics_nodes'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-analytics-node')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'global_system_config', 'http_delete', err_msg) abort(409, err_msg) database_nodes = read_result.get('database_nodes', None) if database_nodes: has_infos = read_result['database_nodes'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-database-node')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'global_system_config', 'http_delete', err_msg) abort(409, err_msg) service_appliance_sets = read_result.get('service_appliance_sets', None) if service_appliance_sets: has_infos = read_result['service_appliance_sets'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-service-appliance-set')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'global_system_config', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._global_system_config_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'global_system_config', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('global-system-config', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'global_system_config', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_global_system_config_delete', id, read_result) except Exception as e: pass #end global_system_config_http_delete def global_system_configs_http_post(self): key = 'global-system-config' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_global_system_config_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('plugin_tuning') if prop_dict: buf = cStringIO.StringIO() xx_plugin_tuning = PluginProperties(**prop_dict) xx_plugin_tuning.export(buf) node = etree.fromstring(buf.getvalue()) xx_plugin_tuning = PluginProperties() try: xx_plugin_tuning.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('ip_fabric_subnets') if prop_dict: buf = cStringIO.StringIO() xx_ip_fabric_subnets = SubnetListType(**prop_dict) xx_ip_fabric_subnets.export(buf) node = etree.fromstring(buf.getvalue()) xx_ip_fabric_subnets = SubnetListType() try: xx_ip_fabric_subnets.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'global-system-config', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'global_system_config', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'global_system_config', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = ['bgp_router', u'global_vrouter_config', u'physical_router', 'virtual_router', u'config_node', u'analytics_node', u'database_node', u'service_appliance_set'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('global-system-config', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'global_system_config', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['global_system_config', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('global-system-config') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'global_system_config', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('global-system-config', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'global_system_config', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('global-system-config', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_global_system_config_create', obj_dict) except Exception as e: pass return {'global-system-config': rsp_body} #end global_system_configs_http_post def global_system_configs_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'global_system_configs', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('global-system-config', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'global_system_configs', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'global-system-configs': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('global-system-config', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('global-system-config', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('global-system-config', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'autonomous_system', u'config_version', u'plugin_tuning', u'ibgp_auto_mesh', u'ip_fabric_subnets', u'id_perms', u'display_name'] + ['bgp_router_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('global-system-config', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('global-system-config', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'global-system-config': obj_dict}) return {'global-system-configs': obj_dicts} #end global_system_configs_http_get def _global_system_config_create_default_children(self, parent_obj): # Create a default child only if provisioned for r_class = self.get_resource_class('global-vrouter-config') if r_class and r_class.generate_default_instance: child_obj = GlobalVrouterConfig(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('global-vrouter-config') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('global-vrouter-config', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('global-vrouter-config', obj_ids, child_dict) self._global_vrouter_config_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('physical-router') if r_class and r_class.generate_default_instance: child_obj = PhysicalRouter(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('physical-router') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('physical-router', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('physical-router', obj_ids, child_dict) self._physical_router_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('virtual-router') if r_class and r_class.generate_default_instance: child_obj = VirtualRouter(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('virtual-router') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('virtual-router', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('virtual-router', obj_ids, child_dict) self._virtual_router_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('config-node') if r_class and r_class.generate_default_instance: child_obj = ConfigNode(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('config-node') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('config-node', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('config-node', obj_ids, child_dict) self._config_node_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('analytics-node') if r_class and r_class.generate_default_instance: child_obj = AnalyticsNode(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('analytics-node') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('analytics-node', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('analytics-node', obj_ids, child_dict) self._analytics_node_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('database-node') if r_class and r_class.generate_default_instance: child_obj = DatabaseNode(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('database-node') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('database-node', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('database-node', obj_ids, child_dict) self._database_node_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('service-appliance-set') if r_class and r_class.generate_default_instance: child_obj = ServiceApplianceSet(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('service-appliance-set') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('service-appliance-set', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('service-appliance-set', obj_ids, child_dict) self._service_appliance_set_create_default_children(child_obj) pass #end _global_system_config_create_default_children def _global_system_config_delete_default_children(self, parent_dict): # Delete a default child only if provisioned for r_class = self.get_resource_class('service-appliance-set') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('global_vrouter_configs') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-global-vrouter-config': default_child_id = has_info['href'].split('/')[-1] self.global_vrouter_config_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('service-appliance-set') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('physical_routers') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-physical-router': default_child_id = has_info['href'].split('/')[-1] self.physical_router_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('service-appliance-set') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('virtual_routers') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-virtual-router': default_child_id = has_info['href'].split('/')[-1] self.virtual_router_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('service-appliance-set') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('config_nodes') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-config-node': default_child_id = has_info['href'].split('/')[-1] self.config_node_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('service-appliance-set') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('analytics_nodes') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-analytics-node': default_child_id = has_info['href'].split('/')[-1] self.analytics_node_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('service-appliance-set') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('database_nodes') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-database-node': default_child_id = has_info['href'].split('/')[-1] self.database_node_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('service-appliance-set') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('service_appliance_sets') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-service-appliance-set': default_child_id = has_info['href'].split('/')[-1] self.service_appliance_set_http_delete(default_child_id) break pass #end _global_system_config_delete_default_children def service_appliance_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_service_appliance_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'service_appliance': abort(404, 'No service-appliance object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'service_appliance', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('service-appliance') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'service_appliance', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'service_appliance_user_credentials', u'service_appliance_ip_address', u'service_appliance_properties', u'id_perms', u'display_name'] references = [] back_references = [u'service_appliance_set_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('service-appliance', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'service_appliance', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'service_appliance', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('service-appliance', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_service_appliance_read', id, rsp_body) except Exception as e: pass return {'service-appliance': rsp_body} #end service_appliance_http_get def service_appliance_http_put(self, id): key = 'service-appliance' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_service_appliance_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'service_appliance': abort(404, 'No service-appliance object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('service_appliance_user_credentials') if prop_dict: buf = cStringIO.StringIO() xx_service_appliance_user_credentials = UserCredentials(**prop_dict) xx_service_appliance_user_credentials.export(buf) node = etree.fromstring(buf.getvalue()) xx_service_appliance_user_credentials = UserCredentials() try: xx_service_appliance_user_credentials.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('service_appliance_properties') if prop_dict: buf = cStringIO.StringIO() xx_service_appliance_properties = KeyValuePairs(**prop_dict) xx_service_appliance_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_service_appliance_properties = KeyValuePairs() try: xx_service_appliance_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'service_appliance', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'service_appliance', 'http_put', msg) abort(code, msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('service-appliance') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'service_appliance', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('service-appliance', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'service_appliance', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('service-appliance', id) try: self._extension_mgrs['resourceApi'].map_method('post_service_appliance_update', id, obj_dict) except Exception as e: pass return {'service-appliance': rsp_body} #end service_appliance_http_put def service_appliance_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'service_appliance': abort(404, 'No service-appliance object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_service_appliance_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'service_appliance_set_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('service-appliance', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'service_appliance', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'service_appliance', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'service_appliance', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('service-appliance', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('service-appliance') if r_class: if read_ok: # fail if non-default children or backrefs exist # Delete default children first self._service_appliance_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'service_appliance', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('service-appliance', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'service_appliance', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_service_appliance_delete', id, read_result) except Exception as e: pass #end service_appliance_http_delete def service_appliances_http_post(self): key = 'service-appliance' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_service_appliance_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('service_appliance_user_credentials') if prop_dict: buf = cStringIO.StringIO() xx_service_appliance_user_credentials = UserCredentials(**prop_dict) xx_service_appliance_user_credentials.export(buf) node = etree.fromstring(buf.getvalue()) xx_service_appliance_user_credentials = UserCredentials() try: xx_service_appliance_user_credentials.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('service_appliance_properties') if prop_dict: buf = cStringIO.StringIO() xx_service_appliance_properties = KeyValuePairs(**prop_dict) xx_service_appliance_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_service_appliance_properties = KeyValuePairs() try: xx_service_appliance_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'service-appliance', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'service_appliance', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'service_appliance', 'http_post', err_msg) abort(400, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('service-appliance', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'service_appliance', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['service_appliance', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('service-appliance') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'service_appliance', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('service-appliance', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'service_appliance', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('service-appliance', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_service_appliance_create', obj_dict) except Exception as e: pass return {'service-appliance': rsp_body} #end service_appliances_http_post def service_appliances_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'service_appliances', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('service-appliance', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'service_appliances', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'service-appliances': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('service-appliance', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('service-appliance', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('service-appliance', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'service_appliance_user_credentials', u'service_appliance_ip_address', u'service_appliance_properties', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('service-appliance', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('service-appliance', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'service-appliance': obj_dict}) return {'service-appliances': obj_dicts} #end service_appliances_http_get def _service_appliance_create_default_children(self, parent_obj): pass #end _service_appliance_create_default_children def _service_appliance_delete_default_children(self, parent_dict): pass #end _service_appliance_delete_default_children def service_instance_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_service_instance_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'service_instance': abort(404, 'No service-instance object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'service_instance', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('service-instance') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'service_instance', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'service_instance_properties', u'id_perms', u'display_name'] references = ['service_template_refs'] back_references = [u'project_back_refs', u'virtual_machine_back_refs', u'logical_router_back_refs', u'loadbalancer_pool_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('service-instance', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'service_instance', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'service_instance', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('service-instance', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_service_instance_read', id, rsp_body) except Exception as e: pass return {'service-instance': rsp_body} #end service_instance_http_get def service_instance_http_put(self, id): key = 'service-instance' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_service_instance_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'service_instance': abort(404, 'No service-instance object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('service_instance_properties') if prop_dict: buf = cStringIO.StringIO() xx_service_instance_properties = ServiceInstanceType(**prop_dict) xx_service_instance_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_service_instance_properties = ServiceInstanceType() try: xx_service_instance_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'service_instance', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'service_instance', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = ['service_template'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('service-instance') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'service_instance', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('service-instance', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'service_instance', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('service-instance', id) try: self._extension_mgrs['resourceApi'].map_method('post_service_instance_update', id, obj_dict) except Exception as e: pass return {'service-instance': rsp_body} #end service_instance_http_put def service_instance_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'service_instance': abort(404, 'No service-instance object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_service_instance_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'project_back_refs', u'virtual_machine_back_refs', u'logical_router_back_refs', u'loadbalancer_pool_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('service-instance', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'service_instance', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'service_instance', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'service_instance', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('service-instance', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('service-instance') if r_class: if read_ok: # fail if non-default children or backrefs exist logical_router_back_refs = read_result.get('logical_router_back_refs', None) if logical_router_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['logical_router_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'service_instance', 'http_delete', err_msg) abort(409, err_msg) loadbalancer_pool_back_refs = read_result.get('loadbalancer_pool_back_refs', None) if loadbalancer_pool_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['loadbalancer_pool_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'service_instance', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._service_instance_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'service_instance', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('service-instance', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'service_instance', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_service_instance_delete', id, read_result) except Exception as e: pass #end service_instance_http_delete def service_instances_http_post(self): key = 'service-instance' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_service_instance_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('service_instance_properties') if prop_dict: buf = cStringIO.StringIO() xx_service_instance_properties = ServiceInstanceType(**prop_dict) xx_service_instance_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_service_instance_properties = ServiceInstanceType() try: xx_service_instance_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'service-instance', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'service_instance', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'service_instance', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = ['service_template'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('service-instance', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'service_instance', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['service_instance', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('service-instance') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'service_instance', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('service-instance', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'service_instance', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('service-instance', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_service_instance_create', obj_dict) except Exception as e: pass return {'service-instance': rsp_body} #end service_instances_http_post def service_instances_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'service_instances', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('service-instance', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'service_instances', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'service-instances': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('service-instance', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('service-instance', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('service-instance', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'service_instance_properties', u'id_perms', u'display_name'] + ['service_template_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('service-instance', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('service-instance', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'service-instance': obj_dict}) return {'service-instances': obj_dicts} #end service_instances_http_get def _service_instance_create_default_children(self, parent_obj): pass #end _service_instance_create_default_children def _service_instance_delete_default_children(self, parent_dict): pass #end _service_instance_delete_default_children def namespace_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_namespace_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'namespace': abort(404, 'No namespace object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'namespace', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('namespace') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'namespace', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'namespace_cidr', u'id_perms', u'display_name'] references = [] back_references = [u'domain_back_refs', u'project_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('namespace', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'namespace', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'namespace', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('namespace', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_namespace_read', id, rsp_body) except Exception as e: pass return {'namespace': rsp_body} #end namespace_http_get def namespace_http_put(self, id): key = 'namespace' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_namespace_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'namespace': abort(404, 'No namespace object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('namespace_cidr') if prop_dict: buf = cStringIO.StringIO() xx_namespace_cidr = SubnetType(**prop_dict) xx_namespace_cidr.export(buf) node = etree.fromstring(buf.getvalue()) xx_namespace_cidr = SubnetType() try: xx_namespace_cidr.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'namespace', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'namespace', 'http_put', msg) abort(code, msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('namespace') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'namespace', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('namespace', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'namespace', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('namespace', id) try: self._extension_mgrs['resourceApi'].map_method('post_namespace_update', id, obj_dict) except Exception as e: pass return {'namespace': rsp_body} #end namespace_http_put def namespace_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'namespace': abort(404, 'No namespace object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_namespace_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'domain_back_refs', u'project_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('namespace', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'namespace', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'namespace', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'namespace', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('namespace', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('namespace') if r_class: if read_ok: # fail if non-default children or backrefs exist project_back_refs = read_result.get('project_back_refs', None) if project_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['project_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'namespace', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._namespace_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'namespace', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('namespace', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'namespace', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_namespace_delete', id, read_result) except Exception as e: pass #end namespace_http_delete def namespaces_http_post(self): key = 'namespace' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_namespace_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('namespace_cidr') if prop_dict: buf = cStringIO.StringIO() xx_namespace_cidr = SubnetType(**prop_dict) xx_namespace_cidr.export(buf) node = etree.fromstring(buf.getvalue()) xx_namespace_cidr = SubnetType() try: xx_namespace_cidr.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'namespace', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'namespace', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'namespace', 'http_post', err_msg) abort(400, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('namespace', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'namespace', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['namespace', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('namespace') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'namespace', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('namespace', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'namespace', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('namespace', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_namespace_create', obj_dict) except Exception as e: pass return {'namespace': rsp_body} #end namespaces_http_post def namespaces_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'namespaces', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('namespace', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'namespaces', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'namespaces': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('namespace', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('namespace', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('namespace', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'namespace_cidr', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('namespace', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('namespace', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'namespace': obj_dict}) return {'namespaces': obj_dicts} #end namespaces_http_get def _namespace_create_default_children(self, parent_obj): pass #end _namespace_create_default_children def _namespace_delete_default_children(self, parent_dict): pass #end _namespace_delete_default_children def logical_interface_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_logical_interface_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'logical_interface': abort(404, 'No logical-interface object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'logical_interface', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('logical-interface') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'logical_interface', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'logical_interface_vlan_tag', u'logical_interface_type', u'id_perms', u'display_name'] references = ['virtual_machine_interface_refs'] back_references = [u'physical_router_back_refs', u'physical_interface_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('logical-interface', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'logical_interface', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'logical_interface', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('logical-interface', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_logical_interface_read', id, rsp_body) except Exception as e: pass return {'logical-interface': rsp_body} #end logical_interface_http_get def logical_interface_http_put(self, id): key = 'logical-interface' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_logical_interface_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'logical_interface': abort(404, 'No logical-interface object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'logical_interface', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'logical_interface', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = ['virtual_machine_interface'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('logical-interface') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'logical_interface', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('logical-interface', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'logical_interface', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('logical-interface', id) try: self._extension_mgrs['resourceApi'].map_method('post_logical_interface_update', id, obj_dict) except Exception as e: pass return {'logical-interface': rsp_body} #end logical_interface_http_put def logical_interface_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'logical_interface': abort(404, 'No logical-interface object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_logical_interface_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'physical_router_back_refs', u'physical_interface_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('logical-interface', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'logical_interface', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'logical_interface', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'logical_interface', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('logical-interface', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('logical-interface') if r_class: if read_ok: # fail if non-default children or backrefs exist # Delete default children first self._logical_interface_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'logical_interface', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('logical-interface', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'logical_interface', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_logical_interface_delete', id, read_result) except Exception as e: pass #end logical_interface_http_delete def logical_interfaces_http_post(self): key = 'logical-interface' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_logical_interface_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'logical-interface', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'logical_interface', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'logical_interface', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = ['virtual_machine_interface'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('logical-interface', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'logical_interface', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['logical_interface', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('logical-interface') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'logical_interface', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('logical-interface', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'logical_interface', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('logical-interface', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_logical_interface_create', obj_dict) except Exception as e: pass return {'logical-interface': rsp_body} #end logical_interfaces_http_post def logical_interfaces_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'logical_interfaces', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('logical-interface', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'logical_interfaces', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'logical-interfaces': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('logical-interface', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('logical-interface', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('logical-interface', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'logical_interface_vlan_tag', u'logical_interface_type', u'id_perms', u'display_name'] + ['virtual_machine_interface_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('logical-interface', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('logical-interface', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'logical-interface': obj_dict}) return {'logical-interfaces': obj_dicts} #end logical_interfaces_http_get def _logical_interface_create_default_children(self, parent_obj): pass #end _logical_interface_create_default_children def _logical_interface_delete_default_children(self, parent_dict): pass #end _logical_interface_delete_default_children def route_table_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_route_table_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'route_table': abort(404, 'No route-table object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'route_table', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('route-table') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'route_table', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'routes', u'id_perms', u'display_name'] references = [] back_references = [u'project_back_refs', u'virtual_network_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('route-table', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'route_table', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'route_table', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('route-table', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_route_table_read', id, rsp_body) except Exception as e: pass return {'route-table': rsp_body} #end route_table_http_get def route_table_http_put(self, id): key = 'route-table' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_route_table_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'route_table': abort(404, 'No route-table object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('routes') if prop_dict: buf = cStringIO.StringIO() xx_routes = RouteTableType(**prop_dict) xx_routes.export(buf) node = etree.fromstring(buf.getvalue()) xx_routes = RouteTableType() try: xx_routes.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'route_table', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'route_table', 'http_put', msg) abort(code, msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('route-table') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'route_table', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('route-table', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'route_table', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('route-table', id) try: self._extension_mgrs['resourceApi'].map_method('post_route_table_update', id, obj_dict) except Exception as e: pass return {'route-table': rsp_body} #end route_table_http_put def route_table_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'route_table': abort(404, 'No route-table object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_route_table_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'project_back_refs', u'virtual_network_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('route-table', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'route_table', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'route_table', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'route_table', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('route-table', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('route-table') if r_class: if read_ok: # fail if non-default children or backrefs exist virtual_network_back_refs = read_result.get('virtual_network_back_refs', None) if virtual_network_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['virtual_network_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'route_table', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._route_table_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'route_table', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('route-table', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'route_table', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_route_table_delete', id, read_result) except Exception as e: pass #end route_table_http_delete def route_tables_http_post(self): key = 'route-table' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_route_table_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('routes') if prop_dict: buf = cStringIO.StringIO() xx_routes = RouteTableType(**prop_dict) xx_routes.export(buf) node = etree.fromstring(buf.getvalue()) xx_routes = RouteTableType() try: xx_routes.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'route-table', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'route_table', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'route_table', 'http_post', err_msg) abort(400, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('route-table', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'route_table', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['route_table', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('route-table') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'route_table', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('route-table', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'route_table', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('route-table', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_route_table_create', obj_dict) except Exception as e: pass return {'route-table': rsp_body} #end route_tables_http_post def route_tables_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'route_tables', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('route-table', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'route_tables', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'route-tables': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('route-table', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('route-table', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('route-table', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'routes', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('route-table', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('route-table', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'route-table': obj_dict}) return {'route-tables': obj_dicts} #end route_tables_http_get def _route_table_create_default_children(self, parent_obj): pass #end _route_table_create_default_children def _route_table_delete_default_children(self, parent_dict): pass #end _route_table_delete_default_children def physical_interface_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_physical_interface_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'physical_interface': abort(404, 'No physical-interface object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'physical_interface', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('physical-interface') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'physical_interface', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'id_perms', u'display_name'] references = [] back_references = [u'physical_router_back_refs'] children = [u'logical_interfaces'] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('physical-interface', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'physical_interface', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'physical_interface', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('physical-interface', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_physical_interface_read', id, rsp_body) except Exception as e: pass return {'physical-interface': rsp_body} #end physical_interface_http_get def physical_interface_http_put(self, id): key = 'physical-interface' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_physical_interface_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'physical_interface': abort(404, 'No physical-interface object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'physical_interface', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'physical_interface', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = [u'logical_interface'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('physical-interface') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'physical_interface', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('physical-interface', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'physical_interface', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('physical-interface', id) try: self._extension_mgrs['resourceApi'].map_method('post_physical_interface_update', id, obj_dict) except Exception as e: pass return {'physical-interface': rsp_body} #end physical_interface_http_put def physical_interface_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'physical_interface': abort(404, 'No physical-interface object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_physical_interface_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'physical_router_back_refs'] children = [u'logical_interfaces'] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('physical-interface', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'physical_interface', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'physical_interface', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'physical_interface', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('physical-interface', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('physical-interface') if r_class: if read_ok: # fail if non-default children or backrefs exist logical_interfaces = read_result.get('logical_interfaces', None) if logical_interfaces: has_infos = read_result['logical_interfaces'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-logical-interface')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'physical_interface', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._physical_interface_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'physical_interface', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('physical-interface', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'physical_interface', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_physical_interface_delete', id, read_result) except Exception as e: pass #end physical_interface_http_delete def physical_interfaces_http_post(self): key = 'physical-interface' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_physical_interface_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'physical-interface', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'physical_interface', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'physical_interface', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = [u'logical_interface'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('physical-interface', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'physical_interface', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['physical_interface', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('physical-interface') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'physical_interface', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('physical-interface', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'physical_interface', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('physical-interface', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_physical_interface_create', obj_dict) except Exception as e: pass return {'physical-interface': rsp_body} #end physical_interfaces_http_post def physical_interfaces_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'physical_interfaces', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('physical-interface', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'physical_interfaces', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'physical-interfaces': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('physical-interface', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('physical-interface', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('physical-interface', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('physical-interface', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('physical-interface', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'physical-interface': obj_dict}) return {'physical-interfaces': obj_dicts} #end physical_interfaces_http_get def _physical_interface_create_default_children(self, parent_obj): # Create a default child only if provisioned for r_class = self.get_resource_class('logical-interface') if r_class and r_class.generate_default_instance: child_obj = LogicalInterface(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('logical-interface') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('logical-interface', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('logical-interface', obj_ids, child_dict) self._logical_interface_create_default_children(child_obj) pass #end _physical_interface_create_default_children def _physical_interface_delete_default_children(self, parent_dict): # Delete a default child only if provisioned for r_class = self.get_resource_class('logical-interface') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('logical_interfaces') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-logical-interface': default_child_id = has_info['href'].split('/')[-1] self.logical_interface_http_delete(default_child_id) break pass #end _physical_interface_delete_default_children def access_control_list_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_access_control_list_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'access_control_list': abort(404, 'No access-control-list object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'access_control_list', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('access-control-list') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'access_control_list', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'access_control_list_entries', u'id_perms', u'display_name'] references = [] back_references = [u'virtual_network_back_refs', u'security_group_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('access-control-list', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'access_control_list', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'access_control_list', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('access-control-list', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_access_control_list_read', id, rsp_body) except Exception as e: pass return {'access-control-list': rsp_body} #end access_control_list_http_get def access_control_list_http_put(self, id): key = 'access-control-list' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_access_control_list_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'access_control_list': abort(404, 'No access-control-list object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('access_control_list_entries') if prop_dict: buf = cStringIO.StringIO() xx_access_control_list_entries = AclEntriesType(**prop_dict) xx_access_control_list_entries.export(buf) node = etree.fromstring(buf.getvalue()) xx_access_control_list_entries = AclEntriesType() try: xx_access_control_list_entries.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'access_control_list', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'access_control_list', 'http_put', msg) abort(code, msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('access-control-list') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'access_control_list', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('access-control-list', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'access_control_list', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('access-control-list', id) try: self._extension_mgrs['resourceApi'].map_method('post_access_control_list_update', id, obj_dict) except Exception as e: pass return {'access-control-list': rsp_body} #end access_control_list_http_put def access_control_list_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'access_control_list': abort(404, 'No access-control-list object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_access_control_list_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'virtual_network_back_refs', u'security_group_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('access-control-list', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'access_control_list', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'access_control_list', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'access_control_list', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('access-control-list', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('access-control-list') if r_class: if read_ok: # fail if non-default children or backrefs exist # Delete default children first self._access_control_list_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'access_control_list', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('access-control-list', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'access_control_list', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_access_control_list_delete', id, read_result) except Exception as e: pass #end access_control_list_http_delete def access_control_lists_http_post(self): key = 'access-control-list' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_access_control_list_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('access_control_list_entries') if prop_dict: buf = cStringIO.StringIO() xx_access_control_list_entries = AclEntriesType(**prop_dict) xx_access_control_list_entries.export(buf) node = etree.fromstring(buf.getvalue()) xx_access_control_list_entries = AclEntriesType() try: xx_access_control_list_entries.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'access-control-list', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'access_control_list', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'access_control_list', 'http_post', err_msg) abort(400, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('access-control-list', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'access_control_list', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['access_control_list', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('access-control-list') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'access_control_list', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('access-control-list', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'access_control_list', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('access-control-list', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_access_control_list_create', obj_dict) except Exception as e: pass return {'access-control-list': rsp_body} #end access_control_lists_http_post def access_control_lists_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'access_control_lists', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('access-control-list', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'access_control_lists', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'access-control-lists': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('access-control-list', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('access-control-list', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('access-control-list', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'access_control_list_entries', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('access-control-list', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('access-control-list', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'access-control-list': obj_dict}) return {'access-control-lists': obj_dicts} #end access_control_lists_http_get def _access_control_list_create_default_children(self, parent_obj): pass #end _access_control_list_create_default_children def _access_control_list_delete_default_children(self, parent_dict): pass #end _access_control_list_delete_default_children def analytics_node_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_analytics_node_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'analytics_node': abort(404, 'No analytics-node object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'analytics_node', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('analytics-node') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'analytics_node', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'analytics_node_ip_address', u'id_perms', u'display_name'] references = [] back_references = [u'global_system_config_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('analytics-node', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'analytics_node', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'analytics_node', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('analytics-node', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_analytics_node_read', id, rsp_body) except Exception as e: pass return {'analytics-node': rsp_body} #end analytics_node_http_get def analytics_node_http_put(self, id): key = 'analytics-node' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_analytics_node_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'analytics_node': abort(404, 'No analytics-node object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'analytics_node', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'analytics_node', 'http_put', msg) abort(code, msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('analytics-node') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'analytics_node', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('analytics-node', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'analytics_node', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('analytics-node', id) try: self._extension_mgrs['resourceApi'].map_method('post_analytics_node_update', id, obj_dict) except Exception as e: pass return {'analytics-node': rsp_body} #end analytics_node_http_put def analytics_node_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'analytics_node': abort(404, 'No analytics-node object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_analytics_node_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'global_system_config_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('analytics-node', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'analytics_node', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'analytics_node', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'analytics_node', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('analytics-node', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('analytics-node') if r_class: if read_ok: # fail if non-default children or backrefs exist # Delete default children first self._analytics_node_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'analytics_node', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('analytics-node', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'analytics_node', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_analytics_node_delete', id, read_result) except Exception as e: pass #end analytics_node_http_delete def analytics_nodes_http_post(self): key = 'analytics-node' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_analytics_node_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'analytics-node', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'analytics_node', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'analytics_node', 'http_post', err_msg) abort(400, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('analytics-node', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'analytics_node', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['analytics_node', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('analytics-node') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'analytics_node', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('analytics-node', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'analytics_node', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('analytics-node', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_analytics_node_create', obj_dict) except Exception as e: pass return {'analytics-node': rsp_body} #end analytics_nodes_http_post def analytics_nodes_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'analytics_nodes', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('analytics-node', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'analytics_nodes', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'analytics-nodes': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('analytics-node', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('analytics-node', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('analytics-node', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'analytics_node_ip_address', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('analytics-node', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('analytics-node', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'analytics-node': obj_dict}) return {'analytics-nodes': obj_dicts} #end analytics_nodes_http_get def _analytics_node_create_default_children(self, parent_obj): pass #end _analytics_node_create_default_children def _analytics_node_delete_default_children(self, parent_dict): pass #end _analytics_node_delete_default_children def virtual_DNS_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_DNS_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'virtual_DNS': abort(404, 'No virtual-DNS object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'virtual_DNS', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('virtual-DNS') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'virtual_DNS', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'virtual_DNS_data', u'id_perms', u'display_name'] references = [] back_references = [u'domain_back_refs', u'network_ipam_back_refs'] children = [u'virtual_DNS_records'] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('virtual-DNS', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'virtual_DNS', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'virtual_DNS', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('virtual-DNS', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_virtual_DNS_read', id, rsp_body) except Exception as e: pass return {'virtual-DNS': rsp_body} #end virtual_DNS_http_get def virtual_DNS_http_put(self, id): key = 'virtual-DNS' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_DNS_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'virtual_DNS': abort(404, 'No virtual-DNS object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('virtual_DNS_data') if prop_dict: buf = cStringIO.StringIO() xx_virtual_DNS_data = VirtualDnsType(**prop_dict) xx_virtual_DNS_data.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_DNS_data = VirtualDnsType() try: xx_virtual_DNS_data.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'virtual_DNS', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'virtual_DNS', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = [u'virtual_DNS_record'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('virtual-DNS') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'virtual_DNS', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('virtual-DNS', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'virtual_DNS', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('virtual-DNS', id) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_DNS_update', id, obj_dict) except Exception as e: pass return {'virtual-DNS': rsp_body} #end virtual_DNS_http_put def virtual_DNS_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'virtual_DNS': abort(404, 'No virtual-DNS object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_DNS_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'domain_back_refs', u'network_ipam_back_refs'] children = [u'virtual_DNS_records'] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('virtual-DNS', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'virtual_DNS', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'virtual_DNS', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'virtual_DNS', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('virtual-DNS', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('virtual-DNS') if r_class: if read_ok: # fail if non-default children or backrefs exist virtual_DNS_records = read_result.get('virtual_DNS_records', None) if virtual_DNS_records: has_infos = read_result['virtual_DNS_records'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-virtual-DNS-record')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'virtual_DNS', 'http_delete', err_msg) abort(409, err_msg) network_ipam_back_refs = read_result.get('network_ipam_back_refs', None) if network_ipam_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['network_ipam_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_DNS', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._virtual_DNS_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'virtual_DNS', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('virtual-DNS', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'virtual_DNS', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_DNS_delete', id, read_result) except Exception as e: pass #end virtual_DNS_http_delete def virtual_DNSs_http_post(self): key = 'virtual-DNS' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_DNS_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('virtual_DNS_data') if prop_dict: buf = cStringIO.StringIO() xx_virtual_DNS_data = VirtualDnsType(**prop_dict) xx_virtual_DNS_data.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_DNS_data = VirtualDnsType() try: xx_virtual_DNS_data.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'virtual-DNS', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'virtual_DNS', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'virtual_DNS', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = [u'virtual_DNS_record'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('virtual-DNS', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'virtual_DNS', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['virtual_DNS', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('virtual-DNS') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'virtual_DNS', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('virtual-DNS', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'virtual_DNS', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('virtual-DNS', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_DNS_create', obj_dict) except Exception as e: pass return {'virtual-DNS': rsp_body} #end virtual_DNSs_http_post def virtual_DNSs_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'virtual_DNSs', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('virtual-DNS', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'virtual_DNSs', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'virtual-DNSs': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('virtual-DNS', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('virtual-DNS', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('virtual-DNS', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'virtual_DNS_data', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('virtual-DNS', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('virtual-DNS', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'virtual-DNS': obj_dict}) return {'virtual-DNSs': obj_dicts} #end virtual_DNSs_http_get def _virtual_DNS_create_default_children(self, parent_obj): # Create a default child only if provisioned for r_class = self.get_resource_class('virtual-DNS-record') if r_class and r_class.generate_default_instance: child_obj = VirtualDnsRecord(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('virtual-DNS-record') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('virtual-DNS-record', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('virtual-DNS-record', obj_ids, child_dict) self._virtual_DNS_record_create_default_children(child_obj) pass #end _virtual_DNS_create_default_children def _virtual_DNS_delete_default_children(self, parent_dict): # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-DNS-record') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('virtual_DNS_records') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-virtual-DNS-record': default_child_id = has_info['href'].split('/')[-1] self.virtual_DNS_record_http_delete(default_child_id) break pass #end _virtual_DNS_delete_default_children def customer_attachment_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_customer_attachment_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'customer_attachment': abort(404, 'No customer-attachment object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'customer_attachment', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('customer-attachment') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'customer_attachment', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'attachment_address', u'id_perms', u'display_name'] references = ['virtual_machine_interface_refs', u'floating_ip_refs'] back_references = [] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('customer-attachment', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'customer_attachment', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'customer_attachment', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('customer-attachment', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_customer_attachment_read', id, rsp_body) except Exception as e: pass return {'customer-attachment': rsp_body} #end customer_attachment_http_get def customer_attachment_http_put(self, id): key = 'customer-attachment' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_customer_attachment_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'customer_attachment': abort(404, 'No customer-attachment object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('attachment_address') if prop_dict: buf = cStringIO.StringIO() xx_attachment_address = AttachmentAddressType(**prop_dict) xx_attachment_address.export(buf) node = etree.fromstring(buf.getvalue()) xx_attachment_address = AttachmentAddressType() try: xx_attachment_address.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'customer_attachment', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'customer_attachment', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = ['virtual_machine_interface', u'floating_ip', 'routing_instance', 'provider_attachment'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('customer-attachment') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'customer_attachment', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('customer-attachment', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'customer_attachment', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('customer-attachment', id) try: self._extension_mgrs['resourceApi'].map_method('post_customer_attachment_update', id, obj_dict) except Exception as e: pass return {'customer-attachment': rsp_body} #end customer_attachment_http_put def customer_attachment_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'customer_attachment': abort(404, 'No customer-attachment object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_customer_attachment_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('customer-attachment', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'customer_attachment', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'customer_attachment', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'customer_attachment', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('customer-attachment', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('customer-attachment') if r_class: if read_ok: # fail if non-default children or backrefs exist # Delete default children first self._customer_attachment_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'customer_attachment', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('customer-attachment', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'customer_attachment', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_customer_attachment_delete', id, read_result) except Exception as e: pass #end customer_attachment_http_delete def customer_attachments_http_post(self): key = 'customer-attachment' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_customer_attachment_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('attachment_address') if prop_dict: buf = cStringIO.StringIO() xx_attachment_address = AttachmentAddressType(**prop_dict) xx_attachment_address.export(buf) node = etree.fromstring(buf.getvalue()) xx_attachment_address = AttachmentAddressType() try: xx_attachment_address.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'customer-attachment', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'customer_attachment', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # Validate perms objtype_list = ['virtual_machine_interface', u'floating_ip', 'routing_instance', 'provider_attachment'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('customer-attachment', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'customer_attachment', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['customer_attachment', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('customer-attachment') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'customer_attachment', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('customer-attachment', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'customer_attachment', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('customer-attachment', obj_ids['uuid']) try: self._extension_mgrs['resourceApi'].map_method('post_customer_attachment_create', obj_dict) except Exception as e: pass return {'customer-attachment': rsp_body} #end customer_attachments_http_post def customer_attachments_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'customer_attachments', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('customer-attachment', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'customer_attachments', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'customer-attachments': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('customer-attachment', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('customer-attachment', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('customer-attachment', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'attachment_address', u'id_perms', u'display_name'] + ['virtual_machine_interface_refs', u'floating_ip_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('customer-attachment', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('customer-attachment', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'customer-attachment': obj_dict}) return {'customer-attachments': obj_dicts} #end customer_attachments_http_get def _customer_attachment_create_default_children(self, parent_obj): pass #end _customer_attachment_create_default_children def _customer_attachment_delete_default_children(self, parent_dict): pass #end _customer_attachment_delete_default_children def service_appliance_set_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_service_appliance_set_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'service_appliance_set': abort(404, 'No service-appliance-set object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'service_appliance_set', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('service-appliance-set') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'service_appliance_set', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'service_appliance_set_properties', u'service_appliance_driver', u'service_appliance_ha_mode', u'id_perms', u'display_name'] references = [] back_references = [u'global_system_config_back_refs', u'loadbalancer_pool_back_refs'] children = [u'service_appliances'] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('service-appliance-set', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'service_appliance_set', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'service_appliance_set', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('service-appliance-set', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_service_appliance_set_read', id, rsp_body) except Exception as e: pass return {'service-appliance-set': rsp_body} #end service_appliance_set_http_get def service_appliance_set_http_put(self, id): key = 'service-appliance-set' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_service_appliance_set_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'service_appliance_set': abort(404, 'No service-appliance-set object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('service_appliance_set_properties') if prop_dict: buf = cStringIO.StringIO() xx_service_appliance_set_properties = KeyValuePairs(**prop_dict) xx_service_appliance_set_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_service_appliance_set_properties = KeyValuePairs() try: xx_service_appliance_set_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'service_appliance_set', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'service_appliance_set', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = [u'service_appliance'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('service-appliance-set') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'service_appliance_set', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('service-appliance-set', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'service_appliance_set', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('service-appliance-set', id) try: self._extension_mgrs['resourceApi'].map_method('post_service_appliance_set_update', id, obj_dict) except Exception as e: pass return {'service-appliance-set': rsp_body} #end service_appliance_set_http_put def service_appliance_set_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'service_appliance_set': abort(404, 'No service-appliance-set object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_service_appliance_set_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'global_system_config_back_refs', u'loadbalancer_pool_back_refs'] children = [u'service_appliances'] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('service-appliance-set', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'service_appliance_set', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'service_appliance_set', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'service_appliance_set', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('service-appliance-set', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('service-appliance-set') if r_class: if read_ok: # fail if non-default children or backrefs exist service_appliances = read_result.get('service_appliances', None) if service_appliances: has_infos = read_result['service_appliances'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-service-appliance')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'service_appliance_set', 'http_delete', err_msg) abort(409, err_msg) loadbalancer_pool_back_refs = read_result.get('loadbalancer_pool_back_refs', None) if loadbalancer_pool_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['loadbalancer_pool_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'service_appliance_set', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._service_appliance_set_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'service_appliance_set', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('service-appliance-set', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'service_appliance_set', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_service_appliance_set_delete', id, read_result) except Exception as e: pass #end service_appliance_set_http_delete def service_appliance_sets_http_post(self): key = 'service-appliance-set' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_service_appliance_set_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('service_appliance_set_properties') if prop_dict: buf = cStringIO.StringIO() xx_service_appliance_set_properties = KeyValuePairs(**prop_dict) xx_service_appliance_set_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_service_appliance_set_properties = KeyValuePairs() try: xx_service_appliance_set_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'service-appliance-set', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'service_appliance_set', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'service_appliance_set', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = [u'service_appliance'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('service-appliance-set', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'service_appliance_set', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['service_appliance_set', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('service-appliance-set') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'service_appliance_set', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('service-appliance-set', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'service_appliance_set', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('service-appliance-set', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_service_appliance_set_create', obj_dict) except Exception as e: pass return {'service-appliance-set': rsp_body} #end service_appliance_sets_http_post def service_appliance_sets_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'service_appliance_sets', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('service-appliance-set', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'service_appliance_sets', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'service-appliance-sets': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('service-appliance-set', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('service-appliance-set', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('service-appliance-set', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'service_appliance_set_properties', u'service_appliance_driver', u'service_appliance_ha_mode', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('service-appliance-set', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('service-appliance-set', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'service-appliance-set': obj_dict}) return {'service-appliance-sets': obj_dicts} #end service_appliance_sets_http_get def _service_appliance_set_create_default_children(self, parent_obj): # Create a default child only if provisioned for r_class = self.get_resource_class('service-appliance') if r_class and r_class.generate_default_instance: child_obj = ServiceAppliance(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('service-appliance') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('service-appliance', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('service-appliance', obj_ids, child_dict) self._service_appliance_create_default_children(child_obj) pass #end _service_appliance_set_create_default_children def _service_appliance_set_delete_default_children(self, parent_dict): # Delete a default child only if provisioned for r_class = self.get_resource_class('service-appliance') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('service_appliances') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-service-appliance': default_child_id = has_info['href'].split('/')[-1] self.service_appliance_http_delete(default_child_id) break pass #end _service_appliance_set_delete_default_children def config_node_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_config_node_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'config_node': abort(404, 'No config-node object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'config_node', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('config-node') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'config_node', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'config_node_ip_address', u'id_perms', u'display_name'] references = [] back_references = [u'global_system_config_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('config-node', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'config_node', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'config_node', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('config-node', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_config_node_read', id, rsp_body) except Exception as e: pass return {'config-node': rsp_body} #end config_node_http_get def config_node_http_put(self, id): key = 'config-node' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_config_node_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'config_node': abort(404, 'No config-node object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'config_node', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'config_node', 'http_put', msg) abort(code, msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('config-node') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'config_node', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('config-node', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'config_node', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('config-node', id) try: self._extension_mgrs['resourceApi'].map_method('post_config_node_update', id, obj_dict) except Exception as e: pass return {'config-node': rsp_body} #end config_node_http_put def config_node_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'config_node': abort(404, 'No config-node object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_config_node_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'global_system_config_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('config-node', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'config_node', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'config_node', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'config_node', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('config-node', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('config-node') if r_class: if read_ok: # fail if non-default children or backrefs exist # Delete default children first self._config_node_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'config_node', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('config-node', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'config_node', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_config_node_delete', id, read_result) except Exception as e: pass #end config_node_http_delete def config_nodes_http_post(self): key = 'config-node' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_config_node_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'config-node', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'config_node', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'config_node', 'http_post', err_msg) abort(400, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('config-node', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'config_node', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['config_node', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('config-node') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'config_node', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('config-node', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'config_node', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('config-node', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_config_node_create', obj_dict) except Exception as e: pass return {'config-node': rsp_body} #end config_nodes_http_post def config_nodes_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'config_nodes', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('config-node', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'config_nodes', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'config-nodes': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('config-node', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('config-node', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('config-node', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'config_node_ip_address', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('config-node', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('config-node', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'config-node': obj_dict}) return {'config-nodes': obj_dicts} #end config_nodes_http_get def _config_node_create_default_children(self, parent_obj): pass #end _config_node_create_default_children def _config_node_delete_default_children(self, parent_dict): pass #end _config_node_delete_default_children def qos_queue_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_qos_queue_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'qos_queue': abort(404, 'No qos-queue object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'qos_queue', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('qos-queue') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'qos_queue', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'min_bandwidth', u'max_bandwidth', u'id_perms', u'display_name'] references = [] back_references = [u'project_back_refs', u'qos_forwarding_class_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('qos-queue', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'qos_queue', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'qos_queue', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('qos-queue', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_qos_queue_read', id, rsp_body) except Exception as e: pass return {'qos-queue': rsp_body} #end qos_queue_http_get def qos_queue_http_put(self, id): key = 'qos-queue' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_qos_queue_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'qos_queue': abort(404, 'No qos-queue object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'qos_queue', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'qos_queue', 'http_put', msg) abort(code, msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('qos-queue') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'qos_queue', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('qos-queue', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'qos_queue', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('qos-queue', id) try: self._extension_mgrs['resourceApi'].map_method('post_qos_queue_update', id, obj_dict) except Exception as e: pass return {'qos-queue': rsp_body} #end qos_queue_http_put def qos_queue_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'qos_queue': abort(404, 'No qos-queue object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_qos_queue_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'project_back_refs', u'qos_forwarding_class_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('qos-queue', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'qos_queue', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'qos_queue', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'qos_queue', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('qos-queue', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('qos-queue') if r_class: if read_ok: # fail if non-default children or backrefs exist qos_forwarding_class_back_refs = read_result.get('qos_forwarding_class_back_refs', None) if qos_forwarding_class_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['qos_forwarding_class_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'qos_queue', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._qos_queue_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'qos_queue', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('qos-queue', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'qos_queue', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_qos_queue_delete', id, read_result) except Exception as e: pass #end qos_queue_http_delete def qos_queues_http_post(self): key = 'qos-queue' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_qos_queue_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'qos-queue', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'qos_queue', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'qos_queue', 'http_post', err_msg) abort(400, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('qos-queue', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'qos_queue', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['qos_queue', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('qos-queue') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'qos_queue', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('qos-queue', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'qos_queue', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('qos-queue', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_qos_queue_create', obj_dict) except Exception as e: pass return {'qos-queue': rsp_body} #end qos_queues_http_post def qos_queues_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'qos_queues', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('qos-queue', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'qos_queues', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'qos-queues': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('qos-queue', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('qos-queue', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('qos-queue', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'min_bandwidth', u'max_bandwidth', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('qos-queue', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('qos-queue', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'qos-queue': obj_dict}) return {'qos-queues': obj_dicts} #end qos_queues_http_get def _qos_queue_create_default_children(self, parent_obj): pass #end _qos_queue_create_default_children def _qos_queue_delete_default_children(self, parent_dict): pass #end _qos_queue_delete_default_children def virtual_machine_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_machine_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'virtual_machine': abort(404, 'No virtual-machine object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'virtual_machine', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('virtual-machine') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'virtual_machine', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'id_perms', u'display_name'] references = [u'service_instance_refs'] back_references = ['virtual_machine_interface_back_refs', 'virtual_router_back_refs'] children = ['virtual_machine_interfaces'] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('virtual-machine', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'virtual_machine', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'virtual_machine', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('virtual-machine', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_virtual_machine_read', id, rsp_body) except Exception as e: pass return {'virtual-machine': rsp_body} #end virtual_machine_http_get def virtual_machine_http_put(self, id): key = 'virtual-machine' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_machine_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'virtual_machine': abort(404, 'No virtual-machine object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'virtual_machine', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'virtual_machine', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = ['virtual_machine_interface', u'service_instance'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('virtual-machine') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'virtual_machine', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('virtual-machine', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'virtual_machine', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('virtual-machine', id) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_machine_update', id, obj_dict) except Exception as e: pass return {'virtual-machine': rsp_body} #end virtual_machine_http_put def virtual_machine_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'virtual_machine': abort(404, 'No virtual-machine object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_machine_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = ['virtual_machine_interface_back_refs', 'virtual_router_back_refs'] children = ['virtual_machine_interfaces'] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('virtual-machine', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'virtual_machine', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'virtual_machine', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'virtual_machine', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('virtual-machine', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('virtual-machine') if r_class: if read_ok: # fail if non-default children or backrefs exist virtual_machine_interfaces = read_result.get('virtual_machine_interfaces', None) if virtual_machine_interfaces: has_infos = read_result['virtual_machine_interfaces'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-virtual-machine-interface')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'virtual_machine', 'http_delete', err_msg) abort(409, err_msg) virtual_machine_interface_back_refs = read_result.get('virtual_machine_interface_back_refs', None) if virtual_machine_interface_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['virtual_machine_interface_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_machine', 'http_delete', err_msg) abort(409, err_msg) virtual_router_back_refs = read_result.get('virtual_router_back_refs', None) if virtual_router_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['virtual_router_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_machine', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._virtual_machine_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'virtual_machine', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('virtual-machine', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'virtual_machine', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_machine_delete', id, read_result) except Exception as e: pass #end virtual_machine_http_delete def virtual_machines_http_post(self): key = 'virtual-machine' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_machine_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'virtual-machine', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'virtual_machine', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # Validate perms objtype_list = ['virtual_machine_interface', u'service_instance'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('virtual-machine', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'virtual_machine', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['virtual_machine', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('virtual-machine') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'virtual_machine', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('virtual-machine', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'virtual_machine', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('virtual-machine', obj_ids['uuid']) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_machine_create', obj_dict) except Exception as e: pass return {'virtual-machine': rsp_body} #end virtual_machines_http_post def virtual_machines_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'virtual_machines', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('virtual-machine', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'virtual_machines', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'virtual-machines': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('virtual-machine', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('virtual-machine', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('virtual-machine', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms', u'display_name'] + [u'service_instance_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('virtual-machine', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('virtual-machine', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'virtual-machine': obj_dict}) return {'virtual-machines': obj_dicts} #end virtual_machines_http_get def _virtual_machine_create_default_children(self, parent_obj): # Create a default child only if provisioned for r_class = self.get_resource_class('virtual-machine-interface') if r_class and r_class.generate_default_instance: child_obj = VirtualMachineInterface(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('virtual-machine-interface') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('virtual-machine-interface', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('virtual-machine-interface', obj_ids, child_dict) self._virtual_machine_interface_create_default_children(child_obj) pass #end _virtual_machine_create_default_children def _virtual_machine_delete_default_children(self, parent_dict): # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-machine-interface') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('virtual_machine_interfaces') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-virtual-machine-interface': default_child_id = has_info['href'].split('/')[-1] self.virtual_machine_interface_http_delete(default_child_id) break pass #end _virtual_machine_delete_default_children def interface_route_table_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_interface_route_table_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'interface_route_table': abort(404, 'No interface-route-table object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'interface_route_table', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('interface-route-table') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'interface_route_table', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'interface_route_table_routes', u'id_perms', u'display_name'] references = [] back_references = [u'project_back_refs', 'virtual_machine_interface_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('interface-route-table', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'interface_route_table', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'interface_route_table', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('interface-route-table', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_interface_route_table_read', id, rsp_body) except Exception as e: pass return {'interface-route-table': rsp_body} #end interface_route_table_http_get def interface_route_table_http_put(self, id): key = 'interface-route-table' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_interface_route_table_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'interface_route_table': abort(404, 'No interface-route-table object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('interface_route_table_routes') if prop_dict: buf = cStringIO.StringIO() xx_interface_route_table_routes = RouteTableType(**prop_dict) xx_interface_route_table_routes.export(buf) node = etree.fromstring(buf.getvalue()) xx_interface_route_table_routes = RouteTableType() try: xx_interface_route_table_routes.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'interface_route_table', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'interface_route_table', 'http_put', msg) abort(code, msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('interface-route-table') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'interface_route_table', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('interface-route-table', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'interface_route_table', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('interface-route-table', id) try: self._extension_mgrs['resourceApi'].map_method('post_interface_route_table_update', id, obj_dict) except Exception as e: pass return {'interface-route-table': rsp_body} #end interface_route_table_http_put def interface_route_table_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'interface_route_table': abort(404, 'No interface-route-table object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_interface_route_table_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'project_back_refs', 'virtual_machine_interface_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('interface-route-table', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'interface_route_table', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'interface_route_table', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'interface_route_table', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('interface-route-table', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('interface-route-table') if r_class: if read_ok: # fail if non-default children or backrefs exist virtual_machine_interface_back_refs = read_result.get('virtual_machine_interface_back_refs', None) if virtual_machine_interface_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['virtual_machine_interface_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'interface_route_table', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._interface_route_table_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'interface_route_table', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('interface-route-table', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'interface_route_table', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_interface_route_table_delete', id, read_result) except Exception as e: pass #end interface_route_table_http_delete def interface_route_tables_http_post(self): key = 'interface-route-table' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_interface_route_table_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('interface_route_table_routes') if prop_dict: buf = cStringIO.StringIO() xx_interface_route_table_routes = RouteTableType(**prop_dict) xx_interface_route_table_routes.export(buf) node = etree.fromstring(buf.getvalue()) xx_interface_route_table_routes = RouteTableType() try: xx_interface_route_table_routes.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'interface-route-table', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'interface_route_table', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'interface_route_table', 'http_post', err_msg) abort(400, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('interface-route-table', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'interface_route_table', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['interface_route_table', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('interface-route-table') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'interface_route_table', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('interface-route-table', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'interface_route_table', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('interface-route-table', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_interface_route_table_create', obj_dict) except Exception as e: pass return {'interface-route-table': rsp_body} #end interface_route_tables_http_post def interface_route_tables_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'interface_route_tables', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('interface-route-table', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'interface_route_tables', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'interface-route-tables': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('interface-route-table', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('interface-route-table', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('interface-route-table', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'interface_route_table_routes', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('interface-route-table', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('interface-route-table', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'interface-route-table': obj_dict}) return {'interface-route-tables': obj_dicts} #end interface_route_tables_http_get def _interface_route_table_create_default_children(self, parent_obj): pass #end _interface_route_table_create_default_children def _interface_route_table_delete_default_children(self, parent_dict): pass #end _interface_route_table_delete_default_children def service_template_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_service_template_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'service_template': abort(404, 'No service-template object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'service_template', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('service-template') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'service_template', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'service_template_properties', u'id_perms', u'display_name'] references = [] back_references = [u'domain_back_refs', u'service_instance_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('service-template', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'service_template', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'service_template', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('service-template', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_service_template_read', id, rsp_body) except Exception as e: pass return {'service-template': rsp_body} #end service_template_http_get def service_template_http_put(self, id): key = 'service-template' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_service_template_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'service_template': abort(404, 'No service-template object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('service_template_properties') if prop_dict: buf = cStringIO.StringIO() xx_service_template_properties = ServiceTemplateType(**prop_dict) xx_service_template_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_service_template_properties = ServiceTemplateType() try: xx_service_template_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'service_template', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'service_template', 'http_put', msg) abort(code, msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('service-template') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'service_template', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('service-template', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'service_template', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('service-template', id) try: self._extension_mgrs['resourceApi'].map_method('post_service_template_update', id, obj_dict) except Exception as e: pass return {'service-template': rsp_body} #end service_template_http_put def service_template_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'service_template': abort(404, 'No service-template object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_service_template_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'domain_back_refs', u'service_instance_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('service-template', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'service_template', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'service_template', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'service_template', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('service-template', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('service-template') if r_class: if read_ok: # fail if non-default children or backrefs exist service_instance_back_refs = read_result.get('service_instance_back_refs', None) if service_instance_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['service_instance_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'service_template', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._service_template_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'service_template', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('service-template', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'service_template', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_service_template_delete', id, read_result) except Exception as e: pass #end service_template_http_delete def service_templates_http_post(self): key = 'service-template' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_service_template_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('service_template_properties') if prop_dict: buf = cStringIO.StringIO() xx_service_template_properties = ServiceTemplateType(**prop_dict) xx_service_template_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_service_template_properties = ServiceTemplateType() try: xx_service_template_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'service-template', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'service_template', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'service_template', 'http_post', err_msg) abort(400, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('service-template', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'service_template', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['service_template', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('service-template') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'service_template', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('service-template', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'service_template', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('service-template', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_service_template_create', obj_dict) except Exception as e: pass return {'service-template': rsp_body} #end service_templates_http_post def service_templates_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'service_templates', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('service-template', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'service_templates', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'service-templates': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('service-template', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('service-template', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('service-template', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'service_template_properties', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('service-template', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('service-template', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'service-template': obj_dict}) return {'service-templates': obj_dicts} #end service_templates_http_get def _service_template_create_default_children(self, parent_obj): pass #end _service_template_create_default_children def _service_template_delete_default_children(self, parent_dict): pass #end _service_template_delete_default_children def virtual_ip_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_ip_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'virtual_ip': abort(404, 'No virtual-ip object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'virtual_ip', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('virtual-ip') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'virtual_ip', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'virtual_ip_properties', u'id_perms', u'display_name'] references = [u'loadbalancer_pool_refs', 'virtual_machine_interface_refs'] back_references = [u'project_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('virtual-ip', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'virtual_ip', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'virtual_ip', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('virtual-ip', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_virtual_ip_read', id, rsp_body) except Exception as e: pass return {'virtual-ip': rsp_body} #end virtual_ip_http_get def virtual_ip_http_put(self, id): key = 'virtual-ip' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_ip_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'virtual_ip': abort(404, 'No virtual-ip object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('virtual_ip_properties') if prop_dict: buf = cStringIO.StringIO() xx_virtual_ip_properties = VirtualIpType(**prop_dict) xx_virtual_ip_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_ip_properties = VirtualIpType() try: xx_virtual_ip_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'virtual_ip', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'virtual_ip', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = [u'loadbalancer_pool', 'virtual_machine_interface'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('virtual-ip') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'virtual_ip', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('virtual-ip', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'virtual_ip', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('virtual-ip', id) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_ip_update', id, obj_dict) except Exception as e: pass return {'virtual-ip': rsp_body} #end virtual_ip_http_put def virtual_ip_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'virtual_ip': abort(404, 'No virtual-ip object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_ip_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'project_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('virtual-ip', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'virtual_ip', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'virtual_ip', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'virtual_ip', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('virtual-ip', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('virtual-ip') if r_class: if read_ok: # fail if non-default children or backrefs exist # Delete default children first self._virtual_ip_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'virtual_ip', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('virtual-ip', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'virtual_ip', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_ip_delete', id, read_result) except Exception as e: pass #end virtual_ip_http_delete def virtual_ips_http_post(self): key = 'virtual-ip' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_ip_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('virtual_ip_properties') if prop_dict: buf = cStringIO.StringIO() xx_virtual_ip_properties = VirtualIpType(**prop_dict) xx_virtual_ip_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_ip_properties = VirtualIpType() try: xx_virtual_ip_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'virtual-ip', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'virtual_ip', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'virtual_ip', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = [u'loadbalancer_pool', 'virtual_machine_interface'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('virtual-ip', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'virtual_ip', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['virtual_ip', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('virtual-ip') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'virtual_ip', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('virtual-ip', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'virtual_ip', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('virtual-ip', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_ip_create', obj_dict) except Exception as e: pass return {'virtual-ip': rsp_body} #end virtual_ips_http_post def virtual_ips_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'virtual_ips', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('virtual-ip', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'virtual_ips', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'virtual-ips': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('virtual-ip', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('virtual-ip', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('virtual-ip', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'virtual_ip_properties', u'id_perms', u'display_name'] + [u'loadbalancer_pool_refs', 'virtual_machine_interface_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('virtual-ip', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('virtual-ip', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'virtual-ip': obj_dict}) return {'virtual-ips': obj_dicts} #end virtual_ips_http_get def _virtual_ip_create_default_children(self, parent_obj): pass #end _virtual_ip_create_default_children def _virtual_ip_delete_default_children(self, parent_dict): pass #end _virtual_ip_delete_default_children def loadbalancer_member_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_loadbalancer_member_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'loadbalancer_member': abort(404, 'No loadbalancer-member object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'loadbalancer_member', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('loadbalancer-member') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'loadbalancer_member', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'loadbalancer_member_properties', u'id_perms', u'display_name'] references = [] back_references = [u'loadbalancer_pool_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('loadbalancer-member', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'loadbalancer_member', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'loadbalancer_member', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('loadbalancer-member', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_loadbalancer_member_read', id, rsp_body) except Exception as e: pass return {'loadbalancer-member': rsp_body} #end loadbalancer_member_http_get def loadbalancer_member_http_put(self, id): key = 'loadbalancer-member' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_loadbalancer_member_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'loadbalancer_member': abort(404, 'No loadbalancer-member object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('loadbalancer_member_properties') if prop_dict: buf = cStringIO.StringIO() xx_loadbalancer_member_properties = LoadbalancerMemberType(**prop_dict) xx_loadbalancer_member_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_loadbalancer_member_properties = LoadbalancerMemberType() try: xx_loadbalancer_member_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'loadbalancer_member', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'loadbalancer_member', 'http_put', msg) abort(code, msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('loadbalancer-member') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'loadbalancer_member', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('loadbalancer-member', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'loadbalancer_member', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('loadbalancer-member', id) try: self._extension_mgrs['resourceApi'].map_method('post_loadbalancer_member_update', id, obj_dict) except Exception as e: pass return {'loadbalancer-member': rsp_body} #end loadbalancer_member_http_put def loadbalancer_member_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'loadbalancer_member': abort(404, 'No loadbalancer-member object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_loadbalancer_member_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'loadbalancer_pool_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('loadbalancer-member', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'loadbalancer_member', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'loadbalancer_member', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'loadbalancer_member', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('loadbalancer-member', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('loadbalancer-member') if r_class: if read_ok: # fail if non-default children or backrefs exist # Delete default children first self._loadbalancer_member_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'loadbalancer_member', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('loadbalancer-member', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'loadbalancer_member', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_loadbalancer_member_delete', id, read_result) except Exception as e: pass #end loadbalancer_member_http_delete def loadbalancer_members_http_post(self): key = 'loadbalancer-member' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_loadbalancer_member_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('loadbalancer_member_properties') if prop_dict: buf = cStringIO.StringIO() xx_loadbalancer_member_properties = LoadbalancerMemberType(**prop_dict) xx_loadbalancer_member_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_loadbalancer_member_properties = LoadbalancerMemberType() try: xx_loadbalancer_member_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'loadbalancer-member', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'loadbalancer_member', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'loadbalancer_member', 'http_post', err_msg) abort(400, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('loadbalancer-member', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'loadbalancer_member', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['loadbalancer_member', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('loadbalancer-member') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'loadbalancer_member', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('loadbalancer-member', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'loadbalancer_member', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('loadbalancer-member', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_loadbalancer_member_create', obj_dict) except Exception as e: pass return {'loadbalancer-member': rsp_body} #end loadbalancer_members_http_post def loadbalancer_members_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'loadbalancer_members', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('loadbalancer-member', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'loadbalancer_members', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'loadbalancer-members': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('loadbalancer-member', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('loadbalancer-member', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('loadbalancer-member', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'loadbalancer_member_properties', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('loadbalancer-member', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('loadbalancer-member', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'loadbalancer-member': obj_dict}) return {'loadbalancer-members': obj_dicts} #end loadbalancer_members_http_get def _loadbalancer_member_create_default_children(self, parent_obj): pass #end _loadbalancer_member_create_default_children def _loadbalancer_member_delete_default_children(self, parent_dict): pass #end _loadbalancer_member_delete_default_children def security_group_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_security_group_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'security_group': abort(404, 'No security-group object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'security_group', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('security-group') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'security_group', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'security_group_id', u'configured_security_group_id', u'security_group_entries', u'id_perms', u'display_name'] references = [] back_references = [u'project_back_refs', 'virtual_machine_interface_back_refs'] children = [u'access_control_lists'] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('security-group', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'security_group', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'security_group', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('security-group', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_security_group_read', id, rsp_body) except Exception as e: pass return {'security-group': rsp_body} #end security_group_http_get def security_group_http_put(self, id): key = 'security-group' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_security_group_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'security_group': abort(404, 'No security-group object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('security_group_entries') if prop_dict: buf = cStringIO.StringIO() xx_security_group_entries = PolicyEntriesType(**prop_dict) xx_security_group_entries.export(buf) node = etree.fromstring(buf.getvalue()) xx_security_group_entries = PolicyEntriesType() try: xx_security_group_entries.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'security_group', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'security_group', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = [u'access_control_list'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('security-group') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'security_group', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('security-group', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'security_group', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('security-group', id) try: self._extension_mgrs['resourceApi'].map_method('post_security_group_update', id, obj_dict) except Exception as e: pass return {'security-group': rsp_body} #end security_group_http_put def security_group_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'security_group': abort(404, 'No security-group object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_security_group_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'project_back_refs', 'virtual_machine_interface_back_refs'] children = [u'access_control_lists'] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('security-group', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'security_group', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'security_group', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'security_group', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('security-group', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('security-group') if r_class: if read_ok: # fail if non-default children or backrefs exist virtual_machine_interface_back_refs = read_result.get('virtual_machine_interface_back_refs', None) if virtual_machine_interface_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['virtual_machine_interface_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'security_group', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._security_group_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'security_group', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('security-group', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'security_group', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_security_group_delete', id, read_result) except Exception as e: pass #end security_group_http_delete def security_groups_http_post(self): key = 'security-group' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_security_group_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('security_group_entries') if prop_dict: buf = cStringIO.StringIO() xx_security_group_entries = PolicyEntriesType(**prop_dict) xx_security_group_entries.export(buf) node = etree.fromstring(buf.getvalue()) xx_security_group_entries = PolicyEntriesType() try: xx_security_group_entries.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'security-group', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'security_group', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'security_group', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = [u'access_control_list'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('security-group', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'security_group', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['security_group', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('security-group') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'security_group', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('security-group', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'security_group', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('security-group', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_security_group_create', obj_dict) except Exception as e: pass return {'security-group': rsp_body} #end security_groups_http_post def security_groups_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'security_groups', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('security-group', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'security_groups', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'security-groups': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('security-group', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('security-group', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('security-group', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'security_group_id', u'configured_security_group_id', u'security_group_entries', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('security-group', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('security-group', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'security-group': obj_dict}) return {'security-groups': obj_dicts} #end security_groups_http_get def _security_group_create_default_children(self, parent_obj): pass #end _security_group_create_default_children def _security_group_delete_default_children(self, parent_dict): # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-machine-interface') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('access_control_lists') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-access-control-list': default_child_id = has_info['href'].split('/')[-1] self.access_control_list_http_delete(default_child_id) break pass #end _security_group_delete_default_children def provider_attachment_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_provider_attachment_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'provider_attachment': abort(404, 'No provider-attachment object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'provider_attachment', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('provider-attachment') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'provider_attachment', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'id_perms', u'display_name'] references = ['virtual_router_refs'] back_references = ['customer_attachment_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('provider-attachment', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'provider_attachment', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'provider_attachment', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('provider-attachment', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_provider_attachment_read', id, rsp_body) except Exception as e: pass return {'provider-attachment': rsp_body} #end provider_attachment_http_get def provider_attachment_http_put(self, id): key = 'provider-attachment' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_provider_attachment_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'provider_attachment': abort(404, 'No provider-attachment object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'provider_attachment', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'provider_attachment', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = ['virtual_router'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('provider-attachment') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'provider_attachment', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('provider-attachment', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'provider_attachment', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('provider-attachment', id) try: self._extension_mgrs['resourceApi'].map_method('post_provider_attachment_update', id, obj_dict) except Exception as e: pass return {'provider-attachment': rsp_body} #end provider_attachment_http_put def provider_attachment_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'provider_attachment': abort(404, 'No provider-attachment object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_provider_attachment_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = ['customer_attachment_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('provider-attachment', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'provider_attachment', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'provider_attachment', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'provider_attachment', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('provider-attachment', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('provider-attachment') if r_class: if read_ok: # fail if non-default children or backrefs exist # Delete default children first self._provider_attachment_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'provider_attachment', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('provider-attachment', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'provider_attachment', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_provider_attachment_delete', id, read_result) except Exception as e: pass #end provider_attachment_http_delete def provider_attachments_http_post(self): key = 'provider-attachment' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_provider_attachment_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'provider-attachment', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'provider_attachment', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # Validate perms objtype_list = ['virtual_router'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('provider-attachment', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'provider_attachment', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['provider_attachment', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('provider-attachment') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'provider_attachment', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('provider-attachment', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'provider_attachment', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('provider-attachment', obj_ids['uuid']) try: self._extension_mgrs['resourceApi'].map_method('post_provider_attachment_create', obj_dict) except Exception as e: pass return {'provider-attachment': rsp_body} #end provider_attachments_http_post def provider_attachments_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'provider_attachments', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('provider-attachment', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'provider_attachments', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'provider-attachments': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('provider-attachment', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('provider-attachment', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('provider-attachment', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms', u'display_name'] + ['virtual_router_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('provider-attachment', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('provider-attachment', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'provider-attachment': obj_dict}) return {'provider-attachments': obj_dicts} #end provider_attachments_http_get def _provider_attachment_create_default_children(self, parent_obj): pass #end _provider_attachment_create_default_children def _provider_attachment_delete_default_children(self, parent_dict): pass #end _provider_attachment_delete_default_children def virtual_machine_interface_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_machine_interface_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'virtual_machine_interface': abort(404, 'No virtual-machine-interface object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'virtual_machine_interface', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('virtual-machine-interface') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'virtual_machine_interface', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'virtual_machine_interface_mac_addresses', u'virtual_machine_interface_dhcp_option_list', u'virtual_machine_interface_host_routes', u'virtual_machine_interface_allowed_address_pairs', u'vrf_assign_table', u'virtual_machine_interface_device_owner', u'virtual_machine_interface_properties', u'id_perms', u'display_name'] references = [u'qos_forwarding_class_refs', u'security_group_refs', 'virtual_machine_interface_refs', u'virtual_machine_refs', u'virtual_network_refs', 'routing_instance_refs', u'interface_route_table_refs'] back_references = ['virtual_machine_interface_back_refs', u'virtual_machine_back_refs', u'project_back_refs', u'instance_ip_back_refs', u'subnet_back_refs', u'floating_ip_back_refs', u'logical_interface_back_refs', 'customer_attachment_back_refs', u'logical_router_back_refs', u'loadbalancer_pool_back_refs', u'virtual_ip_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('virtual-machine-interface', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'virtual_machine_interface', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'virtual_machine_interface', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('virtual-machine-interface', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_virtual_machine_interface_read', id, rsp_body) except Exception as e: pass return {'virtual-machine-interface': rsp_body} #end virtual_machine_interface_http_get def virtual_machine_interface_http_put(self, id): key = 'virtual-machine-interface' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_machine_interface_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'virtual_machine_interface': abort(404, 'No virtual-machine-interface object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('virtual_machine_interface_mac_addresses') if prop_dict: buf = cStringIO.StringIO() xx_virtual_machine_interface_mac_addresses = MacAddressesType(**prop_dict) xx_virtual_machine_interface_mac_addresses.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_machine_interface_mac_addresses = MacAddressesType() try: xx_virtual_machine_interface_mac_addresses.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('virtual_machine_interface_dhcp_option_list') if prop_dict: buf = cStringIO.StringIO() xx_virtual_machine_interface_dhcp_option_list = DhcpOptionsListType(**prop_dict) xx_virtual_machine_interface_dhcp_option_list.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_machine_interface_dhcp_option_list = DhcpOptionsListType() try: xx_virtual_machine_interface_dhcp_option_list.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('virtual_machine_interface_host_routes') if prop_dict: buf = cStringIO.StringIO() xx_virtual_machine_interface_host_routes = RouteTableType(**prop_dict) xx_virtual_machine_interface_host_routes.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_machine_interface_host_routes = RouteTableType() try: xx_virtual_machine_interface_host_routes.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('virtual_machine_interface_allowed_address_pairs') if prop_dict: buf = cStringIO.StringIO() xx_virtual_machine_interface_allowed_address_pairs = AllowedAddressPairs(**prop_dict) xx_virtual_machine_interface_allowed_address_pairs.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_machine_interface_allowed_address_pairs = AllowedAddressPairs() try: xx_virtual_machine_interface_allowed_address_pairs.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('vrf_assign_table') if prop_dict: buf = cStringIO.StringIO() xx_vrf_assign_table = VrfAssignTableType(**prop_dict) xx_vrf_assign_table.export(buf) node = etree.fromstring(buf.getvalue()) xx_vrf_assign_table = VrfAssignTableType() try: xx_vrf_assign_table.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('virtual_machine_interface_properties') if prop_dict: buf = cStringIO.StringIO() xx_virtual_machine_interface_properties = VirtualMachineInterfacePropertiesType(**prop_dict) xx_virtual_machine_interface_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_machine_interface_properties = VirtualMachineInterfacePropertiesType() try: xx_virtual_machine_interface_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) for ref_dict in obj_dict.get('routing_instance_refs') or []: buf = cStringIO.StringIO() xx_routing_instance = PolicyBasedForwardingRuleType(**ref_dict['attr']) xx_routing_instance.export(buf) node = etree.fromstring(buf.getvalue()) try: xx_routing_instance.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'virtual_machine_interface', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'virtual_machine_interface', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = [u'qos_forwarding_class', u'security_group', 'virtual_machine_interface', u'virtual_machine', u'virtual_network', 'routing_instance', u'interface_route_table'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('virtual-machine-interface') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'virtual_machine_interface', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('virtual-machine-interface', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'virtual_machine_interface', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('virtual-machine-interface', id) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_machine_interface_update', id, obj_dict) except Exception as e: pass return {'virtual-machine-interface': rsp_body} #end virtual_machine_interface_http_put def virtual_machine_interface_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'virtual_machine_interface': abort(404, 'No virtual-machine-interface object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_machine_interface_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = ['virtual_machine_interface_back_refs', u'virtual_machine_back_refs', u'project_back_refs', u'instance_ip_back_refs', u'subnet_back_refs', u'floating_ip_back_refs', u'logical_interface_back_refs', 'customer_attachment_back_refs', u'logical_router_back_refs', u'loadbalancer_pool_back_refs', u'virtual_ip_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('virtual-machine-interface', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'virtual_machine_interface', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'virtual_machine_interface', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'virtual_machine_interface', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('virtual-machine-interface', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('virtual-machine-interface') if r_class: if read_ok: # fail if non-default children or backrefs exist virtual_machine_interface_back_refs = read_result.get('virtual_machine_interface_back_refs', None) if virtual_machine_interface_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['virtual_machine_interface_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_machine_interface', 'http_delete', err_msg) abort(409, err_msg) instance_ip_back_refs = read_result.get('instance_ip_back_refs', None) if instance_ip_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['instance_ip_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_machine_interface', 'http_delete', err_msg) abort(409, err_msg) subnet_back_refs = read_result.get('subnet_back_refs', None) if subnet_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['subnet_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_machine_interface', 'http_delete', err_msg) abort(409, err_msg) floating_ip_back_refs = read_result.get('floating_ip_back_refs', None) if floating_ip_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['floating_ip_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_machine_interface', 'http_delete', err_msg) abort(409, err_msg) logical_interface_back_refs = read_result.get('logical_interface_back_refs', None) if logical_interface_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['logical_interface_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_machine_interface', 'http_delete', err_msg) abort(409, err_msg) customer_attachment_back_refs = read_result.get('customer_attachment_back_refs', None) if customer_attachment_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['customer_attachment_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_machine_interface', 'http_delete', err_msg) abort(409, err_msg) logical_router_back_refs = read_result.get('logical_router_back_refs', None) if logical_router_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['logical_router_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_machine_interface', 'http_delete', err_msg) abort(409, err_msg) loadbalancer_pool_back_refs = read_result.get('loadbalancer_pool_back_refs', None) if loadbalancer_pool_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['loadbalancer_pool_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_machine_interface', 'http_delete', err_msg) abort(409, err_msg) virtual_ip_back_refs = read_result.get('virtual_ip_back_refs', None) if virtual_ip_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['virtual_ip_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_machine_interface', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._virtual_machine_interface_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'virtual_machine_interface', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('virtual-machine-interface', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'virtual_machine_interface', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_machine_interface_delete', id, read_result) except Exception as e: pass #end virtual_machine_interface_http_delete def virtual_machine_interfaces_http_post(self): key = 'virtual-machine-interface' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_machine_interface_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('virtual_machine_interface_mac_addresses') if prop_dict: buf = cStringIO.StringIO() xx_virtual_machine_interface_mac_addresses = MacAddressesType(**prop_dict) xx_virtual_machine_interface_mac_addresses.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_machine_interface_mac_addresses = MacAddressesType() try: xx_virtual_machine_interface_mac_addresses.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('virtual_machine_interface_dhcp_option_list') if prop_dict: buf = cStringIO.StringIO() xx_virtual_machine_interface_dhcp_option_list = DhcpOptionsListType(**prop_dict) xx_virtual_machine_interface_dhcp_option_list.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_machine_interface_dhcp_option_list = DhcpOptionsListType() try: xx_virtual_machine_interface_dhcp_option_list.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('virtual_machine_interface_host_routes') if prop_dict: buf = cStringIO.StringIO() xx_virtual_machine_interface_host_routes = RouteTableType(**prop_dict) xx_virtual_machine_interface_host_routes.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_machine_interface_host_routes = RouteTableType() try: xx_virtual_machine_interface_host_routes.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('virtual_machine_interface_allowed_address_pairs') if prop_dict: buf = cStringIO.StringIO() xx_virtual_machine_interface_allowed_address_pairs = AllowedAddressPairs(**prop_dict) xx_virtual_machine_interface_allowed_address_pairs.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_machine_interface_allowed_address_pairs = AllowedAddressPairs() try: xx_virtual_machine_interface_allowed_address_pairs.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('vrf_assign_table') if prop_dict: buf = cStringIO.StringIO() xx_vrf_assign_table = VrfAssignTableType(**prop_dict) xx_vrf_assign_table.export(buf) node = etree.fromstring(buf.getvalue()) xx_vrf_assign_table = VrfAssignTableType() try: xx_vrf_assign_table.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('virtual_machine_interface_properties') if prop_dict: buf = cStringIO.StringIO() xx_virtual_machine_interface_properties = VirtualMachineInterfacePropertiesType(**prop_dict) xx_virtual_machine_interface_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_machine_interface_properties = VirtualMachineInterfacePropertiesType() try: xx_virtual_machine_interface_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) for ref_dict in obj_dict.get('routing_instance_refs') or []: buf = cStringIO.StringIO() xx_routing_instance = PolicyBasedForwardingRuleType(**ref_dict['attr']) xx_routing_instance.export(buf) node = etree.fromstring(buf.getvalue()) try: xx_routing_instance.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'virtual-machine-interface', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'virtual_machine_interface', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'virtual_machine_interface', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = [u'qos_forwarding_class', u'security_group', 'virtual_machine_interface', u'virtual_machine', u'virtual_network', 'routing_instance', u'interface_route_table'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('virtual-machine-interface', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'virtual_machine_interface', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['virtual_machine_interface', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('virtual-machine-interface') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'virtual_machine_interface', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('virtual-machine-interface', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'virtual_machine_interface', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('virtual-machine-interface', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_machine_interface_create', obj_dict) except Exception as e: pass return {'virtual-machine-interface': rsp_body} #end virtual_machine_interfaces_http_post def virtual_machine_interfaces_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'virtual_machine_interfaces', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('virtual-machine-interface', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'virtual_machine_interfaces', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'virtual-machine-interfaces': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('virtual-machine-interface', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('virtual-machine-interface', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('virtual-machine-interface', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'virtual_machine_interface_mac_addresses', u'virtual_machine_interface_dhcp_option_list', u'virtual_machine_interface_host_routes', u'virtual_machine_interface_allowed_address_pairs', u'vrf_assign_table', u'virtual_machine_interface_device_owner', u'virtual_machine_interface_properties', u'id_perms', u'display_name'] + [u'qos_forwarding_class_refs', u'security_group_refs', 'virtual_machine_interface_refs', u'virtual_machine_refs', u'virtual_network_refs', 'routing_instance_refs', u'interface_route_table_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('virtual-machine-interface', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('virtual-machine-interface', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'virtual-machine-interface': obj_dict}) return {'virtual-machine-interfaces': obj_dicts} #end virtual_machine_interfaces_http_get def _virtual_machine_interface_create_default_children(self, parent_obj): pass #end _virtual_machine_interface_create_default_children def _virtual_machine_interface_delete_default_children(self, parent_dict): pass #end _virtual_machine_interface_delete_default_children def loadbalancer_healthmonitor_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_loadbalancer_healthmonitor_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'loadbalancer_healthmonitor': abort(404, 'No loadbalancer-healthmonitor object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'loadbalancer_healthmonitor', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('loadbalancer-healthmonitor') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'loadbalancer_healthmonitor', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'loadbalancer_healthmonitor_properties', u'id_perms', u'display_name'] references = [] back_references = [u'project_back_refs', u'loadbalancer_pool_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('loadbalancer-healthmonitor', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'loadbalancer_healthmonitor', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'loadbalancer_healthmonitor', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('loadbalancer-healthmonitor', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_loadbalancer_healthmonitor_read', id, rsp_body) except Exception as e: pass return {'loadbalancer-healthmonitor': rsp_body} #end loadbalancer_healthmonitor_http_get def loadbalancer_healthmonitor_http_put(self, id): key = 'loadbalancer-healthmonitor' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_loadbalancer_healthmonitor_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'loadbalancer_healthmonitor': abort(404, 'No loadbalancer-healthmonitor object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('loadbalancer_healthmonitor_properties') if prop_dict: buf = cStringIO.StringIO() xx_loadbalancer_healthmonitor_properties = LoadbalancerHealthmonitorType(**prop_dict) xx_loadbalancer_healthmonitor_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_loadbalancer_healthmonitor_properties = LoadbalancerHealthmonitorType() try: xx_loadbalancer_healthmonitor_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'loadbalancer_healthmonitor', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'loadbalancer_healthmonitor', 'http_put', msg) abort(code, msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('loadbalancer-healthmonitor') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'loadbalancer_healthmonitor', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('loadbalancer-healthmonitor', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'loadbalancer_healthmonitor', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('loadbalancer-healthmonitor', id) try: self._extension_mgrs['resourceApi'].map_method('post_loadbalancer_healthmonitor_update', id, obj_dict) except Exception as e: pass return {'loadbalancer-healthmonitor': rsp_body} #end loadbalancer_healthmonitor_http_put def loadbalancer_healthmonitor_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'loadbalancer_healthmonitor': abort(404, 'No loadbalancer-healthmonitor object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_loadbalancer_healthmonitor_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'project_back_refs', u'loadbalancer_pool_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('loadbalancer-healthmonitor', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'loadbalancer_healthmonitor', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'loadbalancer_healthmonitor', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'loadbalancer_healthmonitor', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('loadbalancer-healthmonitor', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('loadbalancer-healthmonitor') if r_class: if read_ok: # fail if non-default children or backrefs exist loadbalancer_pool_back_refs = read_result.get('loadbalancer_pool_back_refs', None) if loadbalancer_pool_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['loadbalancer_pool_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'loadbalancer_healthmonitor', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._loadbalancer_healthmonitor_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'loadbalancer_healthmonitor', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('loadbalancer-healthmonitor', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'loadbalancer_healthmonitor', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_loadbalancer_healthmonitor_delete', id, read_result) except Exception as e: pass #end loadbalancer_healthmonitor_http_delete def loadbalancer_healthmonitors_http_post(self): key = 'loadbalancer-healthmonitor' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_loadbalancer_healthmonitor_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('loadbalancer_healthmonitor_properties') if prop_dict: buf = cStringIO.StringIO() xx_loadbalancer_healthmonitor_properties = LoadbalancerHealthmonitorType(**prop_dict) xx_loadbalancer_healthmonitor_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_loadbalancer_healthmonitor_properties = LoadbalancerHealthmonitorType() try: xx_loadbalancer_healthmonitor_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'loadbalancer-healthmonitor', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'loadbalancer_healthmonitor', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'loadbalancer_healthmonitor', 'http_post', err_msg) abort(400, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('loadbalancer-healthmonitor', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'loadbalancer_healthmonitor', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['loadbalancer_healthmonitor', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('loadbalancer-healthmonitor') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'loadbalancer_healthmonitor', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('loadbalancer-healthmonitor', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'loadbalancer_healthmonitor', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('loadbalancer-healthmonitor', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_loadbalancer_healthmonitor_create', obj_dict) except Exception as e: pass return {'loadbalancer-healthmonitor': rsp_body} #end loadbalancer_healthmonitors_http_post def loadbalancer_healthmonitors_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'loadbalancer_healthmonitors', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('loadbalancer-healthmonitor', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'loadbalancer_healthmonitors', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'loadbalancer-healthmonitors': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('loadbalancer-healthmonitor', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('loadbalancer-healthmonitor', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('loadbalancer-healthmonitor', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'loadbalancer_healthmonitor_properties', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('loadbalancer-healthmonitor', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('loadbalancer-healthmonitor', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'loadbalancer-healthmonitor': obj_dict}) return {'loadbalancer-healthmonitors': obj_dicts} #end loadbalancer_healthmonitors_http_get def _loadbalancer_healthmonitor_create_default_children(self, parent_obj): pass #end _loadbalancer_healthmonitor_create_default_children def _loadbalancer_healthmonitor_delete_default_children(self, parent_dict): pass #end _loadbalancer_healthmonitor_delete_default_children def virtual_network_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_network_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'virtual_network': abort(404, 'No virtual-network object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'virtual_network', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('virtual-network') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'virtual_network', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'virtual_network_properties', u'virtual_network_network_id', u'route_target_list', u'router_external', u'is_shared', u'external_ipam', u'flood_unknown_unicast', u'id_perms', u'display_name'] references = [u'qos_forwarding_class_refs', u'network_ipam_refs', u'network_policy_refs', u'route_table_refs'] back_references = [u'project_back_refs', 'virtual_machine_interface_back_refs', u'instance_ip_back_refs', u'physical_router_back_refs', u'logical_router_back_refs'] children = [u'access_control_lists', u'floating_ip_pools', 'routing_instances'] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('virtual-network', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'virtual_network', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'virtual_network', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('virtual-network', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_virtual_network_read', id, rsp_body) except Exception as e: pass return {'virtual-network': rsp_body} #end virtual_network_http_get def virtual_network_http_put(self, id): key = 'virtual-network' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_network_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'virtual_network': abort(404, 'No virtual-network object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('virtual_network_properties') if prop_dict: buf = cStringIO.StringIO() xx_virtual_network_properties = VirtualNetworkType(**prop_dict) xx_virtual_network_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_network_properties = VirtualNetworkType() try: xx_virtual_network_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('route_target_list') if prop_dict: buf = cStringIO.StringIO() xx_route_target_list = RouteTargetList(**prop_dict) xx_route_target_list.export(buf) node = etree.fromstring(buf.getvalue()) xx_route_target_list = RouteTargetList() try: xx_route_target_list.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) for ref_dict in obj_dict.get('network_ipam_refs') or []: buf = cStringIO.StringIO() xx_network_ipam = VnSubnetsType(**ref_dict['attr']) xx_network_ipam.export(buf) node = etree.fromstring(buf.getvalue()) try: xx_network_ipam.build(node) except Exception as e: abort(400, str(e)) for ref_dict in obj_dict.get('network_policy_refs') or []: buf = cStringIO.StringIO() xx_network_policy = VirtualNetworkPolicyType(**ref_dict['attr']) xx_network_policy.export(buf) node = etree.fromstring(buf.getvalue()) try: xx_network_policy.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'virtual_network', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'virtual_network', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = [u'qos_forwarding_class', u'network_ipam', u'network_policy', u'access_control_list', u'floating_ip_pool', 'routing_instance', u'route_table'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('virtual-network') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'virtual_network', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('virtual-network', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'virtual_network', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('virtual-network', id) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_network_update', id, obj_dict) except Exception as e: pass return {'virtual-network': rsp_body} #end virtual_network_http_put def virtual_network_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'virtual_network': abort(404, 'No virtual-network object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_network_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'project_back_refs', 'virtual_machine_interface_back_refs', u'instance_ip_back_refs', u'physical_router_back_refs', u'logical_router_back_refs'] children = [u'access_control_lists', u'floating_ip_pools', 'routing_instances'] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('virtual-network', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'virtual_network', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'virtual_network', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'virtual_network', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('virtual-network', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('virtual-network') if r_class: if read_ok: # fail if non-default children or backrefs exist floating_ip_pools = read_result.get('floating_ip_pools', None) if floating_ip_pools: has_infos = read_result['floating_ip_pools'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-floating-ip-pool')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'virtual_network', 'http_delete', err_msg) abort(409, err_msg) virtual_machine_interface_back_refs = read_result.get('virtual_machine_interface_back_refs', None) if virtual_machine_interface_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['virtual_machine_interface_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_network', 'http_delete', err_msg) abort(409, err_msg) instance_ip_back_refs = read_result.get('instance_ip_back_refs', None) if instance_ip_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['instance_ip_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_network', 'http_delete', err_msg) abort(409, err_msg) physical_router_back_refs = read_result.get('physical_router_back_refs', None) if physical_router_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['physical_router_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_network', 'http_delete', err_msg) abort(409, err_msg) logical_router_back_refs = read_result.get('logical_router_back_refs', None) if logical_router_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['logical_router_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'virtual_network', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._virtual_network_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'virtual_network', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('virtual-network', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'virtual_network', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_network_delete', id, read_result) except Exception as e: pass #end virtual_network_http_delete def virtual_networks_http_post(self): key = 'virtual-network' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_virtual_network_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('virtual_network_properties') if prop_dict: buf = cStringIO.StringIO() xx_virtual_network_properties = VirtualNetworkType(**prop_dict) xx_virtual_network_properties.export(buf) node = etree.fromstring(buf.getvalue()) xx_virtual_network_properties = VirtualNetworkType() try: xx_virtual_network_properties.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('route_target_list') if prop_dict: buf = cStringIO.StringIO() xx_route_target_list = RouteTargetList(**prop_dict) xx_route_target_list.export(buf) node = etree.fromstring(buf.getvalue()) xx_route_target_list = RouteTargetList() try: xx_route_target_list.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) for ref_dict in obj_dict.get('network_ipam_refs') or []: buf = cStringIO.StringIO() xx_network_ipam = VnSubnetsType(**ref_dict['attr']) xx_network_ipam.export(buf) node = etree.fromstring(buf.getvalue()) try: xx_network_ipam.build(node) except Exception as e: abort(400, str(e)) for ref_dict in obj_dict.get('network_policy_refs') or []: buf = cStringIO.StringIO() xx_network_policy = VirtualNetworkPolicyType(**ref_dict['attr']) xx_network_policy.export(buf) node = etree.fromstring(buf.getvalue()) try: xx_network_policy.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'virtual-network', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'virtual_network', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'virtual_network', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = [u'qos_forwarding_class', u'network_ipam', u'network_policy', u'access_control_list', u'floating_ip_pool', 'routing_instance', u'route_table'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('virtual-network', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'virtual_network', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['virtual_network', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('virtual-network') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'virtual_network', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('virtual-network', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'virtual_network', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('virtual-network', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_virtual_network_create', obj_dict) except Exception as e: pass return {'virtual-network': rsp_body} #end virtual_networks_http_post def virtual_networks_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'virtual_networks', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('virtual-network', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'virtual_networks', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'virtual-networks': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('virtual-network', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('virtual-network', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('virtual-network', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'virtual_network_properties', u'virtual_network_network_id', u'route_target_list', u'router_external', u'is_shared', u'external_ipam', u'flood_unknown_unicast', u'id_perms', u'display_name'] + [u'qos_forwarding_class_refs', u'network_ipam_refs', u'network_policy_refs', u'route_table_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('virtual-network', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('virtual-network', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'virtual-network': obj_dict}) return {'virtual-networks': obj_dicts} #end virtual_networks_http_get def _virtual_network_create_default_children(self, parent_obj): # Create a default child only if provisioned for r_class = self.get_resource_class('floating-ip-pool') if r_class and r_class.generate_default_instance: child_obj = FloatingIpPool(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('floating-ip-pool') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('floating-ip-pool', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('floating-ip-pool', obj_ids, child_dict) self._floating_ip_pool_create_default_children(child_obj) pass #end _virtual_network_create_default_children def _virtual_network_delete_default_children(self, parent_dict): # Delete a default child only if provisioned for r_class = self.get_resource_class('floating-ip-pool') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('access_control_lists') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-access-control-list': default_child_id = has_info['href'].split('/')[-1] self.access_control_list_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('floating-ip-pool') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('floating_ip_pools') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-floating-ip-pool': default_child_id = has_info['href'].split('/')[-1] self.floating_ip_pool_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('floating-ip-pool') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('routing_instances') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-routing-instance': default_child_id = has_info['href'].split('/')[-1] self.routing_instance_http_delete(default_child_id) break pass #end _virtual_network_delete_default_children def project_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_project_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'project': abort(404, 'No project object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'project', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('project') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'project', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'quota', u'id_perms', u'display_name'] references = [u'namespace_refs', u'floating_ip_pool_refs'] back_references = [u'domain_back_refs', u'floating_ip_back_refs'] children = [u'security_groups', u'virtual_networks', u'qos_queues', u'qos_forwarding_classs', u'network_ipams', u'network_policys', 'virtual_machine_interfaces', u'service_instances', u'route_tables', u'interface_route_tables', u'logical_routers', u'loadbalancer_pools', u'loadbalancer_healthmonitors', u'virtual_ips'] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('project', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'project', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'project', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('project', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_project_read', id, rsp_body) except Exception as e: pass return {'project': rsp_body} #end project_http_get def project_http_put(self, id): key = 'project' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_project_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'project': abort(404, 'No project object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('quota') if prop_dict: buf = cStringIO.StringIO() xx_quota = QuotaType(**prop_dict) xx_quota.export(buf) node = etree.fromstring(buf.getvalue()) xx_quota = QuotaType() try: xx_quota.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) for ref_dict in obj_dict.get('namespace_refs') or []: buf = cStringIO.StringIO() xx_namespace = SubnetType(**ref_dict['attr']) xx_namespace.export(buf) node = etree.fromstring(buf.getvalue()) try: xx_namespace.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'project', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'project', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = [u'namespace', u'security_group', u'virtual_network', u'qos_queue', u'qos_forwarding_class', u'network_ipam', u'network_policy', 'virtual_machine_interface', u'floating_ip_pool', u'service_instance', u'route_table', u'interface_route_table', u'logical_router', u'loadbalancer_pool', u'loadbalancer_healthmonitor', u'virtual_ip'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('project') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'project', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('project', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'project', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('project', id) try: self._extension_mgrs['resourceApi'].map_method('post_project_update', id, obj_dict) except Exception as e: pass return {'project': rsp_body} #end project_http_put def project_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'project': abort(404, 'No project object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_project_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'domain_back_refs', u'floating_ip_back_refs'] children = [u'security_groups', u'virtual_networks', u'qos_queues', u'qos_forwarding_classs', u'network_ipams', u'network_policys', 'virtual_machine_interfaces', u'service_instances', u'route_tables', u'interface_route_tables', u'logical_routers', u'loadbalancer_pools', u'loadbalancer_healthmonitors', u'virtual_ips'] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('project', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'project', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'project', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'project', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('project', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('project') if r_class: if read_ok: # fail if non-default children or backrefs exist security_groups = read_result.get('security_groups', None) if security_groups: has_infos = read_result['security_groups'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-security-group')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'project', 'http_delete', err_msg) abort(409, err_msg) virtual_networks = read_result.get('virtual_networks', None) if virtual_networks: has_infos = read_result['virtual_networks'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-virtual-network')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'project', 'http_delete', err_msg) abort(409, err_msg) qos_queues = read_result.get('qos_queues', None) if qos_queues: has_infos = read_result['qos_queues'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-qos-queue')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'project', 'http_delete', err_msg) abort(409, err_msg) qos_forwarding_classs = read_result.get('qos_forwarding_classs', None) if qos_forwarding_classs: has_infos = read_result['qos_forwarding_classs'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-qos-forwarding-class')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'project', 'http_delete', err_msg) abort(409, err_msg) network_ipams = read_result.get('network_ipams', None) if network_ipams: has_infos = read_result['network_ipams'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-network-ipam')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'project', 'http_delete', err_msg) abort(409, err_msg) network_policys = read_result.get('network_policys', None) if network_policys: has_infos = read_result['network_policys'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-network-policy')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'project', 'http_delete', err_msg) abort(409, err_msg) virtual_machine_interfaces = read_result.get('virtual_machine_interfaces', None) if virtual_machine_interfaces: has_infos = read_result['virtual_machine_interfaces'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-virtual-machine-interface')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'project', 'http_delete', err_msg) abort(409, err_msg) service_instances = read_result.get('service_instances', None) if service_instances: has_infos = read_result['service_instances'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-service-instance')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'project', 'http_delete', err_msg) abort(409, err_msg) route_tables = read_result.get('route_tables', None) if route_tables: has_infos = read_result['route_tables'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-route-table')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'project', 'http_delete', err_msg) abort(409, err_msg) interface_route_tables = read_result.get('interface_route_tables', None) if interface_route_tables: has_infos = read_result['interface_route_tables'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-interface-route-table')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'project', 'http_delete', err_msg) abort(409, err_msg) logical_routers = read_result.get('logical_routers', None) if logical_routers: has_infos = read_result['logical_routers'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-logical-router')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'project', 'http_delete', err_msg) abort(409, err_msg) loadbalancer_pools = read_result.get('loadbalancer_pools', None) if loadbalancer_pools: has_infos = read_result['loadbalancer_pools'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-loadbalancer-pool')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'project', 'http_delete', err_msg) abort(409, err_msg) loadbalancer_healthmonitors = read_result.get('loadbalancer_healthmonitors', None) if loadbalancer_healthmonitors: has_infos = read_result['loadbalancer_healthmonitors'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-loadbalancer-healthmonitor')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'project', 'http_delete', err_msg) abort(409, err_msg) virtual_ips = read_result.get('virtual_ips', None) if virtual_ips: has_infos = read_result['virtual_ips'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-virtual-ip')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'project', 'http_delete', err_msg) abort(409, err_msg) floating_ip_back_refs = read_result.get('floating_ip_back_refs', None) if floating_ip_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['floating_ip_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'project', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._project_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'project', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('project', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'project', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_project_delete', id, read_result) except Exception as e: pass #end project_http_delete def projects_http_post(self): key = 'project' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_project_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('quota') if prop_dict: buf = cStringIO.StringIO() xx_quota = QuotaType(**prop_dict) xx_quota.export(buf) node = etree.fromstring(buf.getvalue()) xx_quota = QuotaType() try: xx_quota.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) for ref_dict in obj_dict.get('namespace_refs') or []: buf = cStringIO.StringIO() xx_namespace = SubnetType(**ref_dict['attr']) xx_namespace.export(buf) node = etree.fromstring(buf.getvalue()) try: xx_namespace.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'project', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'project', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'project', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = [u'namespace', u'security_group', u'virtual_network', u'qos_queue', u'qos_forwarding_class', u'network_ipam', u'network_policy', 'virtual_machine_interface', u'floating_ip_pool', u'service_instance', u'route_table', u'interface_route_table', u'logical_router', u'loadbalancer_pool', u'loadbalancer_healthmonitor', u'virtual_ip'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('project', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'project', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['project', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('project') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'project', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('project', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'project', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('project', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_project_create', obj_dict) except Exception as e: pass return {'project': rsp_body} #end projects_http_post def projects_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'projects', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('project', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'projects', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'projects': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('project', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('project', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('project', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'quota', u'id_perms', u'display_name'] + [u'namespace_refs', u'floating_ip_pool_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('project', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('project', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'project': obj_dict}) return {'projects': obj_dicts} #end projects_http_get def _project_create_default_children(self, parent_obj): # Create a default child only if provisioned for r_class = self.get_resource_class('security-group') if r_class and r_class.generate_default_instance: child_obj = SecurityGroup(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('security-group') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('security-group', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('security-group', obj_ids, child_dict) self._security_group_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('virtual-network') if r_class and r_class.generate_default_instance: child_obj = VirtualNetwork(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('virtual-network') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('virtual-network', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('virtual-network', obj_ids, child_dict) self._virtual_network_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('qos-queue') if r_class and r_class.generate_default_instance: child_obj = QosQueue(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('qos-queue') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('qos-queue', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('qos-queue', obj_ids, child_dict) self._qos_queue_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('qos-forwarding-class') if r_class and r_class.generate_default_instance: child_obj = QosForwardingClass(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('qos-forwarding-class') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('qos-forwarding-class', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('qos-forwarding-class', obj_ids, child_dict) self._qos_forwarding_class_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('network-ipam') if r_class and r_class.generate_default_instance: child_obj = NetworkIpam(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('network-ipam') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('network-ipam', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('network-ipam', obj_ids, child_dict) self._network_ipam_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('network-policy') if r_class and r_class.generate_default_instance: child_obj = NetworkPolicy(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('network-policy') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('network-policy', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('network-policy', obj_ids, child_dict) self._network_policy_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('virtual-machine-interface') if r_class and r_class.generate_default_instance: child_obj = VirtualMachineInterface(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('virtual-machine-interface') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('virtual-machine-interface', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('virtual-machine-interface', obj_ids, child_dict) self._virtual_machine_interface_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('service-instance') if r_class and r_class.generate_default_instance: child_obj = ServiceInstance(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('service-instance') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('service-instance', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('service-instance', obj_ids, child_dict) self._service_instance_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('route-table') if r_class and r_class.generate_default_instance: child_obj = RouteTable(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('route-table') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('route-table', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('route-table', obj_ids, child_dict) self._route_table_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('interface-route-table') if r_class and r_class.generate_default_instance: child_obj = InterfaceRouteTable(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('interface-route-table') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('interface-route-table', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('interface-route-table', obj_ids, child_dict) self._interface_route_table_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('logical-router') if r_class and r_class.generate_default_instance: child_obj = LogicalRouter(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('logical-router') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('logical-router', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('logical-router', obj_ids, child_dict) self._logical_router_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('loadbalancer-pool') if r_class and r_class.generate_default_instance: child_obj = LoadbalancerPool(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('loadbalancer-pool') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('loadbalancer-pool', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('loadbalancer-pool', obj_ids, child_dict) self._loadbalancer_pool_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('loadbalancer-healthmonitor') if r_class and r_class.generate_default_instance: child_obj = LoadbalancerHealthmonitor(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('loadbalancer-healthmonitor') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('loadbalancer-healthmonitor', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('loadbalancer-healthmonitor', obj_ids, child_dict) self._loadbalancer_healthmonitor_create_default_children(child_obj) # Create a default child only if provisioned for r_class = self.get_resource_class('virtual-ip') if r_class and r_class.generate_default_instance: child_obj = VirtualIp(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('virtual-ip') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('virtual-ip', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('virtual-ip', obj_ids, child_dict) self._virtual_ip_create_default_children(child_obj) pass #end _project_create_default_children def _project_delete_default_children(self, parent_dict): # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-ip') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('security_groups') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-security-group': default_child_id = has_info['href'].split('/')[-1] self.security_group_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-ip') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('virtual_networks') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-virtual-network': default_child_id = has_info['href'].split('/')[-1] self.virtual_network_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-ip') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('qos_queues') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-qos-queue': default_child_id = has_info['href'].split('/')[-1] self.qos_queue_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-ip') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('qos_forwarding_classs') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-qos-forwarding-class': default_child_id = has_info['href'].split('/')[-1] self.qos_forwarding_class_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-ip') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('network_ipams') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-network-ipam': default_child_id = has_info['href'].split('/')[-1] self.network_ipam_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-ip') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('network_policys') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-network-policy': default_child_id = has_info['href'].split('/')[-1] self.network_policy_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-ip') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('virtual_machine_interfaces') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-virtual-machine-interface': default_child_id = has_info['href'].split('/')[-1] self.virtual_machine_interface_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-ip') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('service_instances') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-service-instance': default_child_id = has_info['href'].split('/')[-1] self.service_instance_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-ip') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('route_tables') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-route-table': default_child_id = has_info['href'].split('/')[-1] self.route_table_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-ip') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('interface_route_tables') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-interface-route-table': default_child_id = has_info['href'].split('/')[-1] self.interface_route_table_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-ip') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('logical_routers') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-logical-router': default_child_id = has_info['href'].split('/')[-1] self.logical_router_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-ip') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('loadbalancer_pools') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-loadbalancer-pool': default_child_id = has_info['href'].split('/')[-1] self.loadbalancer_pool_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-ip') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('loadbalancer_healthmonitors') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-loadbalancer-healthmonitor': default_child_id = has_info['href'].split('/')[-1] self.loadbalancer_healthmonitor_http_delete(default_child_id) break # Delete a default child only if provisioned for r_class = self.get_resource_class('virtual-ip') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('virtual_ips') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-virtual-ip': default_child_id = has_info['href'].split('/')[-1] self.virtual_ip_http_delete(default_child_id) break pass #end _project_delete_default_children def qos_forwarding_class_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_qos_forwarding_class_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'qos_forwarding_class': abort(404, 'No qos-forwarding-class object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'qos_forwarding_class', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('qos-forwarding-class') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'qos_forwarding_class', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'dscp', u'trusted', u'id_perms', u'display_name'] references = [u'qos_queue_refs'] back_references = [u'project_back_refs', u'virtual_network_back_refs', 'virtual_machine_interface_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('qos-forwarding-class', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'qos_forwarding_class', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'qos_forwarding_class', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('qos-forwarding-class', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_qos_forwarding_class_read', id, rsp_body) except Exception as e: pass return {'qos-forwarding-class': rsp_body} #end qos_forwarding_class_http_get def qos_forwarding_class_http_put(self, id): key = 'qos-forwarding-class' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_qos_forwarding_class_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'qos_forwarding_class': abort(404, 'No qos-forwarding-class object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'qos_forwarding_class', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'qos_forwarding_class', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = [u'qos_queue'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('qos-forwarding-class') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'qos_forwarding_class', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('qos-forwarding-class', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'qos_forwarding_class', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('qos-forwarding-class', id) try: self._extension_mgrs['resourceApi'].map_method('post_qos_forwarding_class_update', id, obj_dict) except Exception as e: pass return {'qos-forwarding-class': rsp_body} #end qos_forwarding_class_http_put def qos_forwarding_class_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'qos_forwarding_class': abort(404, 'No qos-forwarding-class object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_qos_forwarding_class_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'project_back_refs', u'virtual_network_back_refs', 'virtual_machine_interface_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('qos-forwarding-class', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'qos_forwarding_class', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'qos_forwarding_class', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'qos_forwarding_class', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('qos-forwarding-class', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('qos-forwarding-class') if r_class: if read_ok: # fail if non-default children or backrefs exist virtual_network_back_refs = read_result.get('virtual_network_back_refs', None) if virtual_network_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['virtual_network_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'qos_forwarding_class', 'http_delete', err_msg) abort(409, err_msg) virtual_machine_interface_back_refs = read_result.get('virtual_machine_interface_back_refs', None) if virtual_machine_interface_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['virtual_machine_interface_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'qos_forwarding_class', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._qos_forwarding_class_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'qos_forwarding_class', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('qos-forwarding-class', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'qos_forwarding_class', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_qos_forwarding_class_delete', id, read_result) except Exception as e: pass #end qos_forwarding_class_http_delete def qos_forwarding_classs_http_post(self): key = 'qos-forwarding-class' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_qos_forwarding_class_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'qos-forwarding-class', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'qos_forwarding_class', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'qos_forwarding_class', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = [u'qos_queue'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('qos-forwarding-class', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'qos_forwarding_class', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['qos_forwarding_class', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('qos-forwarding-class') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'qos_forwarding_class', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('qos-forwarding-class', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'qos_forwarding_class', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('qos-forwarding-class', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_qos_forwarding_class_create', obj_dict) except Exception as e: pass return {'qos-forwarding-class': rsp_body} #end qos_forwarding_classs_http_post def qos_forwarding_classs_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'qos_forwarding_classs', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('qos-forwarding-class', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'qos_forwarding_classs', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'qos-forwarding-classs': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('qos-forwarding-class', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('qos-forwarding-class', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('qos-forwarding-class', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'dscp', u'trusted', u'id_perms', u'display_name'] + [u'qos_queue_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('qos-forwarding-class', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('qos-forwarding-class', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'qos-forwarding-class': obj_dict}) return {'qos-forwarding-classs': obj_dicts} #end qos_forwarding_classs_http_get def _qos_forwarding_class_create_default_children(self, parent_obj): pass #end _qos_forwarding_class_create_default_children def _qos_forwarding_class_delete_default_children(self, parent_dict): pass #end _qos_forwarding_class_delete_default_children def database_node_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_database_node_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'database_node': abort(404, 'No database-node object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'database_node', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('database-node') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'database_node', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'database_node_ip_address', u'id_perms', u'display_name'] references = [] back_references = [u'global_system_config_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('database-node', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'database_node', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'database_node', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('database-node', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_database_node_read', id, rsp_body) except Exception as e: pass return {'database-node': rsp_body} #end database_node_http_get def database_node_http_put(self, id): key = 'database-node' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_database_node_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'database_node': abort(404, 'No database-node object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'database_node', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'database_node', 'http_put', msg) abort(code, msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('database-node') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'database_node', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('database-node', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'database_node', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('database-node', id) try: self._extension_mgrs['resourceApi'].map_method('post_database_node_update', id, obj_dict) except Exception as e: pass return {'database-node': rsp_body} #end database_node_http_put def database_node_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'database_node': abort(404, 'No database-node object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_database_node_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'global_system_config_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('database-node', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'database_node', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'database_node', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'database_node', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('database-node', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('database-node') if r_class: if read_ok: # fail if non-default children or backrefs exist # Delete default children first self._database_node_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'database_node', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('database-node', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'database_node', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_database_node_delete', id, read_result) except Exception as e: pass #end database_node_http_delete def database_nodes_http_post(self): key = 'database-node' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_database_node_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'database-node', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'database_node', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'database_node', 'http_post', err_msg) abort(400, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('database-node', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'database_node', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['database_node', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('database-node') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'database_node', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('database-node', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'database_node', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('database-node', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_database_node_create', obj_dict) except Exception as e: pass return {'database-node': rsp_body} #end database_nodes_http_post def database_nodes_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'database_nodes', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('database-node', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'database_nodes', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'database-nodes': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('database-node', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('database-node', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('database-node', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'database_node_ip_address', u'id_perms', u'display_name'] + [] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('database-node', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('database-node', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'database-node': obj_dict}) return {'database-nodes': obj_dicts} #end database_nodes_http_get def _database_node_create_default_children(self, parent_obj): pass #end _database_node_create_default_children def _database_node_delete_default_children(self, parent_dict): pass #end _database_node_delete_default_children def routing_instance_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_routing_instance_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'routing_instance': abort(404, 'No routing-instance object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'routing_instance', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('routing-instance') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'routing_instance', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'service_chain_information', u'routing_instance_is_default', u'static_route_entries', u'default_ce_protocol', u'id_perms', u'display_name'] references = ['routing_instance_refs', 'route_target_refs'] back_references = ['virtual_machine_interface_back_refs', u'virtual_network_back_refs', 'routing_instance_back_refs', 'customer_attachment_back_refs'] children = ['bgp_routers'] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('routing-instance', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'routing_instance', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'routing_instance', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('routing-instance', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_routing_instance_read', id, rsp_body) except Exception as e: pass return {'routing-instance': rsp_body} #end routing_instance_http_get def routing_instance_http_put(self, id): key = 'routing-instance' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_routing_instance_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'routing_instance': abort(404, 'No routing-instance object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('service_chain_information') if prop_dict: buf = cStringIO.StringIO() xx_service_chain_information = ServiceChainInfo(**prop_dict) xx_service_chain_information.export(buf) node = etree.fromstring(buf.getvalue()) xx_service_chain_information = ServiceChainInfo() try: xx_service_chain_information.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('static_route_entries') if prop_dict: buf = cStringIO.StringIO() xx_static_route_entries = StaticRouteEntriesType(**prop_dict) xx_static_route_entries.export(buf) node = etree.fromstring(buf.getvalue()) xx_static_route_entries = StaticRouteEntriesType() try: xx_static_route_entries.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('default_ce_protocol') if prop_dict: buf = cStringIO.StringIO() xx_default_ce_protocol = DefaultProtocolType(**prop_dict) xx_default_ce_protocol.export(buf) node = etree.fromstring(buf.getvalue()) xx_default_ce_protocol = DefaultProtocolType() try: xx_default_ce_protocol.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) for ref_dict in obj_dict.get('routing_instance_refs') or []: if fq_name == ref_dict['to']: abort(404, 'Cannot add reference to self') buf = cStringIO.StringIO() xx_routing_instance = ConnectionType(**ref_dict['attr']) xx_routing_instance.export(buf) node = etree.fromstring(buf.getvalue()) try: xx_routing_instance.build(node) except Exception as e: abort(400, str(e)) for ref_dict in obj_dict.get('route_target_refs') or []: buf = cStringIO.StringIO() xx_route_target = InstanceTargetType(**ref_dict['attr']) xx_route_target.export(buf) node = etree.fromstring(buf.getvalue()) try: xx_route_target.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'routing_instance', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'routing_instance', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = ['bgp_router', 'routing_instance', 'route_target'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('routing-instance') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'routing_instance', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('routing-instance', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'routing_instance', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('routing-instance', id) try: self._extension_mgrs['resourceApi'].map_method('post_routing_instance_update', id, obj_dict) except Exception as e: pass return {'routing-instance': rsp_body} #end routing_instance_http_put def routing_instance_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'routing_instance': abort(404, 'No routing-instance object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_routing_instance_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = ['virtual_machine_interface_back_refs', u'virtual_network_back_refs', 'routing_instance_back_refs', 'customer_attachment_back_refs'] children = ['bgp_routers'] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('routing-instance', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'routing_instance', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'routing_instance', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'routing_instance', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('routing-instance', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('routing-instance') if r_class: if read_ok: # fail if non-default children or backrefs exist bgp_routers = read_result.get('bgp_routers', None) if bgp_routers: has_infos = read_result['bgp_routers'] if ((len(has_infos) > 1) or (len(has_infos) == 1 and has_infos[0]['to'][-1] != 'default-bgp-router')): has_urls = [has_info['href'] for has_info in has_infos] has_str = ', '.join(has_urls) err_msg = 'Children ' + has_str + ' still exist' self.config_object_error(id, None, 'routing_instance', 'http_delete', err_msg) abort(409, err_msg) virtual_machine_interface_back_refs = read_result.get('virtual_machine_interface_back_refs', None) if virtual_machine_interface_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['virtual_machine_interface_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'routing_instance', 'http_delete', err_msg) abort(409, err_msg) routing_instance_back_refs = read_result.get('routing_instance_back_refs', None) if routing_instance_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['routing_instance_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'routing_instance', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._routing_instance_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'routing_instance', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('routing-instance', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'routing_instance', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_routing_instance_delete', id, read_result) except Exception as e: pass #end routing_instance_http_delete def routing_instances_http_post(self): key = 'routing-instance' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_routing_instance_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('service_chain_information') if prop_dict: buf = cStringIO.StringIO() xx_service_chain_information = ServiceChainInfo(**prop_dict) xx_service_chain_information.export(buf) node = etree.fromstring(buf.getvalue()) xx_service_chain_information = ServiceChainInfo() try: xx_service_chain_information.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('static_route_entries') if prop_dict: buf = cStringIO.StringIO() xx_static_route_entries = StaticRouteEntriesType(**prop_dict) xx_static_route_entries.export(buf) node = etree.fromstring(buf.getvalue()) xx_static_route_entries = StaticRouteEntriesType() try: xx_static_route_entries.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('default_ce_protocol') if prop_dict: buf = cStringIO.StringIO() xx_default_ce_protocol = DefaultProtocolType(**prop_dict) xx_default_ce_protocol.export(buf) node = etree.fromstring(buf.getvalue()) xx_default_ce_protocol = DefaultProtocolType() try: xx_default_ce_protocol.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) for ref_dict in obj_dict.get('routing_instance_refs') or []: if fq_name == ref_dict['to']: abort(404, 'Cannot add reference to self') buf = cStringIO.StringIO() xx_routing_instance = ConnectionType(**ref_dict['attr']) xx_routing_instance.export(buf) node = etree.fromstring(buf.getvalue()) try: xx_routing_instance.build(node) except Exception as e: abort(400, str(e)) for ref_dict in obj_dict.get('route_target_refs') or []: buf = cStringIO.StringIO() xx_route_target = InstanceTargetType(**ref_dict['attr']) xx_route_target.export(buf) node = etree.fromstring(buf.getvalue()) try: xx_route_target.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'routing-instance', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'routing_instance', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'routing_instance', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = ['bgp_router', 'routing_instance', 'route_target'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('routing-instance', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'routing_instance', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['routing_instance', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('routing-instance') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'routing_instance', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('routing-instance', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'routing_instance', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('routing-instance', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_routing_instance_create', obj_dict) except Exception as e: pass return {'routing-instance': rsp_body} #end routing_instances_http_post def routing_instances_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'routing_instances', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('routing-instance', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'routing_instances', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'routing-instances': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('routing-instance', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('routing-instance', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('routing-instance', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'service_chain_information', u'routing_instance_is_default', u'static_route_entries', u'default_ce_protocol', u'id_perms', u'display_name'] + ['routing_instance_refs', 'route_target_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('routing-instance', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('routing-instance', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'routing-instance': obj_dict}) return {'routing-instances': obj_dicts} #end routing_instances_http_get def _routing_instance_create_default_children(self, parent_obj): # Create a default child only if provisioned for r_class = self.get_resource_class('bgp-router') if r_class and r_class.generate_default_instance: child_obj = BgpRouter(parent_obj = parent_obj) child_dict = child_obj.__dict__ fq_name = child_dict['fq_name'] child_dict['id_perms'] = self._get_default_id_perms('bgp-router') db_conn = self._db_conn (ok, result) = db_conn.dbe_alloc('bgp-router', child_dict) if not ok: return (ok, result) obj_ids = result db_conn.dbe_create('bgp-router', obj_ids, child_dict) self._bgp_router_create_default_children(child_obj) pass #end _routing_instance_create_default_children def _routing_instance_delete_default_children(self, parent_dict): # Delete a default child only if provisioned for r_class = self.get_resource_class('bgp-router') if r_class and r_class.generate_default_instance: # first locate default child then delete it has_infos = parent_dict.get('bgp_routers') if has_infos: for has_info in has_infos: if has_info['to'][-1] == 'default-bgp-router': default_child_id = has_info['href'].split('/')[-1] self.bgp_router_http_delete(default_child_id) break pass #end _routing_instance_delete_default_children def network_ipam_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_network_ipam_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'network_ipam': abort(404, 'No network-ipam object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'network_ipam', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('network-ipam') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'network_ipam', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'network_ipam_mgmt', u'id_perms', u'display_name'] references = [u'virtual_DNS_refs'] back_references = [u'project_back_refs', u'virtual_network_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('network-ipam', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'network_ipam', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'network_ipam', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('network-ipam', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_network_ipam_read', id, rsp_body) except Exception as e: pass return {'network-ipam': rsp_body} #end network_ipam_http_get def network_ipam_http_put(self, id): key = 'network-ipam' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_network_ipam_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'network_ipam': abort(404, 'No network-ipam object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('network_ipam_mgmt') if prop_dict: buf = cStringIO.StringIO() xx_network_ipam_mgmt = IpamType(**prop_dict) xx_network_ipam_mgmt.export(buf) node = etree.fromstring(buf.getvalue()) xx_network_ipam_mgmt = IpamType() try: xx_network_ipam_mgmt.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'network_ipam', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'network_ipam', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = [u'virtual_DNS'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('network-ipam') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'network_ipam', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('network-ipam', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'network_ipam', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('network-ipam', id) try: self._extension_mgrs['resourceApi'].map_method('post_network_ipam_update', id, obj_dict) except Exception as e: pass return {'network-ipam': rsp_body} #end network_ipam_http_put def network_ipam_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'network_ipam': abort(404, 'No network-ipam object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_network_ipam_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'project_back_refs', u'virtual_network_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('network-ipam', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'network_ipam', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'network_ipam', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'network_ipam', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('network-ipam', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('network-ipam') if r_class: if read_ok: # fail if non-default children or backrefs exist virtual_network_back_refs = read_result.get('virtual_network_back_refs', None) if virtual_network_back_refs: back_ref_urls = [back_ref_info['href'] for back_ref_info in read_result['virtual_network_back_refs']] back_ref_str = ', '.join(back_ref_urls) err_msg = 'Back-References from ' + back_ref_str + ' still exist' self.config_object_error(id, None, 'network_ipam', 'http_delete', err_msg) abort(409, err_msg) # Delete default children first self._network_ipam_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'network_ipam', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('network-ipam', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'network_ipam', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_network_ipam_delete', id, read_result) except Exception as e: pass #end network_ipam_http_delete def network_ipams_http_post(self): key = 'network-ipam' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_network_ipam_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('network_ipam_mgmt') if prop_dict: buf = cStringIO.StringIO() xx_network_ipam_mgmt = IpamType(**prop_dict) xx_network_ipam_mgmt.export(buf) node = etree.fromstring(buf.getvalue()) xx_network_ipam_mgmt = IpamType() try: xx_network_ipam_mgmt.build(node) except Exception as e: abort(400, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'network-ipam', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'network_ipam', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'network_ipam', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = [u'virtual_DNS'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('network-ipam', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'network_ipam', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['network_ipam', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('network-ipam') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'network_ipam', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('network-ipam', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'network_ipam', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('network-ipam', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_network_ipam_create', obj_dict) except Exception as e: pass return {'network-ipam': rsp_body} #end network_ipams_http_post def network_ipams_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'network_ipams', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('network-ipam', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'network_ipams', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'network-ipams': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('network-ipam', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('network-ipam', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('network-ipam', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'network_ipam_mgmt', u'id_perms', u'display_name'] + [u'virtual_DNS_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('network-ipam', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('network-ipam', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'network-ipam': obj_dict}) return {'network-ipams': obj_dicts} #end network_ipams_http_get def _network_ipam_create_default_children(self, parent_obj): pass #end _network_ipam_create_default_children def _network_ipam_delete_default_children(self, parent_dict): pass #end _network_ipam_delete_default_children def logical_router_http_get(self, id): try: self._extension_mgrs['resourceApi'].map_method('pre_logical_router_read', id) except Exception as e: pass # TODO get vals from request out of the global ASAP etag = request.headers.get('If-None-Match') try: obj_type = self._db_conn.uuid_to_obj_type(id) except NoIdError: obj_type = None if obj_type != 'logical_router': abort(404, 'No logical-router object found for id %s' %(id)) # common handling for all resource get (ok, result) = self._get_common(request, id) if not ok: (code, msg) = result self.config_object_error(id, None, 'logical_router', 'http_get', msg) abort(code, msg) # type-specific hook r_class = self.get_resource_class('logical-router') if r_class: r_class.http_get(id) db_conn = self._db_conn if etag: obj_ids = {'uuid': id} (ok, result) = db_conn.dbe_is_latest(obj_ids, etag.replace('"', '')) if not ok: # Not present in DB self.config_object_error(id, None, 'logical_router', 'http_get', result) abort(404, result) is_latest = result if is_latest: # send Not-Modified, caches use this for read optimization response.status = 304 return #end if etag obj_ids = {'uuid': id} # Generate field list for db layer properties = [u'id_perms', u'display_name'] references = ['virtual_machine_interface_refs', 'route_target_refs', u'virtual_network_refs', u'service_instance_refs'] back_references = [u'project_back_refs'] children = [] if 'fields' in request.query: obj_fields = request.query.fields.split(',') else: # default props + children + refs + backrefs obj_fields = properties + references if 'exclude_back_refs' not in request.query: obj_fields = obj_fields + back_references if 'exclude_children' not in request.query: obj_fields = obj_fields + children (ok, result) = db_conn.dbe_read('logical-router', obj_ids, obj_fields) if not ok: # Not present in DB self.config_object_error(id, None, 'logical_router', 'http_get', result) abort(404, result) # check visibility if (not result['id_perms'].get('user_visible', True) and not self.is_admin_request()): result = 'This object is not visible by users: %s' % id self.config_object_error(id, None, 'logical_router', 'http_get', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('logical-router', id) rsp_body['name'] = result['fq_name'][-1] rsp_body.update(result) id_perms = result['id_perms'] response.set_header('ETag', '"' + id_perms['last_modified'] + '"') try: self._extension_mgrs['resourceApi'].map_method('post_logical_router_read', id, rsp_body) except Exception as e: pass return {'logical-router': rsp_body} #end logical_router_http_get def logical_router_http_put(self, id): key = 'logical-router' obj_dict = request.json[key] try: self._extension_mgrs['resourceApi'].map_method('pre_logical_router_update', id, obj_dict) except Exception as e: pass db_conn = self._db_conn try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'logical_router': abort(404, 'No logical-router object found for id %s' %(id)) fq_name = db_conn.uuid_to_fq_name(id) except NoIdError as e: abort(404, str(e)) prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource put (ok, result) = self._put_common(request, 'logical_router', id, fq_name, obj_dict) if not ok: (code, msg) = result self.config_object_error(id, None, 'logical_router', 'http_put', msg) abort(code, msg) # Validate perms objtype_list = ['virtual_machine_interface', 'route_target', u'virtual_network', u'service_instance'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: try: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) except NoIdError as e: abort(404, str(e)) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('logical-router') if r_class: (ok, put_result) = r_class.http_put(id, fq_name, obj_dict, self._db_conn) if not ok: (code, msg) = put_result self.config_object_error(id, None, 'logical_router', 'http_put', msg) abort(code, msg) callable = getattr(r_class, 'http_put_fail', None) if callable: cleanup_on_failure.append((callable, [id, fq_name, obj_dict, self._db_conn])) obj_ids = {'uuid': id} try: (ok, result) = db_conn.dbe_update('logical-router', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'logical_router', 'http_put', result) abort(404, result) rsp_body = {} rsp_body['uuid'] = id rsp_body['href'] = self.generate_url('logical-router', id) try: self._extension_mgrs['resourceApi'].map_method('post_logical_router_update', id, obj_dict) except Exception as e: pass return {'logical-router': rsp_body} #end logical_router_http_put def logical_router_http_delete(self, id): db_conn = self._db_conn # if obj doesn't exist return early try: obj_type = db_conn.uuid_to_obj_type(id) if obj_type != 'logical_router': abort(404, 'No logical-router object found for id %s' %(id)) _ = db_conn.uuid_to_fq_name(id) except NoIdError: abort(404, 'ID %s does not exist' %(id)) try: self._extension_mgrs['resourceApi'].map_method('pre_logical_router_delete', id) except Exception as e: pass # read in obj from db (accepting error) to get details of it obj_ids = {'uuid': id} back_references = [u'project_back_refs'] children = [] obj_fields = children + back_references (read_ok, read_result) = db_conn.dbe_read('logical-router', obj_ids, obj_fields) if not read_ok: if read_result.startswith('Unknown id:'): abort(404, 'ID %s does not exist' %(id)) else: self.config_object_error(id, None, 'logical_router', 'http_delete', read_result) # proceed down to delete the resource # common handling for all resource delete parent_type = read_result.get('parent_type', None) (ok, del_result) = self._delete_common(request, 'logical_router', id, parent_type) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'logical_router', 'http_delete', msg) abort(code, msg) fq_name = read_result['fq_name'] ifmap_id = cfgm_common.imid.get_ifmap_id_from_fq_name('logical-router', fq_name) obj_ids['imid'] = ifmap_id if parent_type: parent_imid = cfgm_common.imid.get_ifmap_id_from_fq_name(parent_type, fq_name[:-1]) obj_ids['parent_imid'] = parent_imid # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # type-specific hook r_class = self.get_resource_class('logical-router') if r_class: if read_ok: # fail if non-default children or backrefs exist # Delete default children first self._logical_router_delete_default_children(read_result) (ok, del_result) = r_class.http_delete(id, read_result, db_conn) if not ok: (code, msg) = del_result self.config_object_error(id, None, 'logical_router', 'http_delete', msg) abort(code, msg) callable = getattr(r_class, 'http_delete_fail', None) if callable: cleanup_on_failure.append((callable, [id, read_result, db_conn])) #end if read_ok try: (ok, del_result) = db_conn.dbe_delete('logical-router', obj_ids, read_result) except Exception as e: ok = False del_result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) self.config_object_error(id, None, 'logical_router', 'http_delete', del_result) abort(409, del_result) try: self._extension_mgrs['resourceApi'].map_method('post_logical_router_delete', id, read_result) except Exception as e: pass #end logical_router_http_delete def logical_routers_http_post(self): key = 'logical-router' obj_dict = request.json[key] self._post_validate(key, obj_dict=obj_dict) fq_name = obj_dict['fq_name'] try: self._extension_mgrs['resourceApi'].map_method('pre_logical_router_create', obj_dict) except Exception as e: pass prop_dict = obj_dict.get('id_perms') if prop_dict: buf = cStringIO.StringIO() xx_id_perms = IdPermsType(**prop_dict) xx_id_perms.export(buf) node = etree.fromstring(buf.getvalue()) xx_id_perms = IdPermsType() try: xx_id_perms.build(node) except Exception as e: abort(400, str(e)) # common handling for all resource create (ok, result) = self._post_common(request, 'logical-router', obj_dict) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict.get('fq_name', [])) self.config_object_error(None, fq_name_str, 'logical_router', 'http_post', msg) abort(code, msg) name = obj_dict['fq_name'][-1] fq_name = obj_dict['fq_name'] db_conn = self._db_conn # if client gave parent_type of config-root, ignore and remove if 'parent_type' in obj_dict and obj_dict['parent_type'] == 'config-root': del obj_dict['parent_type'] if 'parent_type' in obj_dict: # non config-root child, verify parent exists parent_type = obj_dict['parent_type'] parent_fq_name = obj_dict['fq_name'][:-1] try: parent_uuid = self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name) (ok, status) = self._permissions.check_perms_write(request, parent_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) self._permissions.set_user_role(request, obj_dict) except NoIdError: err_msg = 'Parent ' + pformat(parent_fq_name) + ' type ' + parent_type + ' does not exist' fq_name_str = ':'.join(parent_fq_name) self.config_object_error(None, fq_name_str, 'logical_router', 'http_post', err_msg) abort(400, err_msg) # Validate perms objtype_list = ['virtual_machine_interface', 'route_target', u'virtual_network', u'service_instance'] for obj_type in objtype_list: refs = obj_dict.get('%s_refs'%(obj_type), None) if refs: for ref in refs: ref_uuid = db_conn.fq_name_to_uuid(obj_type, ref['to']) (ok, status) = self._permissions.check_perms_link(request, ref_uuid) if not ok: (code, err_msg) = status abort(code, err_msg) # State modification starts from here. Ensure that cleanup is done for all state changes cleanup_on_failure = [] # Alloc and Store id-mappings before creating entry on pubsub store. # Else a subscriber can ask for an id mapping before we have stored it uuid_requested = result (ok, result) = db_conn.dbe_alloc('logical-router', obj_dict, uuid_requested) if not ok: (code, msg) = result fq_name_str = ':'.join(obj_dict['fq_name']) self.config_object_error(None, fq_name_str, 'logical_router', 'http_post', result) abort(code, msg) cleanup_on_failure.append((db_conn.dbe_release, ['logical_router', fq_name])) obj_ids = result env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') # type-specific hook r_class = self.get_resource_class('logical-router') if r_class: try: (ok, result) = r_class.http_post_collection(tenant_name, obj_dict, db_conn) except Exception as e: ok = False result = (500, str(e)) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) (code, msg) = result fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'logical_router', 'http_post', msg) abort(code, msg) callable = getattr(r_class, 'http_post_collection_fail', None) if callable: cleanup_on_failure.append((callable, [tenant_name, obj_dict, db_conn])) try: (ok, result) = \ db_conn.dbe_create('logical-router', obj_ids, obj_dict) except Exception as e: ok = False result = str(e) if not ok: for fail_cleanup_callable, cleanup_args in cleanup_on_failure: fail_cleanup_callable(*cleanup_args) fq_name_str = ':'.join(fq_name) self.config_object_error(None, fq_name_str, 'logical_router', 'http_post', result) abort(404, result) rsp_body = {} rsp_body['name'] = name rsp_body['fq_name'] = fq_name rsp_body['uuid'] = obj_ids['uuid'] rsp_body['href'] = self.generate_url('logical-router', obj_ids['uuid']) if 'parent_type' in obj_dict: # non config-root child, send back parent uuid/href rsp_body['parent_uuid'] = parent_uuid rsp_body['parent_href'] = self.generate_url(parent_type, parent_uuid) try: self._extension_mgrs['resourceApi'].map_method('post_logical_router_create', obj_dict) except Exception as e: pass return {'logical-router': rsp_body} #end logical_routers_http_post def logical_routers_http_get(self): # gather list of uuids using 1. any specified anchors # 2. any specified filters # if not 'detail' return list with any specified 'fields' # if 'detail' return list with props+refs + any specified 'fields' env = request.headers.environ tenant_name = env.get(hdr_server_tenant(), 'default-project') parent_uuids = None back_ref_uuids = None obj_uuids = None if (('parent_fq_name_str' in request.query) and ('parent_type' in request.query)): parent_fq_name = request.query.parent_fq_name_str.split(':') parent_type = request.query.parent_type parent_uuids = [self._db_conn.fq_name_to_uuid(parent_type, parent_fq_name)] elif 'parent_id' in request.query: parent_ids = request.query.parent_id.split(',') parent_uuids = [str(uuid.UUID(p_uuid)) for p_uuid in parent_ids] if 'back_ref_id' in request.query: back_ref_ids = request.query.back_ref_id.split(',') back_ref_uuids = [str(uuid.UUID(b_uuid)) for b_uuid in back_ref_ids] if 'obj_uuids' in request.query: obj_uuids = request.query.obj_uuids.split(',') # common handling for all resource get (ok, result) = self._get_common(request, parent_uuids) if not ok: (code, msg) = result self.config_object_error(None, None, 'logical_routers', 'http_get_collection', msg) abort(code, msg) if 'count' in request.query: count = 'true' in request.query.count.lower() else: count = False filter_params = request.query.filters if filter_params: try: ff_key_vals = filter_params.split(',') ff_names = [ff.split('==')[0] for ff in ff_key_vals] ff_values = [ff.split('==')[1] for ff in ff_key_vals] filters = {'field_names': ff_names, 'field_values': ff_values} except Exception as e: abort(400, 'Invalid filter ' + filter_params) else: filters = None db_conn = self._db_conn (ok, result) = \ db_conn.dbe_list('logical-router', parent_uuids, back_ref_uuids, obj_uuids, count, filters) if not ok: self.config_object_error(None, None, 'logical_routers', 'http_get_collection', result) abort(404, result) # If only counting, return early if count: return {'logical-routers': {'count': result}} if 'detail' in request.query: detail = 'true' in request.query.detail.lower() else: detail = False fq_names_uuids = result obj_dicts = [] if not detail: if not self.is_admin_request(): obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms'] (ok, result) = db_conn.dbe_read_multi('logical-router', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) if obj_result['id_perms'].get('user_visible', True): obj_dict = {} obj_dict['uuid'] = obj_result['uuid'] obj_dict['href'] = self.generate_url('logical-router', obj_result['uuid']) obj_dict['fq_name'] = obj_result['fq_name'] obj_dicts.append(obj_dict) else: for fq_name, obj_uuid in fq_names_uuids: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['uuid'] = obj_uuid obj_dict['href'] = self.generate_url('logical-router', obj_uuid) obj_dict['fq_name'] = fq_name obj_dicts.append(obj_dict) else: #detail obj_ids_list = [{'uuid': obj_uuid} for _, obj_uuid in fq_names_uuids] obj_fields = [u'id_perms', u'display_name'] + ['virtual_machine_interface_refs', 'route_target_refs', u'virtual_network_refs', u'service_instance_refs'] if 'fields' in request.query: obj_fields.extend(request.query.fields.split(',')) (ok, result) = db_conn.dbe_read_multi('logical-router', obj_ids_list, obj_fields) if not ok: result = [] for obj_result in result: # give chance for zk heartbeat/ping gevent.sleep(0) obj_dict = {} obj_dict['name'] = obj_result['fq_name'][-1] obj_dict['href'] = self.generate_url('logical-router', obj_result['uuid']) obj_dict.update(obj_result) if (obj_dict['id_perms'].get('user_visible', True) or self.is_admin_request()): obj_dicts.append({'logical-router': obj_dict}) return {'logical-routers': obj_dicts} #end logical_routers_http_get def _logical_router_create_default_children(self, parent_obj): pass #end _logical_router_create_default_children def _logical_router_delete_default_children(self, parent_dict): pass #end _logical_router_delete_default_children #end class VncApiServerGen class DefaultsGen(object): def __init__(self): self.perms = {} default_perms = self._common_default_perms id_perms = IdPermsType(default_perms, None, True, 0, 0) self.perms['domain'] = id_perms self.perms['global-vrouter-config'] = id_perms self.perms['instance-ip'] = id_perms self.perms['network-policy'] = id_perms self.perms['loadbalancer-pool'] = id_perms self.perms['virtual-DNS-record'] = id_perms self.perms['route-target'] = id_perms self.perms['floating-ip'] = id_perms self.perms['floating-ip-pool'] = id_perms self.perms['physical-router'] = id_perms self.perms['bgp-router'] = id_perms self.perms['virtual-router'] = id_perms self.perms['config-root'] = id_perms self.perms['subnet'] = id_perms self.perms['global-system-config'] = id_perms self.perms['service-appliance'] = id_perms self.perms['service-instance'] = id_perms self.perms['namespace'] = id_perms self.perms['logical-interface'] = id_perms self.perms['route-table'] = id_perms self.perms['physical-interface'] = id_perms self.perms['access-control-list'] = id_perms self.perms['analytics-node'] = id_perms self.perms['virtual-DNS'] = id_perms self.perms['customer-attachment'] = id_perms self.perms['service-appliance-set'] = id_perms self.perms['config-node'] = id_perms self.perms['qos-queue'] = id_perms self.perms['virtual-machine'] = id_perms self.perms['interface-route-table'] = id_perms self.perms['service-template'] = id_perms self.perms['virtual-ip'] = id_perms self.perms['loadbalancer-member'] = id_perms self.perms['security-group'] = id_perms self.perms['provider-attachment'] = id_perms self.perms['virtual-machine-interface'] = id_perms self.perms['loadbalancer-healthmonitor'] = id_perms self.perms['virtual-network'] = id_perms self.perms['project'] = id_perms self.perms['qos-forwarding-class'] = id_perms self.perms['database-node'] = id_perms self.perms['routing-instance'] = id_perms self.perms['network-ipam'] = id_perms self.perms['logical-router'] = id_perms self.resource = {} #end __init__ #end class DefaultsGen