def _check_delete_network(self, context, network): network_id = network["id"] # NOTE(ft): check non default routes not longer exists # must be done for internet routes routes, dummy = self._sync_routes(context) for route in routes.itervalues(): if (route["network_id"] == network_id and not route["is_default"]): raise exception.InvalidInput(_("Network contains routes")) # NOTE(ft): check invisible routes not longer exists # must be done for routes on non default subnet and other non GCE stuff client = clients.neutron(context) checked_routers = set() subnets = client.list_subnets(network_id=network_id)["subnets"] cidrs = [netaddr.IPNetwork(subnet["cidr"]) for subnet in subnets] ports = client.list_ports( network_id=network["id"], device_owner="network:router_interface")["ports"] for port in ports: if port["device_id"] in checked_routers: continue checked_routers.add(port["device_id"]) router = client.show_router(port["device_id"])["router"] for route in router["routes"]: nexthop = netaddr.IPAddress(route["nexthop"]) if any(nexthop in cidr for cidr in cidrs): raise exception.InvalidInput(_("Network contains routes"))
def delete_item(self, context, name, scope=None): routes, aliased_routes = self._sync_routes(context) route = routes[name] if route.get("nexthop") is None: raise exception.InvalidInput( _("The local route cannot be deleted.")) destination = route["destination"] nexthop = route["nexthop"] # NOTE(ft): delete OS route only if it doesn't have aliases # at the moment client = clients.neutron(context) operation_util.start_operation(context) if self._get_route_key(route) not in aliased_routes: dummy, router = self._get_network_objects(client, route["network"]) if "external_gateway_info" in route: client.remove_gateway_router(router["id"]) else: routes = [ r for r in router["routes"] if (destination != r["destination"] or nexthop != r["nexthop"]) ] client.update_router(router["id"], { "router": { "routes": routes, }, }) self._delete_db_item(context, route)
def delete_item(self, context, name, scope=None): routes, aliased_routes = self._sync_routes(context) route = routes[name] if route.get("nexthop") is None: raise exception.InvalidInput( _("The local route cannot be deleted.")) destination = route["destination"] nexthop = route["nexthop"] # NOTE(ft): delete OS route only if it doesn't have aliases # at the moment client = clients.neutron(context) operation_util.start_operation(context) if self._get_route_key(route) not in aliased_routes: dummy, router = self._get_network_objects(client, route["network"]) if "external_gateway_info" in route: client.remove_gateway_router(router["id"]) else: routes = [r for r in router["routes"] if (destination != r["destination"] or nexthop != r["nexthop"])] client.update_router( router["id"], {"router": {"routes": routes, }, }) self._delete_db_item(context, route)
def _create_custom_route(self, context, network, body): client = clients.neutron(context) port, router = self._get_network_objects(client, network) destination = body.get("destRange") nexthop = body.get("nextHopIp") routes = router["routes"] if all(r["destination"] != destination or r["nexthop"] != nexthop for r in routes): routes.append({ "destination": destination, "nexthop": nexthop, }) client.update_router(router["id"], { "router": { "routes": router["routes"], }, }) route = self._add_gce_route(context, network, port, body, is_default=False, destination=destination, nexthop=nexthop) route["network"] = network route["port"] = port return route
def get_public_network_id(self, context): """Get id of public network appointed to GCE in config.""" client = clients.neutron(context) search_opts = {"name": self._public_network_name, "router:external": True} networks = client.list_networks(**search_opts)["networks"] return networks[0]["id"]
def _create_network_router(self, context, network, subnet_id): public_network_id = network_api.API().get_public_network_id(context) client = clients.neutron(context) router = client.create_router(body={"router": { "name": network["name"], "admin_state_up": True, "external_gateway_info": {"network_id": public_network_id}, }})["router"] client.add_interface_router(router["id"], {"subnet_id": subnet_id})
def get_public_network_id(self, context): """Get id of public network appointed to GCE in config.""" client = clients.neutron(context) search_opts = { "name": self._public_network_name, "router:external": True } networks = client.list_networks(**search_opts)["networks"] return networks[0]["id"]
def get_items(self, context, scope=None): client = clients.neutron(context) networks = client.list_networks(tenant_id=context.project_id) networks = networks["networks"] gce_networks = self._get_db_items_dict(context) result_networks = [] for network in networks: network = self._prepare_network(client, network, gce_networks.get(network["id"])) result_networks.append(network) self._purge_db(context, result_networks, gce_networks) return result_networks
def delete_item(self, context, name, scope=None): client = clients.neutron(context) network = self.get_item(context, name) self._process_callbacks( context, base_api._callback_reasons.check_delete, network) operation_util.start_operation(context) self._delete_db_item(context, network) self._process_callbacks( context, base_api._callback_reasons.pre_delete, network) client.delete_network(network["id"])
def delete_item(self, context, name, scope=None): client = clients.neutron(context) network = self.get_item(context, name) self._process_callbacks(context, base_api._callback_reasons.check_delete, network) operation_util.start_operation(context) self._delete_db_item(context, network) self._process_callbacks(context, base_api._callback_reasons.pre_delete, network) client.delete_network(network["id"])
def _create_network_router(self, context, network, subnet_id): public_network_id = network_api.API().get_public_network_id(context) client = clients.neutron(context) router = client.create_router( body={ "router": { "name": network["name"], "admin_state_up": True, "external_gateway_info": { "network_id": public_network_id }, } })["router"] client.add_interface_router(router["id"], {"subnet_id": subnet_id})
def get_item(self, context, name, scope=None): client = clients.neutron(context) networks = client.list_networks( tenant_id=context.project_id, name=name)["networks"] if not networks: msg = _("Network resource '%s' could not be found.") % name raise exception.NotFound(msg) else: # NOTE(Alex) There might be more than one network with this name. # TODO(Alex) We have to decide if we should support IDs as # parameters for names as well and return error if we have # multi-results when addressed by name. network = networks[0] gce_network = self._get_db_item_by_id(context, network["id"]) return self._prepare_network(client, network, gce_network)
def get_item(self, context, name, scope=None): client = clients.neutron(context) networks = client.list_networks(tenant_id=context.project_id, name=name)["networks"] if not networks: msg = _("Network resource '%s' could not be found.") % name raise exception.NotFound(msg) else: # NOTE(Alex) There might be more than one network with this name. # TODO(Alex) We have to decide if we should support IDs as # parameters for names as well and return error if we have # multi-results when addressed by name. network = networks[0] gce_network = self._get_db_item_by_id(context, network["id"]) return self._prepare_network(client, network, gce_network)
def add_item(self, context, name, body, scope=None): if any(x["name"] == name for x in self._get_floating_ips(context, scope)): raise exception.InvalidInput( _("The resource '%s' already exists.") % name) public_network_id = network_api.API().get_public_network_id(context) operation_util.start_operation(context) floating_ip = clients.neutron(context).create_floatingip( {"floatingip": {"floating_network_id": public_network_id}}) floating_ip = self._prepare_floating_ip( clients.nova(context), floating_ip["floatingip"], scope) floating_ip["name"] = body["name"] if "description" in body: floating_ip["description"] = body["description"] floating_ip = self._add_db_item(context, floating_ip) return floating_ip
def _get_floating_ips(self, context, scope, name=None): results = clients.neutron(context).list_floatingips( tenant_id=context.project_id)["floatingips"] gce_floating_ips = self._get_db_items_dict(context) nova_client = clients.nova(context) results = [self._prepare_floating_ip(nova_client, x, scope, gce_floating_ips.get(x["id"])) for x in results] unnamed_ips = self._purge_db(context, results, gce_floating_ips) self._add_nonnamed_items(context, unnamed_ips) if name is None: return results for item in results: if item["name"] == name: return [item] raise exception.NotFound
def _get_os_routes(self, context): client = clients.neutron(context) routers = client.list_routers(tenant_id=context.project_id)["routers"] routers = dict((r["id"], r) for r in routers) ports = client.list_ports( tenant_id=context.project_id, device_owner="network:router_interface")["ports"] ports = dict((p["network_id"], p) for p in ports) gateway_ports = client.list_ports( device_owner="network:router_gateway")["ports"] gateway_ports = dict((p["device_id"], p) for p in gateway_ports) routes = {} networks = network_api.API().get_items(context) for network in networks: # NOTE(ft): append local route network_id = network["id"] routes[network_id] = self._init_local_route(network) port = ports.get(network_id) if port is None: continue router = routers.get(port["device_id"]) if router is None: continue key_prefix = network_id + port["id"] # NOTE(ft): append internet route external_gateway_info = router.get("external_gateway_info") gateway_port = gateway_ports.get(router["id"]) if (external_gateway_info is not None and gateway_port is not None): key = key_prefix + ALL_IP_CIDR + gateway_port["id"] routes[key] = self._init_internet_route( network, port, gateway_port["id"], external_gateway_info) # NOTE(ft): append other routes for route in router["routes"]: destination = route["destination"] nexthop = route["nexthop"] key = key_prefix + destination + nexthop routes[key] = self._init_custom_route( network, port, destination, nexthop) return routes
def _create_internet_route(self, context, network, body): client = clients.neutron(context) port, router = self._get_network_objects(client, network) public_network_id = network_api.API().get_public_network_id(context) external_gateway_info = {"network_id": public_network_id} router = client.add_gateway_router( router["id"], external_gateway_info)["router"] gateway_port = client.list_ports( device_id=router["id"], device_owner="network:router_gateway")["ports"][0] route = self._add_gce_route(context, network, port, body, is_default=False, destination=gateway_port["id"], nexthop=ALL_IP_CIDR) route["network"] = network route["port"] = port route["external_gateway_info"] = external_gateway_info return route
def add_item(self, context, name, body, scope=None): if any(x["name"] == name for x in self._get_floating_ips(context, scope)): raise exception.InvalidInput( _("The resource '%s' already exists.") % name) public_network_id = network_api.API().get_public_network_id(context) operation_util.start_operation(context) floating_ip = clients.neutron(context).create_floatingip( {"floatingip": { "floating_network_id": public_network_id }}) floating_ip = self._prepare_floating_ip(clients.nova(context), floating_ip["floatingip"], scope) floating_ip["name"] = body["name"] if "description" in body: floating_ip["description"] = body["description"] floating_ip = self._add_db_item(context, floating_ip) return floating_ip
def _get_os_routes(self, context): client = clients.neutron(context) routers = client.list_routers(tenant_id=context.project_id)["routers"] routers = dict((r["id"], r) for r in routers) ports = client.list_ports( tenant_id=context.project_id, device_owner="network:router_interface")["ports"] ports = dict((p["network_id"], p) for p in ports) gateway_ports = client.list_ports( device_owner="network:router_gateway")["ports"] gateway_ports = dict((p["device_id"], p) for p in gateway_ports) routes = {} networks = network_api.API().get_items(context) for network in networks: # NOTE(ft): append local route network_id = network["id"] routes[network_id] = self._init_local_route(network) port = ports.get(network_id) if port is None: continue router = routers.get(port["device_id"]) if router is None: continue key_prefix = network_id + port["id"] # NOTE(ft): append internet route external_gateway_info = router.get("external_gateway_info") gateway_port = gateway_ports.get(router["id"]) if (external_gateway_info is not None and gateway_port is not None): key = key_prefix + ALL_IP_CIDR + gateway_port["id"] routes[key] = self._init_internet_route( network, port, gateway_port["id"], external_gateway_info) # NOTE(ft): append other routes for route in router["routes"]: destination = route["destination"] nexthop = route["nexthop"] key = key_prefix + destination + nexthop routes[key] = self._init_custom_route(network, port, destination, nexthop) return routes
def get_item(self, context, name, scope=None): session = clients.admin_session() keystone = clients.keystone(context, session=session) project = keystone.projects.get(context.project_id) result = utils.to_dict(project) result["keypair"] = self._get_gce_keypair(context) project_id = project.id nova = clients.nova(context, session=session) nova_limits = nova.limits.get(tenant_id=project_id) result["nova_limits"] = dict( (l.name, l.value) for l in nova_limits.absolute) cinder_client = clients.cinder(context, session=session) try: result["cinder_quotas"] = utils.to_dict( cinder_client.quotas.get(project_id, usage=True)) except TypeError: # NOTE(apavlov): cinderclient of version 1.0.6 and below # has no usage parameter result["cinder_quotas"] = dict([ ("limit", x) for x in utils.to_dict(cinder_client.quotas.get(project_id)) ]) net_api = CONF.get("network_api") if net_api is None or ("quantum" in net_api or "neutron" in net_api): neutron_client = clients.neutron(context, session=session) result["neutron_quota"] = ( neutron_client.show_quota(project_id)["quota"]) result["neutron_quota"]["network_used"] = len( neutron_client.list_networks(tenant_id=project_id)["networks"]) result["neutron_quota"]["floatingip_used"] = len( neutron_client.list_floatingips( tenant_id=project_id)["floatingips"]) result["neutron_quota"]["security_group_used"] = len( neutron_client.list_security_groups( tenant_id=project_id)["security_groups"]) else: result["neutron_quota"] = {} return result
def _get_floating_ips(self, context, scope, name=None): results = clients.neutron(context).list_floatingips( tenant_id=context.project_id)["floatingips"] gce_floating_ips = self._get_db_items_dict(context) nova_client = clients.nova(context) results = [ self._prepare_floating_ip(nova_client, x, scope, gce_floating_ips.get(x["id"])) for x in results ] unnamed_ips = self._purge_db(context, results, gce_floating_ips) self._add_nonnamed_items(context, unnamed_ips) if name is None: return results for item in results: if item["name"] == name: return [item] raise exception.NotFound
def add_item(self, context, name, body, scope=None): ip_range = body.get('IPv4Range', CONF.default_network_ip_range) gateway = body.get('gatewayIPv4') if gateway is None: network_cidr = netaddr.IPNetwork(ip_range) gateway_ip = netaddr.IPAddress(network_cidr.first + 1) gateway = str(gateway_ip) client = clients.neutron(context) network = None try: network = self.get_item(context, name) except exception.NotFound: pass if network is not None: raise exception.DuplicateVlan network_body = {} network_body["network"] = {"name": name} operation_util.start_operation(context) network = client.create_network(network_body) network = network["network"] if ip_range: subnet_body = {} subnet_body["subnet"] = { # NOTE(Alex) "name": name + ".default_subnet", # Won't give it a name for now "network_id": network["id"], "ip_version": "4", "cidr": ip_range, "gateway_ip": gateway } result_data = client.create_subnet(subnet_body) subnet_id = result_data["subnet"]["id"] network = self._prepare_network(client, network) if 'description' in body: network["description"] = body["description"] network = self._add_db_item(context, network) self._process_callbacks(context, base_api._callback_reasons.post_add, network, subnet_id=subnet_id) return network
def get_item(self, context, name, scope=None): project_name = context.project_name keystone = clients.keystone(context) project = [t for t in keystone.tenants.list() if t.name == project_name][0] result = utils.to_dict(project) result["keypair"] = self._get_gce_keypair(context) project_id = project.id nova_limits = clients.nova(context).limits.get(tenant_id=project_id) result["nova_limits"] = dict((l.name, l.value) for l in nova_limits.absolute) cinder_client = clients.cinder(context) try: result["cinder_quotas"] = utils.to_dict( cinder_client.quotas.get(project_id, usage=True)) except TypeError: # NOTE(apavlov): cinderclient of version 1.0.6 and below # has no usage parameter result["cinder_quotas"] = dict([("limit", x) for x in utils.to_dict(cinder_client.quotas.get(project_id))]) net_api = CONF.get("network_api") if net_api is None or ("quantum" in net_api or "neutron" in net_api): neutron_client = clients.neutron(context) result["neutron_quota"] = ( neutron_client.show_quota(project_id)["quota"]) result["neutron_quota"]["network_used"] = len(neutron_client .list_networks(tenant_id=project_id)["networks"]) result["neutron_quota"]["floatingip_used"] = len(neutron_client .list_floatingips(tenant_id=project_id)["floatingips"]) result["neutron_quota"]["security_group_used"] = len(neutron_client .list_security_groups(tenant_id=project_id)["security_groups"]) else: result["neutron_quota"] = {} return result
def _create_custom_route(self, context, network, body): client = clients.neutron(context) port, router = self._get_network_objects(client, network) destination = body.get("destRange") nexthop = body.get("nextHopIp") routes = router["routes"] if all(r["destination"] != destination or r["nexthop"] != nexthop for r in routes): routes.append({ "destination": destination, "nexthop": nexthop, }) client.update_router( router["id"], {"router": {"routes": router["routes"], }, }) route = self._add_gce_route(context, network, port, body, is_default=False, destination=destination, nexthop=nexthop) route["network"] = network route["port"] = port return route
def _delete_network_router(self, context, network): client = clients.neutron(context) ports = client.list_ports( network_id=network["id"], device_owner="network:router_interface")["ports"] router_ids = set() for port in ports: if port["device_owner"] == "network:router_interface": router_ids.add(port["device_id"]) client.remove_interface_router(port["device_id"], {"port_id": port["id"]}) # NOTE(ft): leave routers if network is plugged to more than one route # because it's look like some non GCE settings, so we don't want # to decide whether we can delete router or not if len(router_ids) != 1: return router = router_ids.pop() # NOTE(ft): leave router if other subnets are plugged to it ports = client.list_ports( device_id=router, device_owner="network:router_interface")["ports"] if len(ports) == 0: client.delete_router(router)
def add_item(self, context, name, body, scope=None): ip_range = body.get('IPv4Range', CONF.default_network_ip_range) gateway = body.get('gatewayIPv4') if gateway is None: network_cidr = netaddr.IPNetwork(ip_range) gateway_ip = netaddr.IPAddress(network_cidr.first + 1) gateway = str(gateway_ip) client = clients.neutron(context) network = None try: network = self.get_item(context, name) except exception.NotFound: pass if network is not None: raise exception.DuplicateVlan network_body = {} network_body["network"] = {"name": name} operation_util.start_operation(context) network = client.create_network(network_body) network = network["network"] if ip_range: subnet_body = {} subnet_body["subnet"] = { # NOTE(Alex) "name": name + ".default_subnet", # Won't give it a name for now "network_id": network["id"], "ip_version": "4", "cidr": ip_range, "gateway_ip": gateway} result_data = client.create_subnet(subnet_body) subnet_id = result_data["subnet"]["id"] network = self._prepare_network(client, network) if 'description' in body: network["description"] = body["description"] network = self._add_db_item(context, network) self._process_callbacks( context, base_api._callback_reasons.post_add, network, subnet_id=subnet_id) return network
def _create_internet_route(self, context, network, body): client = clients.neutron(context) port, router = self._get_network_objects(client, network) public_network_id = network_api.API().get_public_network_id(context) external_gateway_info = {"network_id": public_network_id} router = client.add_gateway_router(router["id"], external_gateway_info)["router"] # TODO(alexey-mr): ?admin needed - router_gateway ports haven't tenant ports = client.list_ports(device_id=router["id"], device_owner="network:router_gateway") gateway_port = ports["ports"][0] route = self._add_gce_route(context, network, port, body, is_default=False, destination=gateway_port["id"], nexthop=ALL_IP_CIDR) route["network"] = network route["port"] = port route["external_gateway_info"] = external_gateway_info return route
def delete_item(self, context, name, scope=None): floating_ip = self._get_floating_ips(context, scope, name)[0] operation_util.start_operation(context) self._delete_db_item(context, floating_ip) clients.neutron(context).delete_floatingip(floating_ip["id"])