Heat: support create and attach volume in heat type context 61/37961/5
authorJingLu5 <lvjing5@huawei.com>
Mon, 24 Jul 2017 01:39:57 +0000 (01:39 +0000)
committerJing Lu <lvjing5@huawei.com>
Sat, 29 Jul 2017 04:39:36 +0000 (04:39 +0000)
JIRA: YARDSTICK-756

Some test scenarios require VM with volume attached.
This work is about supporting create and attach volume in heat type context.

context:
  name: demo
  image: cirros-0.3.5
  flavor: yardstick-flavor
  user: cirros

  placement_groups:
    pgrp1:
      policy: "availability"

  servers:
    athena:
      floating_ip: true
      # per-vm inline volume definition. if no volume size specified, then this
      # volume should be an existing volume in the openstack environment
      volume: yardstick-volume
      placement: "pgrp1"
    ares:
      # per-vm inline volume definition. if volume size is specified, then this
      # volume will be crated and attach to the vm
      volume:
        name: test-volume
        size: 10
      # volume mountpoint is also configurable
      volume_mountpoint: /dev/vdb
      placement: "pgrp1"

  networks:
    test:
      cidr: '10.0.1.0/24'

Change-Id: Ief87b313980a59eac229eb4780d93ffc929ceb66
Signed-off-by: JingLu5 <lvjing5@huawei.com>
samples/fio_volume.yaml [new file with mode: 0644]
yardstick/benchmark/contexts/model.py
yardstick/common/openstack_utils.py
yardstick/orchestrator/heat.py

diff --git a/samples/fio_volume.yaml b/samples/fio_volume.yaml
new file mode 100644 (file)
index 0000000..edb3837
--- /dev/null
@@ -0,0 +1,74 @@
+##############################################################################
+# Copyright (c) 2017 Huawei Technologies Co.,Ltd and others.
+#
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Apache License, Version 2.0
+# which accompanies this distribution, and is available at
+# http://www.apache.org/licenses/LICENSE-2.0
+##############################################################################
+---
+# Sample benchmark task config file
+# measure storage performance using fio
+#
+# For this sample just like running the command below on the test vm and
+# getting benchmark info back to the yardstick.
+#
+# sudo fio -filename=/home/ubuntu/data.raw -bs=4k -ipdepth=1 -rw=rw \
+#          -ramp_time=10 -runtime=60 -name=yardstick-fio -ioengine=libaio \
+#          -direct=1 -group_reporting -numjobs=1 -time_based \
+#          --output-format=json
+
+schema: "yardstick:task:0.1"
+
+{% set rw = rw or "randrw" %}
+{% set bs = bs or "8k" %}
+{% set size = size or "100g" %}
+{% set rwmixwrite = rwmixwrite or "50" %}
+{% set numjobs = numjobs or "1" %}
+{% set direct = direct or "1" %}
+
+scenarios:
+-
+  type: Fio
+  options:
+    filename: /dev/vdb
+    bs: {{bs}}
+    rw: {{rw}}
+    size: {{size}}
+    rwmixwrite: {{rwmixwrite}}
+    numjobs: {{numjobs}}
+    direct: {{direct}}
+    ramp_time: 10
+
+  host: fio.fio_volume
+
+  runner:
+    type: Duration
+    duration: 60
+    interval: 1
+
+  sla:
+    read_bw: 6000
+    read_iops: 1500
+    read_lat: 500.1
+    write_bw: 6000
+    write_iops: 1500
+    write_lat: 500.1
+    action: monitor
+
+context:
+  name: fio_volume
+  image: yardstick-image
+  flavor: yardstick-flavor
+  user: ubuntu
+  servers:
+    fio:
+      volume:
+        name: fio-volume
+        size: 200
+      volume_mountpoint: "/dev/vdb"
+      floating_ip: true
+  networks:
+    test:
+      cidr: "10.0.1.0/24"
+      port_security_enabled: true
index ec47432..0bf85d0 100644 (file)
@@ -184,6 +184,14 @@ class Server(Object):     # pragma: no cover
             self.placement_groups.append(pg)
             pg.add_member(self.stack_name)
 
+        self.volume = None
+        if "volume" in attrs:
+            self.volume = attrs.get("volume")
+
+        self.volume_mountpoint = None
+        if "volume_mountpoint" in attrs:
+            self.volume_mountpoint = attrs.get("volume_mountpoint")
+
         # support servergroup attr
         self.server_group = None
         sg = attrs.get("server_group")
@@ -283,6 +291,17 @@ class Server(Object):     # pragma: no cover
             else:
                 self.flavor_name = self.flavor
 
+        if self.volume:
+            if isinstance(self.volume, dict):
+                self.volume["name"] = \
+                    self.volume.setdefault("name", server_name + "-volume")
+                template.add_volume(**self.volume)
+                template.add_volume_attachment(server_name, self.volume["name"],
+                                               mountpoint=self.volume_mountpoint)
+            else:
+                template.add_volume_attachment(server_name, self.volume,
+                                               mountpoint=self.volume_mountpoint)
+
         template.add_server(server_name, self.image, flavor=self.flavor_name,
                             flavors=self.context.flavors,
                             ports=port_name_list,
index 8787e60..f027b79 100644 (file)
@@ -15,6 +15,7 @@ import logging
 
 from keystoneauth1 import loading
 from keystoneauth1 import session
+from cinderclient import client as cinderclient
 from novaclient import client as novaclient
 from glanceclient import client as glanceclient
 from neutronclient.neutron import client as neutronclient
@@ -108,6 +109,21 @@ def get_heat_api_version():     # pragma: no cover
         return api_version
 
 
+def get_cinder_client_version():      # pragma: no cover
+    try:
+        api_version = os.environ['OS_VOLUME_API_VERSION']
+    except KeyError:
+        return DEFAULT_API_VERSION
+    else:
+        log.info("OS_VOLUME_API_VERSION is set in env as '%s'", api_version)
+        return api_version
+
+
+def get_cinder_client():      # pragma: no cover
+    sess = get_session()
+    return cinderclient.Client(get_cinder_client_version(), session=sess)
+
+
 def get_nova_client_version():      # pragma: no cover
     try:
         api_version = os.environ['OS_COMPUTE_API_VERSION']
@@ -430,3 +446,11 @@ def get_port_id_by_ip(neutron_client, ip_address):      # pragma: no cover
 def get_image_id(glance_client, image_name):    # pragma: no cover
     images = glance_client.images.list()
     return next((i.id for i in images if i.name == image_name), None)
+
+
+# *********************************************
+#   CINDER
+# *********************************************
+def get_volume_id(volume_name):    # pragma: no cover
+    volumes = get_cinder_client().volumes.list()
+    return next((v.id for v in volumes if v.name == volume_name), None)
index 95ca0ad..05e3597 100644 (file)
@@ -230,6 +230,40 @@ name (i.e. %s).\
             'value': {'get_resource': name}
         }
 
+    def add_volume(self, name, size=10):
+        """add to the template a volume description"""
+        log.debug("adding Cinder::Volume '%s' size '%d' ", name, size)
+
+        self.resources[name] = {
+            'type': 'OS::Cinder::Volume',
+            'properties': {'name': name,
+                           'size': size}
+        }
+
+        self._template['outputs'][name] = {
+            'description': 'Volume %s ID' % name,
+            'value': {'get_resource': name}
+        }
+
+    def add_volume_attachment(self, server_name, volume_name, mountpoint=None):
+        """add to the template an association of volume to instance"""
+        log.debug("adding Cinder::VolumeAttachment server '%s' volume '%s' ", server_name,
+                  volume_name)
+
+        name = "%s-%s" % (server_name, volume_name)
+
+        volume_id = op_utils.get_volume_id(volume_name)
+        if not volume_id:
+            volume_id = {'get_resource': volume_name}
+        self.resources[name] = {
+            'type': 'OS::Cinder::VolumeAttachment',
+            'properties': {'instance_uuid': {'get_resource': server_name},
+                           'volume_id': volume_id}
+        }
+
+        if mountpoint:
+            self.resources[name]['properties']['mountpoint'] = mountpoint
+
     def add_network(self, name, physical_network='physnet1', provider=None,
                     segmentation_id=None, port_security_enabled=None):
         """add to the template a Neutron Net"""