872 lines
26 KiB
Python
872 lines
26 KiB
Python
#
|
|
# Copyright (c) 2015-2016 Wind River Systems, Inc.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
import json
|
|
import six
|
|
import uuid
|
|
|
|
from nfv_common import debug
|
|
from nfv_common.helpers import Constant
|
|
from nfv_common.helpers import Constants
|
|
from nfv_common.helpers import Singleton
|
|
|
|
from nfv_plugins.nfvi_plugins.openstack.objects import OPENSTACK_SERVICE
|
|
from nfv_plugins.nfvi_plugins.openstack.rest_api import rest_api_request
|
|
|
|
DLOG = debug.debug_get_logger('nfv_plugins.nfvi_plugins.openstack.neutron')
|
|
|
|
|
|
@six.add_metaclass(Singleton)
|
|
class NeutronExtensionNames(Constants):
|
|
"""
|
|
Neutron Extension Name Constants
|
|
"""
|
|
HOST = Constant('host')
|
|
AGENT = Constant('agent')
|
|
|
|
|
|
@six.add_metaclass(Singleton)
|
|
class NetworkAdministrativeState(Constants):
|
|
"""
|
|
NETWORK ADMINISTRATIVE STATE Constants
|
|
"""
|
|
UP = Constant(True)
|
|
DOWN = Constant(False)
|
|
|
|
|
|
@six.add_metaclass(Singleton)
|
|
class NetworkStatus(Constants):
|
|
"""
|
|
NETWORK STATUS Constants
|
|
"""
|
|
ACTIVE = Constant('ACTIVE')
|
|
BUILD = Constant('BUILD')
|
|
DOWN = Constant('DOWN')
|
|
ERROR = Constant('ERROR')
|
|
|
|
|
|
@six.add_metaclass(Singleton)
|
|
class AgentType(Constants):
|
|
"""
|
|
AGENT TYPE Constants
|
|
"""
|
|
L3 = Constant('L3 agent')
|
|
DHCP = Constant('DHCP agent')
|
|
|
|
|
|
@six.add_metaclass(Singleton)
|
|
class VnicType(Constants):
|
|
"""
|
|
VNIC TYPE constants
|
|
"""
|
|
NORMAL = Constant('normal')
|
|
DIRECT = Constant('direct')
|
|
MACVTAP = Constant('macvtap')
|
|
BAREMETAL = Constant('baremetal')
|
|
DIRECT_PHYSICAL = Constant('direct-physical')
|
|
VIRTIO_FORWARDER = Constant('virtio-forwarder')
|
|
|
|
|
|
# Constant Instantiation
|
|
EXTENSION_NAMES = NeutronExtensionNames()
|
|
NETWORK_ADMIN_STATE = NetworkAdministrativeState()
|
|
NETWORK_STATUS = NetworkStatus()
|
|
AGENT_TYPE = AgentType()
|
|
VNIC_TYPE = VnicType()
|
|
|
|
|
|
def get_network_agents(token):
|
|
"""
|
|
Get Network Agent information for all agents.
|
|
"""
|
|
url, api_cmd, api_cmd_headers, result_data = _get_network_agents(
|
|
token, None)
|
|
|
|
return result_data
|
|
|
|
|
|
def get_dhcp_agent_networks(token, agent_id):
|
|
"""
|
|
Get all networks hosted by a particular dhcp agent
|
|
Paging not supported by API.
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/agents/" + agent_id + "/dhcp-networks?fields=id&fields=provider%3Aphysical_network"
|
|
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
response = rest_api_request(token, "GET", api_cmd, api_cmd_headers)
|
|
result_data = response.result_data['networks']
|
|
|
|
return result_data
|
|
|
|
|
|
def add_network_to_dhcp_agent(token, agent_id, network_id):
|
|
"""
|
|
Schedule a network on a DHCP agent
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/agents/" + agent_id + "/dhcp-networks"
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
api_cmd_payload = dict()
|
|
api_cmd_payload['network_id'] = network_id
|
|
|
|
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
|
|
json.dumps(api_cmd_payload))
|
|
|
|
return response
|
|
|
|
|
|
def remove_network_from_dhcp_agent(token, agent_id, network_id):
|
|
"""
|
|
Unschedule a network from a DHCP agent
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/agents/" + agent_id + "/dhcp-networks/" + network_id
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
response = rest_api_request(token, "DELETE", api_cmd, api_cmd_headers)
|
|
|
|
return response
|
|
|
|
|
|
def get_agent_routers(token, agent_id):
|
|
"""
|
|
Get all routers hosted by a particular agent
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/agents/" + agent_id + "/l3-routers?fields=id"
|
|
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
response = rest_api_request(token, "GET", api_cmd, api_cmd_headers)
|
|
result_data = response.result_data['routers']
|
|
|
|
return result_data
|
|
|
|
|
|
def add_router_to_agent(token, agent_id, router_id):
|
|
"""
|
|
Schedule a router on an L3 agent
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/agents/" + agent_id + "/l3-routers"
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
api_cmd_payload = dict()
|
|
api_cmd_payload['router_id'] = router_id
|
|
|
|
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
|
|
json.dumps(api_cmd_payload))
|
|
|
|
return response
|
|
|
|
|
|
def remove_router_from_agent(token, agent_id, router_id):
|
|
"""
|
|
Unschedule a router from an L3 agent
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/agents/" + agent_id + "/l3-routers/" + router_id
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
response = rest_api_request(token, "DELETE", api_cmd, api_cmd_headers)
|
|
|
|
return response
|
|
|
|
|
|
def get_router_ports(token, router_id):
|
|
"""
|
|
Get port information for particular router
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/ports?device_id=" + router_id
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
response = rest_api_request(token, "GET", api_cmd, api_cmd_headers)
|
|
|
|
return response
|
|
|
|
|
|
def get_physical_network(token, network_id):
|
|
"""
|
|
Get the physical network of a network
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/networks/" + network_id + "?fields=provider%3Aphysical_network"
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
response = rest_api_request(token, "GET", api_cmd, api_cmd_headers)
|
|
result_data = response.result_data['network']
|
|
|
|
return result_data
|
|
|
|
|
|
def _get_network_agents(token, host_name):
|
|
"""
|
|
Get network agents of a host
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/agents"
|
|
if host_name is not None:
|
|
api_cmd = api_cmd + "?host=" + host_name
|
|
else:
|
|
# if host_name is None, we are to retrieve information
|
|
# on all agents on all hosts.
|
|
fields_qualifier = "?fields=id&fields=host&fields=agent_type&fields=alive&fields=admin_state_up"
|
|
api_cmd = api_cmd + fields_qualifier
|
|
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
response = rest_api_request(token, "GET", api_cmd, api_cmd_headers)
|
|
result_data = response.result_data['agents']
|
|
|
|
return url, api_cmd, api_cmd_headers, result_data
|
|
|
|
|
|
def lookup_extension(extension_name, extensions):
|
|
"""
|
|
Lookup an extension for OpenStack Neutron
|
|
"""
|
|
if extensions is None:
|
|
return None
|
|
|
|
extension_list = extensions.get('extensions', None)
|
|
if extension_list is None:
|
|
return None
|
|
|
|
for extension in extension_list:
|
|
alias = extension.get('alias', None)
|
|
if alias is not None:
|
|
if alias == extension_name:
|
|
return extension
|
|
|
|
return None
|
|
|
|
|
|
def get_extensions(token):
|
|
"""
|
|
Asks OpenStack Neutron for a list of extensions
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
return dict()
|
|
|
|
api_cmd = url + "/v2.0/extensions.json"
|
|
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
response = rest_api_request(token, "GET", api_cmd)
|
|
return response
|
|
|
|
|
|
def get_networks(token, page_limit=None, next_page=None):
|
|
"""
|
|
Asks OpenStack Neutron for a list of networks
|
|
"""
|
|
if next_page is None:
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/networks"
|
|
|
|
if page_limit is not None:
|
|
api_cmd += "?limit=%s" % page_limit
|
|
else:
|
|
api_cmd = next_page
|
|
|
|
api_cmd_headers = dict()
|
|
|
|
response = rest_api_request(token, "GET", api_cmd, api_cmd_headers)
|
|
return response
|
|
|
|
|
|
def create_network(token, network_name, network_type, segmentation_id,
|
|
physical_network, shared):
|
|
"""
|
|
Asks OpenStack Neutron to create a network
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/networks"
|
|
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
network = dict()
|
|
network['name'] = network_name
|
|
network['shared'] = shared
|
|
|
|
if 'flat' == network_type:
|
|
network['provider:network_type'] = network_type
|
|
network['provider:physical_network'] = physical_network
|
|
else:
|
|
network['provider:network_type'] = network_type
|
|
network['provider:segmentation_id'] = segmentation_id
|
|
network['provider:physical_network'] = physical_network
|
|
|
|
api_cmd_payload = dict()
|
|
api_cmd_payload['network'] = network
|
|
|
|
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
|
|
json.dumps(api_cmd_payload))
|
|
return response
|
|
|
|
|
|
def update_network(token, network_id, admin_state=None, shared=None):
|
|
"""
|
|
Asks OpenStack Neutron to update a network
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/networks/%s" % network_id
|
|
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
network = dict()
|
|
|
|
if admin_state is not None:
|
|
if NETWORK_ADMIN_STATE.UP == admin_state:
|
|
network['admin_state_up'] = True
|
|
else:
|
|
network['admin_state_up'] = False
|
|
|
|
if shared is not None:
|
|
network['shared'] = shared
|
|
|
|
api_cmd_payload = dict()
|
|
api_cmd_payload['network'] = network
|
|
|
|
response = rest_api_request(token, "PUT", api_cmd, api_cmd_headers,
|
|
json.dumps(api_cmd_payload))
|
|
return response
|
|
|
|
|
|
def delete_network(token, network_id):
|
|
"""
|
|
Asks OpenStack Neutron to delete a network
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/networks/%s" % network_id
|
|
|
|
api_cmd_headers = dict()
|
|
|
|
response = rest_api_request(token, "DELETE", api_cmd, api_cmd_headers)
|
|
return response
|
|
|
|
|
|
def get_network(token, network_id):
|
|
"""
|
|
Asks OpenStack Neutron for network details
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/networks/%s" % network_id
|
|
|
|
api_cmd_headers = dict()
|
|
|
|
response = rest_api_request(token, "GET", api_cmd, api_cmd_headers)
|
|
return response
|
|
|
|
|
|
def get_subnets(token, page_limit=None, next_page=None):
|
|
"""
|
|
Ask OpenStack Neutron for a list of subnets
|
|
"""
|
|
if next_page is None:
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/subnets"
|
|
|
|
if page_limit is not None:
|
|
api_cmd += "?limit=%s" % page_limit
|
|
else:
|
|
api_cmd = next_page
|
|
|
|
api_cmd_headers = dict()
|
|
|
|
response = rest_api_request(token, "GET", api_cmd, api_cmd_headers)
|
|
return response
|
|
|
|
|
|
def create_subnet(token, network_id, subnet_name, ip_version, cidr,
|
|
gateway_ip, dhcp_enabled):
|
|
"""
|
|
Ask OpenStack Neutron to create a subnet
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/subnets"
|
|
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
subnet = dict()
|
|
if subnet_name is not None:
|
|
subnet['name'] = subnet_name
|
|
|
|
subnet['network_id'] = network_id
|
|
subnet['ip_version'] = ip_version
|
|
subnet['cidr'] = cidr
|
|
subnet['enable_dhcp'] = dhcp_enabled
|
|
|
|
if gateway_ip is not None:
|
|
subnet['gateway_ip'] = gateway_ip
|
|
|
|
api_cmd_payload = dict()
|
|
api_cmd_payload['subnet'] = subnet
|
|
|
|
response = rest_api_request(token, "POST", api_cmd, api_cmd_headers,
|
|
json.dumps(api_cmd_payload))
|
|
return response
|
|
|
|
|
|
def update_subnet(token, subnet_id, gateway_ip=None, delete_gateway=False,
|
|
dhcp_enabled=None):
|
|
"""
|
|
Ask OpenStack Neutron to update a subnet
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/subnets/%s" % subnet_id
|
|
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
subnet = dict()
|
|
|
|
if gateway_ip is not None:
|
|
subnet['gateway_ip'] = gateway_ip
|
|
|
|
elif delete_gateway:
|
|
subnet['gateway_ip'] = None
|
|
|
|
if dhcp_enabled is not None:
|
|
subnet['enable_dhcp'] = dhcp_enabled
|
|
|
|
api_cmd_payload = dict()
|
|
api_cmd_payload['subnet'] = subnet
|
|
|
|
response = rest_api_request(token, "PUT", api_cmd, api_cmd_headers,
|
|
json.dumps(api_cmd_payload))
|
|
return response
|
|
|
|
|
|
def delete_subnet(token, subnet_id):
|
|
"""
|
|
Asks OpenStack Neutron to delete a subnet
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/subnets/%s" % subnet_id
|
|
|
|
api_cmd_headers = dict()
|
|
|
|
response = rest_api_request(token, "DELETE", api_cmd, api_cmd_headers)
|
|
return response
|
|
|
|
|
|
def get_subnet(token, subnet_id):
|
|
"""
|
|
Asks OpenStack Neutron for subnet details
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/subnets/%s" % subnet_id
|
|
|
|
api_cmd_headers = dict()
|
|
|
|
response = rest_api_request(token, "GET", api_cmd, api_cmd_headers)
|
|
return response
|
|
|
|
|
|
def get_ports_for_instance(token, instance_uuid):
|
|
"""
|
|
Ask OpenStack Neutron for a list of ports attached to an instance
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/ports?device_id=%s" % (instance_uuid)
|
|
|
|
api_cmd_headers = dict()
|
|
|
|
response = rest_api_request(token, "GET", api_cmd, api_cmd_headers)
|
|
return response
|
|
|
|
|
|
def delete_host_services(token, host_uuid):
|
|
"""
|
|
Asks OpenStack Neutron to delete a host
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/hosts/%s" % host_uuid
|
|
|
|
api_cmd_headers = dict()
|
|
|
|
# WARNING: Any change to the timeout must be reflected in the config.ini
|
|
# file for the nfvi plugins.
|
|
response = rest_api_request(token, "DELETE", api_cmd, api_cmd_headers,
|
|
timeout_in_secs=40)
|
|
return response
|
|
|
|
|
|
def delete_network_agents(token, host_name):
|
|
"""
|
|
Asks OpenStack Neutron to delete agents for a host
|
|
"""
|
|
try:
|
|
url, api_cmd, api_cmd_headers, result_data = _get_network_agents(
|
|
token, host_name)
|
|
|
|
num_agents_found = 0
|
|
supported_agents = [AGENT_TYPE.L3, AGENT_TYPE.DHCP]
|
|
for agent in result_data:
|
|
if (agent['host'] == host_name and
|
|
agent['agent_type'] in supported_agents):
|
|
api_cmd = url + "/v2.0/agents/%s" % agent['id']
|
|
rest_api_request(token, "DELETE", api_cmd,
|
|
api_cmd_headers)
|
|
num_agents_found = num_agents_found + 1
|
|
|
|
except Exception as e:
|
|
DLOG.exception("Caught exception trying to delete host %s agent: %s" %
|
|
(host_name, e))
|
|
return False
|
|
|
|
if num_agents_found != len(supported_agents):
|
|
DLOG.warn("Host %s, did not find expected agents to delete"
|
|
% host_name)
|
|
|
|
return True
|
|
|
|
|
|
def delete_host_services_by_name(token, host_name, host_uuid,
|
|
only_if_changed=False):
|
|
"""
|
|
Asks OpenStack Neutron to delete a host by name
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/hosts.json?fields=id&fields=name"
|
|
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
response = rest_api_request(token, "GET", api_cmd)
|
|
for host in response.result_data['hosts']:
|
|
if host['name'] == host_name:
|
|
if only_if_changed:
|
|
if host['id'] != host_uuid:
|
|
api_cmd = url + "/v2.0/hosts/%s" % host['id']
|
|
rest_api_request(token, "DELETE", api_cmd)
|
|
else:
|
|
api_cmd = url + "/v2.0/hosts/%s" % host['id']
|
|
rest_api_request(token, "DELETE", api_cmd)
|
|
|
|
|
|
def enable_host_services(token, host_uuid):
|
|
"""
|
|
Asks OpenStack Neutron to enable a host
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/hosts/%s" % host_uuid
|
|
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
payload = dict()
|
|
payload['availability'] = 'up'
|
|
|
|
api_cmd_payload = dict()
|
|
api_cmd_payload['host'] = payload
|
|
|
|
response = rest_api_request(token, "PUT", api_cmd, api_cmd_headers,
|
|
json.dumps(api_cmd_payload))
|
|
return response
|
|
|
|
|
|
def enable_network_agents(token, host_name):
|
|
"""
|
|
Asks OpenStack Neutron to enable agents on a host.
|
|
Set admin_state_up to True for all agents found for a host, but
|
|
ensure that the set of supported agents that are managed
|
|
are all alive and admin_state_up is successfully set to True
|
|
before declaring success.
|
|
"""
|
|
try:
|
|
url, api_cmd, api_cmd_headers, result_data = _get_network_agents(
|
|
token, host_name)
|
|
|
|
payload = dict()
|
|
payload['admin_state_up'] = True
|
|
api_cmd_payload = dict()
|
|
api_cmd_payload['agent'] = payload
|
|
|
|
num_agents_found = 0
|
|
all_enabled = True
|
|
supported_agents = [AGENT_TYPE.L3, AGENT_TYPE.DHCP]
|
|
for agent in result_data:
|
|
if agent['host'] == host_name:
|
|
alive = agent.get('alive', False)
|
|
supported = agent['agent_type'] in supported_agents
|
|
if (not alive) and supported:
|
|
DLOG.error("Host %s %s not alive" %
|
|
(host_name, agent['agent_type']))
|
|
return False
|
|
admin_up = agent['admin_state_up']
|
|
if not admin_up:
|
|
api_cmd = url + "/v2.0/agents/%s" % agent['id']
|
|
response = rest_api_request(token, "PUT", api_cmd,
|
|
api_cmd_headers,
|
|
json.dumps(api_cmd_payload))
|
|
admin_up = response.result_data['agent']['admin_state_up']
|
|
if supported:
|
|
all_enabled = all_enabled and admin_up
|
|
num_agents_found = num_agents_found + 1
|
|
|
|
except Exception as e:
|
|
DLOG.exception("Caught exception trying to enable host %s agents: %s" %
|
|
(host_name, e))
|
|
return False
|
|
|
|
if num_agents_found != len(supported_agents):
|
|
DLOG.error("Host %s, did not find expected agents to enable"
|
|
% host_name)
|
|
return False
|
|
|
|
return all_enabled
|
|
|
|
|
|
def disable_host_services(token, host_uuid):
|
|
"""
|
|
Asks OpenStack Neutron to disable a host
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/hosts/%s" % host_uuid
|
|
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
payload = dict()
|
|
payload['availability'] = 'down'
|
|
|
|
api_cmd_payload = dict()
|
|
api_cmd_payload['host'] = payload
|
|
|
|
# WARNING: Any change to the timeout must be reflected in the config.ini
|
|
# file for the nfvi plugins.
|
|
response = rest_api_request(token, "PUT", api_cmd, api_cmd_headers,
|
|
json.dumps(api_cmd_payload),
|
|
timeout_in_secs=40)
|
|
return response
|
|
|
|
|
|
def disable_network_agents(token, host_name):
|
|
"""
|
|
Asks OpenStack Neutron to disable the set of supported agents
|
|
that are managed on a host by setting the admin_state_up parameter
|
|
to False. Other agents are left alone.
|
|
"""
|
|
try:
|
|
url, api_cmd, api_cmd_headers, result_data = _get_network_agents(
|
|
token, host_name)
|
|
|
|
payload = dict()
|
|
payload['admin_state_up'] = False
|
|
api_cmd_payload = dict()
|
|
api_cmd_payload['agent'] = payload
|
|
|
|
num_agents_found = 0
|
|
all_disabled = True
|
|
supported_agents = [AGENT_TYPE.L3, AGENT_TYPE.DHCP]
|
|
for agent in result_data:
|
|
if (agent['host'] == host_name and
|
|
agent['agent_type'] in supported_agents):
|
|
api_cmd = url + "/v2.0/agents/%s" % agent['id']
|
|
response = rest_api_request(token, "PUT", api_cmd,
|
|
api_cmd_headers,
|
|
json.dumps(api_cmd_payload))
|
|
all_disabled = all_disabled and not \
|
|
response.result_data['agent']['admin_state_up']
|
|
num_agents_found = num_agents_found + 1
|
|
|
|
except Exception as e:
|
|
DLOG.exception("Caught exception trying to disable host %s agents: %s" %
|
|
(host_name, e))
|
|
return False
|
|
|
|
if num_agents_found != len(supported_agents):
|
|
DLOG.error("Host %s, did not find expected agents to disable"
|
|
% host_name)
|
|
return False
|
|
|
|
return all_disabled
|
|
|
|
|
|
def query_host_services(token, host_name):
|
|
"""
|
|
Asks OpenStack Neutron for the state of services on a host
|
|
"""
|
|
url = token.get_service_url(OPENSTACK_SERVICE.NEUTRON)
|
|
if url is None:
|
|
raise ValueError("OpenStack Neutron URL is invalid")
|
|
|
|
api_cmd = url + "/v2.0/hosts.json?fields=id&name=%s" % host_name
|
|
|
|
api_cmd_headers = dict()
|
|
api_cmd_headers['Content-Type'] = "application/json"
|
|
|
|
response = rest_api_request(token, "GET", api_cmd)
|
|
if 0 == len(response.result_data['hosts']):
|
|
return None
|
|
|
|
result_data = response.result_data['hosts'][0]
|
|
host_id = result_data['id']
|
|
|
|
# Deal with getting an invalid uuid
|
|
try:
|
|
uuid.UUID(host_id)
|
|
|
|
except (TypeError, ValueError, AttributeError):
|
|
DLOG.error("Neutron host query failed for %s, defaulting return "
|
|
"to down." % host_name)
|
|
return 'down'
|
|
|
|
api_cmd = url + "/v2.0/hosts/%s" % host_id
|
|
|
|
response = rest_api_request(token, "GET", api_cmd)
|
|
result_data = response.result_data['host']
|
|
host_state = result_data['availability']
|
|
|
|
# Deal with invalid return value
|
|
if not (host_state == 'up' or host_state == 'down'):
|
|
DLOG.error("Neutron availability state query failed for %s, defaulting "
|
|
"return to down." % host_name)
|
|
host_state = 'down'
|
|
|
|
return host_state
|
|
|
|
|
|
def query_network_agents(token, host_name, check_fully_up):
|
|
"""
|
|
Asks OpenStack Neutron for the state of the supported agents
|
|
that are managed on a host.
|
|
Input parameter check_fully_up set to True will check for
|
|
both alive and admin_state_up, otherwise only alive is checked.
|
|
"""
|
|
url, api_cmd, api_cmd_headers, result_data = _get_network_agents(
|
|
token, host_name)
|
|
agent_state = 'up'
|
|
alive = False
|
|
admin_state_up = False
|
|
supported_agents = [AGENT_TYPE.L3, AGENT_TYPE.DHCP]
|
|
for supported_agent in supported_agents:
|
|
found = False
|
|
for agent in result_data:
|
|
agent_type = agent.get('agent_type', '')
|
|
host = agent.get('host', '')
|
|
if (agent_type == supported_agent) and (host == host_name):
|
|
DLOG.verbose("found agent %s for host %s" %
|
|
(supported_agent, host_name))
|
|
alive = agent.get('alive', False)
|
|
admin_state_up = agent.get('admin_state_up', False)
|
|
# found the agent of interest.
|
|
found = True
|
|
break
|
|
if found:
|
|
if check_fully_up:
|
|
if not (alive and admin_state_up):
|
|
DLOG.verbose("host %s agent %s not fully up. alive: %s,"
|
|
" admin_state_up: %s" %
|
|
(host_name, supported_agent,
|
|
alive, admin_state_up))
|
|
agent_state = 'down'
|
|
break
|
|
else:
|
|
if not alive:
|
|
DLOG.verbose("host %s agent %s not alive" %
|
|
(host_name, supported_agent))
|
|
agent_state = 'down'
|
|
break
|
|
else:
|
|
DLOG.error("host %s agent %s not present" %
|
|
(host_name, supported_agent))
|
|
agent_state = 'down'
|
|
break
|
|
|
|
return agent_state
|