Revision 07e3c124

b/lib/client/gnt_os.py
245 245
  else:
246 246
    osp = None
247 247

  
248
  if opts.osparams_private:
249
    osp_private = {os: opts.osparams_private}
250
  else:
251
    osp_private = None
252

  
248 253
  if opts.hidden is not None:
249 254
    if opts.hidden:
250 255
      ohid = [(constants.DDM_ADD, os)]
......
261 266
  else:
262 267
    oblk = None
263 268

  
264
  if not (os_hvp or osp or ohid or oblk):
269
  if not (os_hvp or osp or osp_private or ohid or oblk):
265 270
    ToStderr("At least one of OS parameters or hypervisor parameters"
266 271
             " must be passed")
267 272
    return 1
268 273

  
269 274
  op = opcodes.OpClusterSetParams(os_hvp=os_hvp,
270 275
                                  osparams=osp,
276
                                  osparams_private_cluster=osp_private,
271 277
                                  hidden_os=ohid,
272 278
                                  blacklisted_os=oblk)
273 279
  SubmitOrSend(op, opts)
......
288 294
    "operating systems"),
289 295
  "modify": (
290 296
    ModifyOS, ARGS_ONE_OS,
291
    [HVLIST_OPT, OSPARAMS_OPT, DRY_RUN_OPT, PRIORITY_OPT,
292
     HID_OS_OPT, BLK_OS_OPT] + SUBMIT_OPTS,
297
    [HVLIST_OPT, OSPARAMS_OPT, OSPARAMS_PRIVATE_OPT,
298
     DRY_RUN_OPT, PRIORITY_OPT, HID_OS_OPT, BLK_OS_OPT] + SUBMIT_OPTS,
293 299
    "", "Modify the OS parameters"),
294 300
  }
295 301

  
b/lib/cmdlib/cluster.py
1163 1163
              self.new_os_hvp[os_name][hv_name].update(hv_dict)
1164 1164

  
1165 1165
    # os parameters
1166
    self.new_osp = objects.FillDict(cluster.osparams, {})
1167
    if self.op.osparams:
1168
      for os_name, osp in self.op.osparams.items():
1169
        if os_name not in self.new_osp:
1170
          self.new_osp[os_name] = {}
1171

  
1172
        self.new_osp[os_name] = GetUpdatedParams(self.new_osp[os_name], osp,
1173
                                                 use_none=True)
1174

  
1175
        if not self.new_osp[os_name]:
1176
          # we removed all parameters
1177
          del self.new_osp[os_name]
1178
        else:
1179
          # check the parameter validity (remote check)
1180
          CheckOSParams(self, False, [self.cfg.GetMasterNode()],
1181
                        os_name, self.new_osp[os_name])
1166
    self._BuildOSParams(cluster)
1182 1167

  
1183 1168
    # changes to the hypervisor list
1184 1169
    if self.op.enabled_hypervisors is not None:
......
1232 1217
                                   " specified" % self.op.default_iallocator,
1233 1218
                                   errors.ECODE_INVAL)
1234 1219

  
1220
  def _BuildOSParams(self, cluster):
1221
    "Calculate the new OS parameters for this operation."
1222

  
1223
    def _GetNewParams(source, new_params):
1224
      "Wrapper around GetUpdatedParams."
1225
      if new_params is None:
1226
        return source
1227
      result = objects.FillDict(source, {}) # deep copy of source
1228
      for os_name in new_params:
1229
        result[os_name] = GetUpdatedParams(result.get(os_name, {}),
1230
                                           new_params[os_name],
1231
                                           use_none=True)
1232
        if not result[os_name]:
1233
          del result[os_name] # we removed all parameters
1234
      return result
1235

  
1236
    self.new_osp = _GetNewParams(cluster.osparams,
1237
                                 self.op.osparams)
1238
    self.new_osp_private = _GetNewParams(cluster.osparams_private_cluster,
1239
                                         self.op.osparams_private_cluster)
1240

  
1241
    # Remove os validity check
1242
    changed_oses = (set(self.new_osp.keys()) | set(self.new_osp_private.keys()))
1243
    for os_name in changed_oses:
1244
      os_params = cluster.SimpleFillOS(
1245
        os_name,
1246
        self.new_osp.get(os_name, {}),
1247
        os_params_private=self.new_osp_private.get(os_name, {})
1248
      )
1249
      # check the parameter validity (remote check)
1250
      CheckOSParams(self, False, [self.cfg.GetMasterNode()],
1251
                    os_name, os_params)
1252

  
1235 1253
  def _CheckDiskTemplateConsistency(self):
1236 1254
    """Check whether the disk templates that are going to be disabled
1237 1255
       are still in use by some instances.
......
1318 1336
      self.cluster.ipolicy = self.new_ipolicy
1319 1337
    if self.op.osparams:
1320 1338
      self.cluster.osparams = self.new_osp
1339
    if self.op.osparams_private_cluster:
1340
      self.cluster.osparams_private_cluster = self.new_osp_private
1321 1341
    if self.op.ndparams:
1322 1342
      self.cluster.ndparams = self.new_ndparams
1323 1343
    if self.op.diskparams:
b/lib/cmdlib/common.py
32 32
from ganeti import objects
33 33
from ganeti import opcodes
34 34
from ganeti import pathutils
35
from ganeti.serializer import Private
35 36
import ganeti.rpc.node as rpc
36 37
from ganeti import ssconf
37 38
from ganeti import utils
......
382 383

  
383 384
  """
384 385
  node_uuids = _FilterVmNodes(lu, node_uuids)
386

  
387
  # Last chance to unwrap private elements.
388
  for key in osparams:
389
    if isinstance(osparams[key], Private):
390
      osparams[key] = osparams[key].Get()
391

  
385 392
  result = lu.rpc.call_os_validate(node_uuids, required, osname,
386 393
                                   [constants.OS_VALIDATE_PARAMETERS],
387 394
                                   osparams)
b/man/gnt-os.rst
57 57
~~~~~~
58 58

  
59 59
| **modify** [\--submit] [\--print-job-id]
60
| [ [ -O | --os-parameters ] =*option*=*value*]
61
| [ --os-parameters-private=*option*=*value*]
60 62
| [-H *HYPERVISOR*:option=*value*[,...]]
61 63
| [\--hidden=*yes|no*] [\--blacklisted=*yes|no*]
62 64
| {*OS*}
......
68 70
same syntax as in **gnt-cluster init** to override default
69 71
hypervisor parameters of the cluster for specified *OS* argument.
70 72

  
73
To modify the parameters passed to the OS install scripts, use the
74
**--os-parameters** option. If the value of the parameter should not be
75
saved to logs, use **--os-parameters-private** *and* make sure that
76
no Ganeti daemon or program is running in debug mode. **ganeti-luxid**
77
in particular will issue a warning at startup time if ran in debug mode.
78

  
71 79
To modify the hidden and blacklisted states of an OS, pass the options
72
``--hidden ``*yes|no*, or respectively ``--blacklisted ...``. The
80
``--hidden`` *yes|no*, or respectively ``--blacklisted ...``. The
73 81
'hidden' state means that an OS won't be listed by default in the OS
74 82
list, but is available for installation. The 'blacklisted' state means
75 83
that the OS is not listed and is also not allowed for new instance
b/src/Ganeti/Objects.hs
72 72
  , OsHvParams
73 73
  , ClusterBeParams
74 74
  , ClusterOsParams
75
  , ClusterOsParamsPrivate
75 76
  , ClusterNicParams
76 77
  , Cluster(..)
77 78
  , ConfigData(..)
b/src/Ganeti/OpCodes.hs
213 213
     , pClusterBeParams
214 214
     , pOsHvp
215 215
     , pClusterOsParams
216
     , pClusterOsParamsPrivate
216 217
     , pDiskParams
217 218
     , pCandidatePoolSize
218 219
     , pMaxRunningJobs
b/src/Ganeti/OpParams.hs
118 118
  , pResetDefaults
119 119
  , pOsHvp
120 120
  , pClusterOsParams
121
  , pClusterOsParamsPrivate
121 122
  , pInstOsParams
122 123
  , pCandidatePoolSize
123 124
  , pMaxRunningJobs
......
620 621
  optionalField $
621 622
  simpleField "osparams" [t| GenericContainer String (JSObject JSValue) |]
622 623

  
624
pClusterOsParamsPrivate :: Field
625
pClusterOsParamsPrivate =
626
  withDoc "Cluster-wide private OS parameter defaults" .
627
  renameField "ClusterOsParamsPrivate" .
628
  optionalField $
629
  -- This field needs an unique name to aid Python deserialization
630
  simpleField "osparams_private_cluster"
631
    [t| GenericContainer String (JSObject (Private JSValue)) |]
632

  
623 633
pDiskParams :: Field
624 634
pDiskParams =
625 635
  withDoc "Disk templates' parameter defaults" .
b/test/hs/Test/Ganeti/OpCodes.hs
171 171
      "OP_CLUSTER_RENAME" ->
172 172
        OpCodes.OpClusterRename <$> genNameNE
173 173
      "OP_CLUSTER_SET_PARAMS" ->
174
        OpCodes.OpClusterSetParams <$> arbitrary <*> emptyMUD <*> emptyMUD <*>
175
          arbitrary <*> genMaybe arbitrary <*>
176
          genMaybe genEmptyContainer <*> emptyMUD <*>
177
          genMaybe genEmptyContainer <*> genMaybe genEmptyContainer <*>
178
          genMaybe genEmptyContainer <*> genMaybe arbitrary <*>
179
          genMaybe arbitrary <*>
180
          arbitrary <*> arbitrary <*> arbitrary <*>
181
          arbitrary <*> arbitrary <*> arbitrary <*>
182
          emptyMUD <*> emptyMUD <*> arbitrary <*>
183
          arbitrary  <*> emptyMUD <*> arbitrary <*> arbitrary <*> arbitrary <*>
184
          arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*>
185
          arbitrary <*> genMaybe genName <*> genMaybe genName
174
        OpCodes.OpClusterSetParams
175
          <$> arbitrary                    -- force
176
          <*> emptyMUD                     -- hv_state
177
          <*> emptyMUD                     -- disk_state
178
          <*> arbitrary                    -- vg_name
179
          <*> genMaybe arbitrary           -- enabled_hypervisors
180
          <*> genMaybe genEmptyContainer   -- hvparams
181
          <*> emptyMUD                     -- beparams
182
          <*> genMaybe genEmptyContainer   -- os_hvp
183
          <*> genMaybe genEmptyContainer   -- osparams
184
          <*> genMaybe genEmptyContainer   -- osparams_private_cluster
185
          <*> genMaybe genEmptyContainer   -- diskparams
186
          <*> genMaybe arbitrary           -- candidate_pool_size
187
          <*> genMaybe arbitrary           -- max_running_jobs
188
          <*> arbitrary                    -- uid_pool
189
          <*> arbitrary                    -- add_uids
190
          <*> arbitrary                    -- remove_uids
191
          <*> arbitrary                    -- maintain_node_health
192
          <*> arbitrary                    -- prealloc_wipe_disks
193
          <*> arbitrary                    -- nicparams
194
          <*> emptyMUD                     -- ndparams
195
          <*> emptyMUD                     -- ipolicy
196
          <*> arbitrary                    -- drbd_helper
197
          <*> arbitrary                    -- default_iallocator
198
          <*> emptyMUD                     -- default_iallocator_params
199
          <*> arbitrary                    -- master_netdev
200
          <*> arbitrary                    -- master_netmask
201
          <*> arbitrary                    -- reserved_lvs
202
          <*> arbitrary                    -- hidden_os
203
          <*> arbitrary                    -- blacklisted_os
204
          <*> arbitrary                    -- use_external_mip_script
205
          <*> arbitrary                    -- enabled_disk_templates
206
          <*> arbitrary                    -- modify_etc_hosts
207
          <*> genMaybe genName             -- file_storage_dir
208
          <*> genMaybe genName             -- shared_file_storage_dir
209
          <*> genMaybe genName             -- gluster_file_storage_dir
186 210
      "OP_CLUSTER_REDIST_CONF" -> pure OpCodes.OpClusterRedistConf
187 211
      "OP_CLUSTER_ACTIVATE_MASTER_IP" ->
188 212
        pure OpCodes.OpClusterActivateMasterIp
b/test/py/cmdlib/cluster_unittest.py
752 752
      }
753 753
    }
754 754
    self.cluster.osparams = {"other_os": {"param1": "value1"}}
755
    self.cluster.osparams_private_cluster = {}
755 756
    op = opcodes.OpClusterSetParams(osparams=osparams)
756 757
    self.ExecOpCode(op)
757 758

  

Also available in: Unified diff