Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modify the proxmox VM when using clone in the salt-cloud profile #49256

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions salt/cloud/clouds/proxmox.py
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,41 @@ def list_nodes_select(call=None):
)


def _stringlist_to_dictionary(input_string):
'''
Convert a stringlist (comma separated settings) to a dictionary

The result of the string setting1=value1,setting2=value2 will be a python dictionary:

{'setting1':'value1','setting2':'value2'}
'''
li = str(input_string).split(',')
ret = {}
for item in li:
pair = str(item).replace(' ', '').split('=')
if len(pair) != 2:
log.warn("Cannot process stringlist item %s", item)
continue

ret[pair[0]] = pair[1]
return ret


def _dictionary_to_stringlist(input_dict):
'''
Convert a dictionary to a stringlist (comma separated settings)

The result of the dictionary {'setting1':'value1','setting2':'value2'} will be:

setting1=value1,setting2=value2
'''
string_value = ""
for s in input_dict:
string_value += "{0}={1},".format(s, input_dict[s])
string_value = string_value[:-1]
return string_value


def create(vm_):
'''
Create a single VM from a data dict
Expand Down Expand Up @@ -575,6 +610,61 @@ def create(vm_):
if not wait_for_created(data['upid'], timeout=300):
return {'Error': 'Unable to create {0}, command timed out'.format(name)}

if 'clone' in vm_ and vm_['clone'] is True and vm_['technology'] == 'qemu':
# If we cloned a machine, see if we need to reconfigure any of the options such as net0,
# ide2, etc. This enables us to have a different cloud-init ISO mounted for each VM that's
# brought up

# TODO: Support other settings here too as these are not the only ones that can be modified
# after a clone operation
log.info('Configuring cloned VM')

# Modify the settings for the VM one at a time so we can see any problems with the values
# as quickly as possible
for setting_number in range(3):
setting = 'ide{0}'.format(setting_number)
if setting in vm_:
postParams = {}
postParams[setting] = vm_[setting]
query('post', 'nodes/{0}/qemu/{1}/config'.format(vm_['host'], vmid), postParams)

for setting_number in range(5):
setting = 'sata{0}'.format(setting_number)
if setting in vm_:
postParams = {}
postParams[setting] = vm_[setting]
query('post', 'nodes/{0}/qemu/{1}/config'.format(vm_['host'], vmid), postParams)

for setting_number in range(13):
setting = 'scsi{0}'.format(setting_number)
if setting in vm_:
postParams = {}
postParams[setting] = vm_[setting]
query('post', 'nodes/{0}/qemu/{1}/config'.format(vm_['host'], vmid), postParams)

# net strings are a list of comma seperated settings. We need to merge the settings so that
# the setting in the profile only changes the settings it touches and the other settings
# are left alone. An example of why this is necessary is because the MAC address is set
# in here and generally you don't want to alter or have to know the MAC address of the new
# instance, but you may want to set the VLAN bridge for example
for setting_number in range(20):
setting = 'net{0}'.format(setting_number)
if setting in vm_:
data = query('get', 'nodes/{0}/qemu/{1}/config'.format(vm_['host'], vmid))

# Generate a dictionary of settings from the existing string
new_setting = {}
if setting in data:
new_setting.update(_stringlist_to_dictionary(data[setting]))

# Merge the new settings (as a dictionary) into the existing dictionary to get the
# new merged settings
new_setting.update(_stringlist_to_dictionary(vm_[setting]))

# Convert the dictionary back into a string list
postParams = {setting: _dictionary_to_stringlist(new_setting)}
query('post', 'nodes/{0}/qemu/{1}/config'.format(vm_['host'], vmid), postParams)

# VM has been created. Starting..
if not start(name, vmid, call='action'):
log.error('Node %s (%s) failed to start!', name, vmid)
Expand Down