X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=yardstick%2Fcommon%2Fopenstack_utils.py;h=0d6afc54a0519fdd0c9c8b07d0678252b90647a2;hb=3fd6e8f9590ebb0accb402eb356aec24c15aa843;hp=e3f67baa5e484d4aa5f406703ee03c3d0d9d96e1;hpb=bdfdad8f8c064228b11238bf33a02a57829d6993;p=yardstick.git diff --git a/yardstick/common/openstack_utils.py b/yardstick/common/openstack_utils.py index e3f67baa5..0d6afc54a 100644 --- a/yardstick/common/openstack_utils.py +++ b/yardstick/common/openstack_utils.py @@ -429,19 +429,29 @@ def delete_keypair(nova_client, key): # pragma: no cover # ********************************************* # NEUTRON # ********************************************* -def get_network_id(shade_client, network_name): - networks = shade_client.list_networks({'name': network_name}) - if networks: - return networks[0]['id'] - - -def create_neutron_net(neutron_client, json_body): # pragma: no cover +def create_neutron_net(shade_client, network_name, shared=False, + admin_state_up=True, external=False, provider=None, + project_id=None): + """Create a neutron network. + + :param network_name:(string) name of the network being created. + :param shared:(bool) whether the network is shared. + :param admin_state_up:(bool) set the network administrative state. + :param external:(bool) whether this network is externally accessible. + :param provider:(dict) a dict of network provider options. + :param project_id:(string) specify the project ID this network + will be created on (admin-only). + :returns:(string) the network id. + """ try: - network = neutron_client.create_network(body=json_body) - return network['network']['id'] - except Exception: # pylint: disable=broad-except - log.error("Error [create_neutron_net(neutron_client)]") - raise Exception("operation error") + networks = shade_client.create_network( + name=network_name, shared=shared, admin_state_up=admin_state_up, + external=external, provider=provider, project_id=project_id) + return networks['id'] + except exc.OpenStackCloudException as o_exc: + log.error("Error [create_neutron_net(shade_client)]." + "Exception message, '%s'", o_exc.orig_message) + return None def delete_neutron_net(shade_client, network_id): @@ -452,31 +462,88 @@ def delete_neutron_net(shade_client, network_id): return False -def create_neutron_subnet(neutron_client, json_body): # pragma: no cover +def create_neutron_subnet(shade_client, network_name_or_id, cidr=None, + ip_version=4, enable_dhcp=False, subnet_name=None, + tenant_id=None, allocation_pools=None, + gateway_ip=None, disable_gateway_ip=False, + dns_nameservers=None, host_routes=None, + ipv6_ra_mode=None, ipv6_address_mode=None, + use_default_subnetpool=False): + """Create a subnet on a specified network. + + :param network_name_or_id:(string) the unique name or ID of the + attached network. If a non-unique name is + supplied, an exception is raised. + :param cidr:(string) the CIDR. + :param ip_version:(int) the IP version. + :param enable_dhcp:(bool) whether DHCP is enable. + :param subnet_name:(string) the name of the subnet. + :param tenant_id:(string) the ID of the tenant who owns the network. + :param allocation_pools: A list of dictionaries of the start and end + addresses for the allocation pools. + :param gateway_ip:(string) the gateway IP address. + :param disable_gateway_ip:(bool) whether gateway IP address is enabled. + :param dns_nameservers: A list of DNS name servers for the subnet. + :param host_routes: A list of host route dictionaries for the subnet. + :param ipv6_ra_mode:(string) IPv6 Router Advertisement mode. + Valid values are: 'dhcpv6-stateful', + 'dhcpv6-stateless', or 'slaac'. + :param ipv6_address_mode:(string) IPv6 address mode. + Valid values are: 'dhcpv6-stateful', + 'dhcpv6-stateless', or 'slaac'. + :param use_default_subnetpool:(bool) use the default subnetpool for + ``ip_version`` to obtain a CIDR. It is + required to pass ``None`` to the ``cidr`` + argument when enabling this option. + :returns:(string) the subnet id. + """ try: - subnet = neutron_client.create_subnet(body=json_body) - return subnet['subnets'][0]['id'] - except Exception: # pylint: disable=broad-except - log.error("Error [create_neutron_subnet") - raise Exception("operation error") + subnet = shade_client.create_subnet( + network_name_or_id, cidr=cidr, ip_version=ip_version, + enable_dhcp=enable_dhcp, subnet_name=subnet_name, + tenant_id=tenant_id, allocation_pools=allocation_pools, + gateway_ip=gateway_ip, disable_gateway_ip=disable_gateway_ip, + dns_nameservers=dns_nameservers, host_routes=host_routes, + ipv6_ra_mode=ipv6_ra_mode, ipv6_address_mode=ipv6_address_mode, + use_default_subnetpool=use_default_subnetpool) + return subnet['id'] + except exc.OpenStackCloudException as o_exc: + log.error("Error [create_neutron_subnet(shade_client)]. " + "Exception message: %s", o_exc.orig_message) + return None + +def create_neutron_router(shade_client, name=None, admin_state_up=True, + ext_gateway_net_id=None, enable_snat=None, + ext_fixed_ips=None, project_id=None): + """Create a logical router. -def create_neutron_router(neutron_client, json_body): # pragma: no cover + :param name:(string) the router name. + :param admin_state_up:(bool) the administrative state of the router. + :param ext_gateway_net_id:(string) network ID for the external gateway. + :param enable_snat:(bool) enable Source NAT (SNAT) attribute. + :param ext_fixed_ips: List of dictionaries of desired IP and/or subnet + on the external network. + :param project_id:(string) project ID for the router. + + :returns:(string) the router id. + """ try: - router = neutron_client.create_router(json_body) - return router['router']['id'] - except Exception: # pylint: disable=broad-except - log.error("Error [create_neutron_router(neutron_client)]") - raise Exception("operation error") + router = shade_client.create_router( + name, admin_state_up, ext_gateway_net_id, enable_snat, + ext_fixed_ips, project_id) + return router['id'] + except exc.OpenStackCloudException as o_exc: + log.error("Error [create_neutron_router(shade_client)]. " + "Exception message: %s", o_exc.orig_message) -def delete_neutron_router(neutron_client, router_id): # pragma: no cover +def delete_neutron_router(shade_client, router_id): try: - neutron_client.delete_router(router=router_id) - return True - except Exception: # pylint: disable=broad-except - log.error("Error [delete_neutron_router(neutron_client, '%s')]", - router_id) + return shade_client.delete_router(router_id) + except exc.OpenStackCloudException as o_exc: + log.error("Error [delete_neutron_router(shade_client, '%s')]. " + "Exception message: %s", router_id, o_exc.orig_message) return False @@ -490,151 +557,174 @@ def remove_gateway_router(neutron_client, router_id): # pragma: no cover return False -def remove_interface_router(neutron_client, router_id, subnet_id, - **json_body): # pragma: no cover - json_body.update({"subnet_id": subnet_id}) - try: - neutron_client.remove_interface_router(router=router_id, - body=json_body) - return True - except Exception: # pylint: disable=broad-except - log.error("Error [remove_interface_router(neutron_client, '%s', " - "'%s')]", router_id, subnet_id) - return False - - -def create_floating_ip(neutron_client, extnet_id): # pragma: no cover - props = {'floating_network_id': extnet_id} - try: - ip_json = neutron_client.create_floatingip({'floatingip': props}) - fip_addr = ip_json['floatingip']['floating_ip_address'] - fip_id = ip_json['floatingip']['id'] - except Exception: # pylint: disable=broad-except - log.error("Error [create_floating_ip(neutron_client)]") - return None - return {'fip_addr': fip_addr, 'fip_id': fip_id} +def remove_router_interface(shade_client, router, subnet_id=None, + port_id=None): + """Detach a subnet from an internal router interface. + At least one of subnet_id or port_id must be supplied. If you specify both + subnet and port ID, the subnet ID must correspond to the subnet ID of the + first IP address on the port specified by the port ID. + Otherwise an error occurs. -def delete_floating_ip(nova_client, floatingip_id): # pragma: no cover + :param router: The dict object of the router being changed + :param subnet_id:(string) The ID of the subnet to use for the interface + :param port_id:(string) The ID of the port to use for the interface + :returns: True on success + """ try: - nova_client.floating_ips.delete(floatingip_id) + shade_client.remove_router_interface( + router, subnet_id=subnet_id, port_id=port_id) return True - except Exception: # pylint: disable=broad-except - log.error("Error [delete_floating_ip(nova_client, '%s')]", - floatingip_id) + except exc.OpenStackCloudException as o_exc: + log.error("Error [remove_interface_router(shade_client)]. " + "Exception message: %s", o_exc.orig_message) return False -def get_security_groups(neutron_client): # pragma: no cover +def create_floating_ip(shade_client, network_name_or_id=None, server=None, + fixed_address=None, nat_destination=None, + port=None, wait=False, timeout=60): + """Allocate a new floating IP from a network or a pool. + + :param network_name_or_id: Name or ID of the network + that the floating IP should come from. + :param server: Server dict for the server to create + the IP for and to which it should be attached. + :param fixed_address: Fixed IP to attach the floating ip to. + :param nat_destination: Name or ID of the network + that the fixed IP to attach the floating + IP to should be on. + :param port: The port ID that the floating IP should be + attached to. Specifying a port conflicts with specifying a + server,fixed_address or nat_destination. + :param wait: Whether to wait for the IP to be active.Only applies + if a server is provided. + :param timeout: How long to wait for the IP to be active.Only + applies if a server is provided. + + :returns:Floating IP id and address + """ try: - security_groups = neutron_client.list_security_groups()[ - 'security_groups'] - return security_groups - except Exception: # pylint: disable=broad-except - log.error("Error [get_security_groups(neutron_client)]") - return None - - -def get_security_group_id(neutron_client, sg_name): # pragma: no cover - security_groups = get_security_groups(neutron_client) - id = '' - for sg in security_groups: - if sg['name'] == sg_name: - id = sg['id'] - break - return id + fip = shade_client.create_floating_ip( + network=network_name_or_id, server=server, + fixed_address=fixed_address, nat_destination=nat_destination, + port=port, wait=wait, timeout=timeout) + return {'fip_addr': fip['floating_ip_address'], 'fip_id': fip['id']} + except exc.OpenStackCloudException as o_exc: + log.error("Error [create_floating_ip(shade_client)]. " + "Exception message: %s", o_exc.orig_message) -def create_security_group(neutron_client, sg_name, - sg_description): # pragma: no cover - json_body = {'security_group': {'name': sg_name, - 'description': sg_description}} +def delete_floating_ip(shade_client, floating_ip_id, retry=1): try: - secgroup = neutron_client.create_security_group(json_body) - return secgroup['security_group'] - except Exception: # pylint: disable=broad-except - log.error("Error [create_security_group(neutron_client, '%s', " - "'%s')]", sg_name, sg_description) - return None + return shade_client.delete_floating_ip(floating_ip_id=floating_ip_id, + retry=retry) + except exc.OpenStackCloudException as o_exc: + log.error("Error [delete_floating_ip(shade_client,'%s')]. " + "Exception message: %s", floating_ip_id, o_exc.orig_message) + return False -def create_secgroup_rule(neutron_client, sg_id, direction, protocol, - port_range_min=None, port_range_max=None, - **json_body): # pragma: no cover - # We create a security group in 2 steps - # 1 - we check the format and set the json body accordingly - # 2 - we call neturon client to create the security group - - # Format check - json_body.update({'security_group_rule': {'direction': direction, - 'security_group_id': sg_id, 'protocol': protocol}}) - # parameters may be - # - both None => we do nothing - # - both Not None => we add them to the json description - # but one cannot be None is the other is not None - if (port_range_min is not None and port_range_max is not None): - # add port_range in json description - json_body['security_group_rule']['port_range_min'] = port_range_min - json_body['security_group_rule']['port_range_max'] = port_range_max - log.debug("Security_group format set (port range included)") - else: - # either both port range are set to None => do nothing - # or one is set but not the other => log it and return False - if port_range_min is None and port_range_max is None: - log.debug("Security_group format set (no port range mentioned)") - else: - log.error("Bad security group format." - "One of the port range is not properly set:" - "range min: %s, range max: %s", port_range_min, - port_range_max) - return False +def create_security_group_rule(shade_client, secgroup_name_or_id, + port_range_min=None, port_range_max=None, + protocol=None, remote_ip_prefix=None, + remote_group_id=None, direction='ingress', + ethertype='IPv4', project_id=None): + """Create a new security group rule + + :param secgroup_name_or_id:(string) The security group name or ID to + associate with this security group rule. If a + non-unique group name is given, an exception is + raised. + :param port_range_min:(int) The minimum port number in the range that is + matched by the security group rule. If the protocol + is TCP or UDP, this value must be less than or equal + to the port_range_max attribute value. If nova is + used by the cloud provider for security groups, then + a value of None will be transformed to -1. + :param port_range_max:(int) The maximum port number in the range that is + matched by the security group rule. The + port_range_min attribute constrains the + port_range_max attribute. If nova is used by the + cloud provider for security groups, then a value of + None will be transformed to -1. + :param protocol:(string) The protocol that is matched by the security group + rule. Valid values are None, tcp, udp, and icmp. + :param remote_ip_prefix:(string) The remote IP prefix to be associated with + this security group rule. This attribute matches + the specified IP prefix as the source IP address of + the IP packet. + :param remote_group_id:(string) The remote group ID to be associated with + this security group rule. + :param direction:(string) Ingress or egress: The direction in which the + security group rule is applied. + :param ethertype:(string) Must be IPv4 or IPv6, and addresses represented + in CIDR must match the ingress or egress rules. + :param project_id:(string) Specify the project ID this security group will + be created on (admin-only). + + :returns: True on success. + """ - # Create security group using neutron client try: - neutron_client.create_security_group_rule(json_body) + shade_client.create_security_group_rule( + secgroup_name_or_id, port_range_min=port_range_min, + port_range_max=port_range_max, protocol=protocol, + remote_ip_prefix=remote_ip_prefix, remote_group_id=remote_group_id, + direction=direction, ethertype=ethertype, project_id=project_id) return True - except Exception: # pylint: disable=broad-except - log.exception("Impossible to create_security_group_rule," - "security group rule probably already exists") + except exc.OpenStackCloudException as op_exc: + log.error("Failed to create_security_group_rule(shade_client). " + "Exception message: %s", op_exc.orig_message) return False -def create_security_group_full(neutron_client, sg_name, - sg_description): # pragma: no cover - sg_id = get_security_group_id(neutron_client, sg_name) - if sg_id != '': - log.info("Using existing security group '%s'...", sg_name) - else: - log.info("Creating security group '%s'...", sg_name) - SECGROUP = create_security_group(neutron_client, - sg_name, - sg_description) - if not SECGROUP: - log.error("Failed to create the security group...") - return None +def create_security_group_full(shade_client, sg_name, + sg_description, project_id=None): + security_group = shade_client.get_security_group(sg_name) - sg_id = SECGROUP['id'] - - log.debug("Security group '%s' with ID=%s created successfully.", - SECGROUP['name'], sg_id) - - log.debug("Adding ICMP rules in security group '%s'...", sg_name) - if not create_secgroup_rule(neutron_client, sg_id, - 'ingress', 'icmp'): - log.error("Failed to create the security group rule...") - return None - - log.debug("Adding SSH rules in security group '%s'...", sg_name) - if not create_secgroup_rule( - neutron_client, sg_id, 'ingress', 'tcp', '22', '22'): - log.error("Failed to create the security group rule...") - return None - - if not create_secgroup_rule( - neutron_client, sg_id, 'egress', 'tcp', '22', '22'): - log.error("Failed to create the security group rule...") - return None - return sg_id + if security_group: + log.info("Using existing security group '%s'...", sg_name) + return security_group['id'] + + log.info("Creating security group '%s'...", sg_name) + try: + security_group = shade_client.create_security_group( + sg_name, sg_description, project_id=project_id) + except (exc.OpenStackCloudException, + exc.OpenStackCloudUnavailableFeature) as op_exc: + log.error("Error [create_security_group(shade_client, %s, %s)]. " + "Exception message: %s", sg_name, sg_description, + op_exc.orig_message) + return + + log.debug("Security group '%s' with ID=%s created successfully.", + security_group['name'], security_group['id']) + + log.debug("Adding ICMP rules in security group '%s'...", sg_name) + if not create_security_group_rule(shade_client, security_group['id'], + direction='ingress', protocol='icmp'): + log.error("Failed to create the security group rule...") + shade_client.delete_security_group(sg_name) + return + + log.debug("Adding SSH rules in security group '%s'...", sg_name) + if not create_security_group_rule(shade_client, security_group['id'], + direction='ingress', protocol='tcp', + port_range_min='22', + port_range_max='22'): + log.error("Failed to create the security group rule...") + shade_client.delete_security_group(sg_name) + return + + if not create_security_group_rule(shade_client, security_group['id'], + direction='egress', protocol='tcp', + port_range_min='22', + port_range_max='22'): + log.error("Failed to create the security group rule...") + shade_client.delete_security_group(sg_name) + return + return security_group['id'] # ********************************************* @@ -684,6 +774,18 @@ def delete_image(glance_client, image_id): # pragma: no cover return True +def list_images(shade_client=None): + if shade_client is None: + shade_client = get_shade_client() + + try: + return shade_client.list_images() + except exc.OpenStackCloudException as o_exc: + log.error("Error [list_images(shade_client)]." + "Exception message, '%s'", o_exc.orig_message) + return False + + # ********************************************* # CINDER # *********************************************