add more clone options to virtualbox and add better dhcp handling

This commit is contained in:
Brian McQueen 2017-12-03 19:08:30 -08:00
parent 4ebac09f60
commit c38ff74261
No known key found for this signature in database
GPG key ID: 73EBFE56A5D07E9D
2 changed files with 72 additions and 21 deletions

View file

@ -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__():
'''
@ -84,6 +88,26 @@ def get_configured_provider():
)
return configured
def map_clonemode(vm_info):
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):
"""
@ -102,6 +126,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 +158,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 +175,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 +192,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'](

View file

@ -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?
)