Statistics
| Branch: | Tag: | Revision:

root / qa / qa_instance_utils.py @ 2129c5ff

History | View | Annotate | Download (6.7 kB)

1
#
2
#
3

    
4
# Copyright (C) 2013 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

    
21

    
22
"""QA utility functions for managing instances
23

24
"""
25

    
26
import operator
27

    
28
from ganeti import utils
29
from ganeti import constants
30
from ganeti import pathutils
31

    
32
import qa_config
33
import qa_error
34
import qa_utils
35

    
36
from qa_utils import AssertIn, AssertCommand
37

    
38

    
39
def RemoveInstance(instance):
40
  AssertCommand(["gnt-instance", "remove", "-f", instance.name])
41

    
42

    
43
def GetGenericAddParameters(inst, disk_template, force_mac=None):
44
  params = ["-B"]
45
  params.append("%s=%s,%s=%s" % (constants.BE_MINMEM,
46
                                 qa_config.get(constants.BE_MINMEM),
47
                                 constants.BE_MAXMEM,
48
                                 qa_config.get(constants.BE_MAXMEM)))
49

    
50
  if disk_template != constants.DT_DISKLESS:
51
    for idx, disk in enumerate(qa_config.GetDiskOptions()):
52
      size = disk.get("size")
53
      name = disk.get("name")
54
      diskparams = "%s:size=%s" % (idx, size)
55
      if name:
56
        diskparams += ",name=%s" % name
57
      if qa_config.AreSpindlesSupported():
58
        spindles = disk.get("spindles")
59
        if spindles is None:
60
          raise qa_error.Error("'spindles' is a required parameter for disks"
61
                               " when you enable exclusive storage tests")
62
        diskparams += ",spindles=%s" % spindles
63
      params.extend(["--disk", diskparams])
64

    
65
  # Set static MAC address if configured
66
  if force_mac:
67
    nic0_mac = force_mac
68
  else:
69
    nic0_mac = inst.GetNicMacAddr(0, None)
70

    
71
  if nic0_mac:
72
    params.extend(["--net", "0:mac=%s" % nic0_mac])
73

    
74
  return params
75

    
76

    
77
def _CreateInstanceByDiskTemplateRaw(nodes_spec, disk_template, fail=False):
78
  """Creates an instance with the given disk template on the given nodes(s).
79
     Note that this function does not check if enough nodes are given for
80
     the respective disk template.
81

82
  @type nodes_spec: string
83
  @param nodes_spec: string specification of one node (by node name) or several
84
                     nodes according to the requirements of the disk template
85
  @type disk_template: string
86
  @param disk_template: the disk template to be used by the instance
87
  @return: the created instance
88

89
  """
90
  instance = qa_config.AcquireInstance()
91
  try:
92
    cmd = (["gnt-instance", "add",
93
            "--os-type=%s" % qa_config.get("os"),
94
            "--disk-template=%s" % disk_template,
95
            "--node=%s" % nodes_spec] +
96
           GetGenericAddParameters(instance, disk_template))
97
    cmd.append(instance.name)
98

    
99
    AssertCommand(cmd, fail=fail)
100

    
101
    if not fail:
102
      CheckSsconfInstanceList(instance.name)
103
      instance.SetDiskTemplate(disk_template)
104

    
105
      return instance
106
  except:
107
    instance.Release()
108
    raise
109

    
110
  # Handle the case where creation is expected to fail
111
  assert fail
112
  instance.Release()
113
  return None
114

    
115

    
116
def CreateInstanceDrbd8(nodes, fail=False):
117
  """Creates an instance using disk template 'drbd' on the given nodes.
118

119
  @type nodes: list of nodes
120
  @param nodes: nodes to be used by the instance
121
  @return: the created instance
122

123
  """
124
  assert len(nodes) > 1
125
  return _CreateInstanceByDiskTemplateRaw(
126
    ":".join(map(operator.attrgetter("primary"), nodes)),
127
    constants.DT_DRBD8, fail=fail)
128

    
129

    
130
def CreateInstanceByDiskTemplateOneNode(nodes, disk_template, fail=False):
131
  """Creates an instance using the given disk template for disk templates
132
     for which one given node is sufficient. These templates are for example:
133
     plain, diskless, file, sharedfile, blockdev, rados.
134

135
  @type nodes: list of nodes
136
  @param nodes: a list of nodes, whose first element is used to create the
137
                instance
138
  @type disk_template: string
139
  @param disk_template: the disk template to be used by the instance
140
  @return: the created instance
141

142
  """
143
  assert len(nodes) > 0
144
  return _CreateInstanceByDiskTemplateRaw(nodes[0].primary, disk_template,
145
                                          fail=fail)
146

    
147

    
148
def CreateInstanceByDiskTemplate(nodes, disk_template, fail=False):
149
  """Given a disk template, this function creates an instance using
150
     the template. It uses the required number of nodes depending on
151
     the disk template. This function is intended to be used by tests
152
     that don't care about the specifics of the instance other than
153
     that it uses the given disk template.
154

155
     Note: If you use this function, make sure to call
156
     'TestInstanceRemove' at the end of your tests to avoid orphaned
157
     instances hanging around and interfering with the following tests.
158

159
  @type nodes: list of nodes
160
  @param nodes: the list of the nodes on which the instance will be placed;
161
                it needs to have sufficiently many elements for the given
162
                disk template
163
  @type disk_template: string
164
  @param disk_template: the disk template to be used by the instance
165
  @return: the created instance
166

167
  """
168
  if disk_template == constants.DT_DRBD8:
169
    return CreateInstanceDrbd8(nodes, fail=fail)
170
  elif disk_template in [constants.DT_DISKLESS, constants.DT_PLAIN,
171
                         constants.DT_FILE]:
172
    return CreateInstanceByDiskTemplateOneNode(nodes, disk_template, fail=fail)
173
  else:
174
    # FIXME: This assumes that for all other disk templates, we only need one
175
    # node and no disk template specific parameters. This else-branch is
176
    # currently only used in cases where we expect failure. Extend it when
177
    # QA needs for these templates change.
178
    return CreateInstanceByDiskTemplateOneNode(nodes, disk_template, fail=fail)
179

    
180

    
181
def _ReadSsconfInstanceList():
182
  """Reads ssconf_instance_list from the master node.
183

184
  """
185
  master = qa_config.GetMasterNode()
186

    
187
  ssconf_path = utils.PathJoin(pathutils.DATA_DIR,
188
                               "ssconf_%s" % constants.SS_INSTANCE_LIST)
189

    
190
  cmd = ["cat", qa_utils.MakeNodePath(master, ssconf_path)]
191

    
192
  return qa_utils.GetCommandOutput(master.primary,
193
                                   utils.ShellQuoteArgs(cmd)).splitlines()
194

    
195

    
196
def CheckSsconfInstanceList(instance):
197
  """Checks if a certain instance is in the ssconf instance list.
198

199
  @type instance: string
200
  @param instance: Instance name
201

202
  """
203
  AssertIn(qa_utils.ResolveInstanceName(instance),
204
           _ReadSsconfInstanceList())