mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #44827 from mz-bmcqueen/2017.7
add more clone options to virtualbox and add better dhcp handling
This commit is contained in:
commit
d6c37ea19c
2 changed files with 76 additions and 21 deletions
|
@ -48,6 +48,10 @@ log = logging.getLogger(__name__)
|
|||
# The name salt will identify the lib by
|
||||
__virtualname__ = 'virtualbox'
|
||||
|
||||
#if no clone mode is specified in the virtualbox profile
|
||||
#then default to 0 which was the old default value
|
||||
DEFAULT_CLONE_MODE = 0
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
|
@ -85,6 +89,30 @@ def get_configured_provider():
|
|||
return configured
|
||||
|
||||
|
||||
def map_clonemode(vm_info):
|
||||
"""
|
||||
Convert the virtualbox config file values for clone_mode into the integers the API requires
|
||||
"""
|
||||
mode_map = {
|
||||
'state': 0,
|
||||
'child': 1,
|
||||
'all': 2
|
||||
}
|
||||
|
||||
if not vm_info:
|
||||
return DEFAULT_CLONE_MODE
|
||||
|
||||
if 'clonemode' not in vm_info:
|
||||
return DEFAULT_CLONE_MODE
|
||||
|
||||
if vm_info['clonemode'] in mode_map:
|
||||
return mode_map[vm_info['clonemode']]
|
||||
else:
|
||||
raise SaltCloudSystemExit(
|
||||
"Illegal clonemode for virtualbox profile. Legal values are: {}".format(','.join(mode_map.keys()))
|
||||
)
|
||||
|
||||
|
||||
def create(vm_info):
|
||||
"""
|
||||
Creates a virtual machine from the given VM information.
|
||||
|
@ -102,6 +130,7 @@ def create(vm_info):
|
|||
profile: <dict>
|
||||
driver: <provider>:<profile>
|
||||
clonefrom: <vm_name>
|
||||
clonemode: <mode> (default: state, choices: state, child, all)
|
||||
}
|
||||
@type vm_info dict
|
||||
@return dict of resulting vm. !!!Passwords can and should be included!!!
|
||||
|
@ -133,6 +162,9 @@ def create(vm_info):
|
|||
key_filename = config.get_cloud_config_value(
|
||||
'private_key', vm_info, __opts__, search_global=False, default=None
|
||||
)
|
||||
clone_mode = map_clonemode(vm_info)
|
||||
wait_for_pattern = vm_info['waitforpattern'] if 'waitforpattern' in vm_info.keys() else None
|
||||
interface_index = vm_info['interfaceindex'] if 'interfaceindex' in vm_info.keys() else 0
|
||||
|
||||
log.debug("Going to fire event: starting create")
|
||||
__utils__['cloud.fire_event'](
|
||||
|
@ -147,7 +179,8 @@ def create(vm_info):
|
|||
# to create the virtual machine.
|
||||
request_kwargs = {
|
||||
'name': vm_info['name'],
|
||||
'clone_from': vm_info['clonefrom']
|
||||
'clone_from': vm_info['clonefrom'],
|
||||
'clone_mode': clone_mode
|
||||
}
|
||||
|
||||
__utils__['cloud.fire_event'](
|
||||
|
@ -163,17 +196,17 @@ def create(vm_info):
|
|||
# Booting and deploying if needed
|
||||
if power:
|
||||
vb_start_vm(vm_name, timeout=boot_timeout)
|
||||
ips = vb_wait_for_network_address(wait_for_ip_timeout, machine_name=vm_name)
|
||||
ips = vb_wait_for_network_address(wait_for_ip_timeout, machine_name=vm_name, wait_for_pattern=wait_for_pattern)
|
||||
|
||||
if len(ips):
|
||||
ip = ips[0]
|
||||
ip = ips[interface_index]
|
||||
log.info("[ {0} ] IPv4 is: {1}".format(vm_name, ip))
|
||||
# ssh or smb using ip and install salt only if deploy is True
|
||||
if deploy:
|
||||
vm_info['key_filename'] = key_filename
|
||||
vm_info['ssh_host'] = ip
|
||||
|
||||
res = __utils__['cloud.bootstrap'](vm_info)
|
||||
res = __utils__['cloud.bootstrap'](vm_info, __opts__)
|
||||
vm_result.update(res)
|
||||
|
||||
__utils__['cloud.fire_event'](
|
||||
|
|
|
@ -197,7 +197,7 @@ def vb_get_network_adapters(machine_name=None, machine=None):
|
|||
return network_adapters
|
||||
|
||||
|
||||
def vb_wait_for_network_address(timeout, step=None, machine_name=None, machine=None):
|
||||
def vb_wait_for_network_address(timeout, step=None, machine_name=None, machine=None, wait_for_pattern=None):
|
||||
'''
|
||||
Wait until a machine has a network address to return or quit after the timeout
|
||||
|
||||
|
@ -209,12 +209,16 @@ def vb_wait_for_network_address(timeout, step=None, machine_name=None, machine=N
|
|||
@type machine_name: str
|
||||
@param machine:
|
||||
@type machine: IMachine
|
||||
@type wait_for_pattern: str
|
||||
@param wait_for_pattern:
|
||||
@type machine: str
|
||||
@return:
|
||||
@rtype: list
|
||||
'''
|
||||
kwargs = {
|
||||
'machine_name': machine_name,
|
||||
'machine': machine
|
||||
'machine': machine,
|
||||
'wait_for_pattern': wait_for_pattern
|
||||
}
|
||||
return wait_for(vb_get_network_addresses, timeout=timeout, step=step, default=[], func_kwargs=kwargs)
|
||||
|
||||
|
@ -251,7 +255,7 @@ def vb_wait_for_session_state(xp_session, state='Unlocked', timeout=10, step=Non
|
|||
wait_for(_check_session_state, timeout=timeout, step=step, default=False, func_args=args)
|
||||
|
||||
|
||||
def vb_get_network_addresses(machine_name=None, machine=None):
|
||||
def vb_get_network_addresses(machine_name=None, machine=None, wait_for_pattern=None):
|
||||
'''
|
||||
TODO distinguish between private and public addresses
|
||||
|
||||
|
@ -276,21 +280,38 @@ def vb_get_network_addresses(machine_name=None, machine=None):
|
|||
machine = vb_get_box().findMachine(machine_name)
|
||||
|
||||
ip_addresses = []
|
||||
# We can't trust virtualbox to give us up to date guest properties if the machine isn't running
|
||||
# For some reason it may give us outdated (cached?) values
|
||||
log.debug("checking for power on:")
|
||||
if machine.state == _virtualboxManager.constants.MachineState_Running:
|
||||
try:
|
||||
total_slots = int(machine.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/Count'))
|
||||
except ValueError:
|
||||
total_slots = 0
|
||||
for i in range(total_slots):
|
||||
try:
|
||||
address = machine.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/{0}/V4/IP'.format(i))
|
||||
if address:
|
||||
ip_addresses.append(address)
|
||||
except Exception as e:
|
||||
log.debug(e.message)
|
||||
|
||||
log.debug("got power on:")
|
||||
|
||||
#wait on an arbitrary named property
|
||||
#for instance use a dhcp client script to set a property via VBoxControl guestproperty set dhcp_done 1
|
||||
if wait_for_pattern and not machine.getGuestPropertyValue(wait_for_pattern):
|
||||
log.debug("waiting for pattern:{}:".format(wait_for_pattern))
|
||||
return None
|
||||
|
||||
_total_slots = machine.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/Count')
|
||||
|
||||
#upon dhcp the net count drops to 0 and it takes some seconds for it to be set again
|
||||
if not _total_slots:
|
||||
log.debug("waiting for net count:{}:".format(wait_for_pattern))
|
||||
return None
|
||||
|
||||
try:
|
||||
total_slots = int(_total_slots)
|
||||
for i in range(total_slots):
|
||||
try:
|
||||
address = machine.getGuestPropertyValue('/VirtualBox/GuestInfo/Net/{0}/V4/IP'.format(i))
|
||||
if address:
|
||||
ip_addresses.append(address)
|
||||
except Exception as e:
|
||||
log.debug(e.message)
|
||||
except ValueError as e:
|
||||
log.debug(e.message)
|
||||
return None
|
||||
|
||||
log.debug("returning ip_addresses:{}:".format(ip_addresses))
|
||||
return ip_addresses
|
||||
|
||||
|
||||
|
@ -339,6 +360,7 @@ def vb_create_machine(name=None):
|
|||
def vb_clone_vm(
|
||||
name=None,
|
||||
clone_from=None,
|
||||
clone_mode=0,
|
||||
timeout=10000,
|
||||
**kwargs
|
||||
):
|
||||
|
@ -370,7 +392,7 @@ def vb_clone_vm(
|
|||
|
||||
progress = source_machine.cloneTo(
|
||||
new_machine,
|
||||
0, # CloneMode
|
||||
clone_mode, # CloneMode
|
||||
None # CloneOptions : None = Full?
|
||||
)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue