Revision cc7f5bfc

b/lib/ssconf.py
103 103
    - keys are restricted to predefined values
104 104

  
105 105
  """
106
  def __init__(self, cfg_location=None):
106
  def __init__(self, cfg_location=None, _lockfile=pathutils.SSCONF_LOCK_FILE):
107 107
    if cfg_location is None:
108 108
      self._cfg_dir = pathutils.DATA_DIR
109 109
    else:
110 110
      self._cfg_dir = cfg_location
111 111

  
112
    self._lockfile = _lockfile
113

  
112 114
  def KeyToFilename(self, key):
113 115
    """Convert a given key into filename.
114 116

  
......
136 138
      raise errors.ConfigurationError("Can't read ssconf file %s: %s" %
137 139
                                      (filename, str(err)))
138 140

  
139
  def WriteFiles(self, values):
141
  def WriteFiles(self, values, dry_run=False):
140 142
    """Writes ssconf files used by external scripts.
141 143

  
142 144
    @type values: dict
143 145
    @param values: Dictionary of (name, value)
146
    @type dry_run boolean
147
    @param dry_run: Whether to perform a dry run
144 148

  
145 149
    """
146
    ssconf_lock = utils.FileLock.Open(pathutils.SSCONF_LOCK_FILE)
150
    ssconf_lock = utils.FileLock.Open(self._lockfile)
147 151

  
148 152
    # Get lock while writing files
149 153
    ssconf_lock.Exclusive(blocking=True, timeout=SSCONF_LOCK_TIMEOUT)
......
151 155
      for name, value in values.iteritems():
152 156
        if value and not value.endswith("\n"):
153 157
          value += "\n"
158

  
154 159
        if len(value) > _MAX_SIZE:
155
          raise errors.ConfigurationError("ssconf file %s above maximum size" %
156
                                          name)
160
          msg = ("Value '%s' has a length of %s bytes, but only up to %s are"
161
                 " allowed" % (name, len(value), _MAX_SIZE))
162
          raise errors.ConfigurationError(msg)
163

  
157 164
        utils.WriteFile(self.KeyToFilename(name), data=value,
158
                        mode=constants.SS_FILE_PERMS)
165
                        mode=constants.SS_FILE_PERMS,
166
                        dry_run=dry_run)
159 167
    finally:
160 168
      ssconf_lock.Unlock()
161 169

  
......
320 328
                                      " family: %s" % err)
321 329

  
322 330

  
323
def WriteSsconfFiles(values):
331
def WriteSsconfFiles(values, dry_run=False):
324 332
  """Update all ssconf files.
325 333

  
326 334
  Wrapper around L{SimpleStore.WriteFiles}.
327 335

  
328 336
  """
329
  SimpleStore().WriteFiles(values)
337
  SimpleStore().WriteFiles(values, dry_run=dry_run)
330 338

  
331 339

  
332 340
def GetMasterAndMyself(ss=None):
b/test/ganeti.ssconf_unittest.py
95 95

  
96 96
class TestSimpleStore(unittest.TestCase):
97 97
  def setUp(self):
98
    self.tmpdir = tempfile.mkdtemp()
99
    self.sstore = ssconf.SimpleStore(cfg_location=self.tmpdir)
98
    self._tmpdir = tempfile.mkdtemp()
99
    self.ssdir = utils.PathJoin(self._tmpdir, "files")
100
    lockfile = utils.PathJoin(self._tmpdir, "lock")
101

  
102
    os.mkdir(self.ssdir)
103

  
104
    self.sstore = ssconf.SimpleStore(cfg_location=self.ssdir,
105
                                     _lockfile=lockfile)
100 106

  
101 107
  def tearDown(self):
102
    shutil.rmtree(self.tmpdir)
108
    shutil.rmtree(self._tmpdir)
109

  
110
  def _ReadSsFile(self, filename):
111
    return utils.ReadFile(utils.PathJoin(self.ssdir, "ssconf_%s" % filename))
103 112

  
104 113
  def testInvalidKey(self):
105 114
    self.assertRaises(errors.ProgrammerError, self.sstore.KeyToFilename,
......
110 119
  def testKeyToFilename(self):
111 120
    for key in ssconf._VALID_KEYS:
112 121
      result = self.sstore.KeyToFilename(key)
113
      self.assertTrue(utils.IsBelowDir(self.tmpdir, result))
122
      self.assertTrue(utils.IsBelowDir(self.ssdir, result))
114 123
      self.assertTrue(os.path.basename(result).startswith("ssconf_"))
115 124

  
116 125
  def testReadFileNonExistingFile(self):
......
140 149
                                           default="something.example.com"),
141 150
                     "cluster.example.com")
142 151

  
152
  def testWriteFiles(self):
153
    values = {
154
      constants.SS_CLUSTER_NAME: "cluster.example.com",
155
      constants.SS_CLUSTER_TAGS: "value\nwith\nnewlines\n",
156
      constants.SS_INSTANCE_LIST: "",
157
      }
158

  
159
    self.sstore.WriteFiles(values)
160

  
161
    self.assertEqual(sorted(os.listdir(self.ssdir)), sorted([
162
      "ssconf_cluster_name",
163
      "ssconf_cluster_tags",
164
      "ssconf_instance_list",
165
      ]))
166

  
167
    self.assertEqual(self._ReadSsFile(constants.SS_CLUSTER_NAME),
168
                     "cluster.example.com\n")
169
    self.assertEqual(self._ReadSsFile(constants.SS_CLUSTER_TAGS),
170
                     "value\nwith\nnewlines\n")
171
    self.assertEqual(self._ReadSsFile(constants.SS_INSTANCE_LIST), "")
172

  
173
  def testWriteFilesUnknownKey(self):
174
    values = {
175
      "unknown key": "value",
176
      }
177

  
178
    self.assertRaises(errors.ProgrammerError, self.sstore.WriteFiles,
179
                      values, dry_run=True)
180

  
181
    self.assertEqual(os.listdir(self.ssdir), [])
182

  
183
  def testWriteFilesDryRun(self):
184
    values = {
185
      constants.SS_CLUSTER_NAME: "cluster.example.com",
186
      }
187

  
188
    self.sstore.WriteFiles(values, dry_run=True)
189

  
190
    self.assertEqual(os.listdir(self.ssdir), [])
191

  
192
  def testWriteFilesNoValues(self):
193
    for dry_run in [False, True]:
194
      self.sstore.WriteFiles({}, dry_run=dry_run)
195

  
196
      self.assertEqual(os.listdir(self.ssdir), [])
197

  
198
  def testWriteFilesTooLong(self):
199
    values = {
200
      constants.SS_INSTANCE_LIST: "A" * ssconf._MAX_SIZE,
201
      }
202

  
203
    for dry_run in [False, True]:
204
      try:
205
        self.sstore.WriteFiles(values, dry_run=dry_run)
206
      except errors.ConfigurationError, err:
207
        self.assertTrue(str(err).startswith("Value 'instance_list' has"))
208
      else:
209
        self.fail("Exception was not raised")
210

  
211
      self.assertEqual(os.listdir(self.ssdir), [])
212

  
143 213

  
144 214
class TestVerifyClusterName(unittest.TestCase):
145 215
  def setUp(self):

Also available in: Unified diff