From c77b30801784a5e1db727a4d853a9e56c54b6953 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Thu, 7 Aug 2014 13:04:56 -0400 Subject: [PATCH 01/12] Add the --dhcp option to allow using dhcp on the cloned vm instead of static IPs Addresses #3 --- ezmomi/ezmomi.py | 11 ++++++++--- ezmomi/params.py | 6 ++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/ezmomi/ezmomi.py b/ezmomi/ezmomi.py index 5868b7d..1abdbb0 100644 --- a/ezmomi/ezmomi.py +++ b/ezmomi/ezmomi.py @@ -130,6 +130,7 @@ def list_objects(self): print "{0:<20} {1:<20}".format(c._moId, c.name) def clone(self): + self.config['hostname'] = self.config['hostname'].lower() self.config['mem'] = self.config['mem'] * 1024 # convert GB to MB @@ -250,8 +251,10 @@ def clone(self): # DNS settings globalip = vim.vm.customization.GlobalIPSettings() - globalip.dnsServerList = self.config['dns_servers'] - globalip.dnsSuffixList = self.config['domain'] + + if not self.config['dhcp']: + globalip.dnsServerList = self.config['dns_servers'] + globalip.dnsSuffixList = self.config['domain'] # Hostname settings ident = vim.vm.customization.LinuxPrep() @@ -268,7 +271,9 @@ def clone(self): clonespec = vim.vm.CloneSpec() clonespec.location = relospec clonespec.config = vmconf - clonespec.customization = customspec + + if not self.config['dhcp']: + clonespec.customization = customspec clonespec.powerOn = True clonespec.template = False diff --git a/ezmomi/params.py b/ezmomi/params.py index dfd2edc..e78a862 100644 --- a/ezmomi/params.py +++ b/ezmomi/params.py @@ -59,6 +59,12 @@ def add_params(subparsers): 'List primary IP first.', nargs='+', ) + clone_parser.add_argument( + '--dhcp', + action="store_true", + required=False, + help='Use DHCP instead of static IPs', + ) clone_parser.add_argument( '--cpus', type=int, From 1e40daee96ef81b91014e5aae12d0e7bc101f370 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Thu, 7 Aug 2014 16:12:57 -0400 Subject: [PATCH 02/12] Add a waitforip parameter to poll the VM till it obtains an IP and then send that IP to stdout Addresses #3 --- ezmomi/ezmomi.py | 42 ++++++++++++++++++++++++++++++++++++++++++ ezmomi/params.py | 7 +++++++ 2 files changed, 49 insertions(+) diff --git a/ezmomi/ezmomi.py b/ezmomi/ezmomi.py index 1abdbb0..945ce93 100644 --- a/ezmomi/ezmomi.py +++ b/ezmomi/ezmomi.py @@ -284,8 +284,50 @@ def clone(self): )] result = self.WaitForTasks(tasks) + if self.config['waitforip']: + uuid, ip = self._wait_for_ip(self.config['hostname']) + print "UUID: %s" % uuid + print "IP: %s" % ip + self.send_email() + def _wait_for_ip(self, hostname): + + """ Poll a VM until it registers an IP address """ + + vimtype = "VirtualMachine" + vim_obj = "vim.%s" % vimtype + uuid = None + ip = None + count = 0 + + while not found or count <= 1000: + + # TODO optimize search for the expected VM + try: + container = self.content.viewManager.CreateContainerView( + self.content.rootFolder, [eval(vim_obj)], True) + except AttributeError,e : + print "%s" % e + sys.exit(1) + + vm = [c for c in container.view if c.name == hostname] + if len(vm) < 1 or len(vm) > 1: + return None, None + + uuid = vm[0].config.uuid + ip = vm[0].summary.guest.ipAddress + + if str(ip) != "None": + break + else: + print "Waiting for %s [%s] to obtain an ip address" % (hostname, uuid) + time.sleep(2) + count += 1 + + return uuid,ip + + def destroy(self): tasks = list() print "Finding VM named %s..." % self.config['name'] diff --git a/ezmomi/params.py b/ezmomi/params.py index e78a862..169c51a 100644 --- a/ezmomi/params.py +++ b/ezmomi/params.py @@ -65,6 +65,13 @@ def add_params(subparsers): required=False, help='Use DHCP instead of static IPs', ) + clone_parser.add_argument( + '--waitforip', + action="store_true", + required=False, + default=False, + help='Wait for the system to obtain and IP address', + ) clone_parser.add_argument( '--cpus', type=int, From 877bbcb8904585a1b5671e49cef284a8b8384ce3 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Thu, 7 Aug 2014 16:32:00 -0400 Subject: [PATCH 03/12] Remove unused var --- ezmomi/ezmomi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ezmomi/ezmomi.py b/ezmomi/ezmomi.py index 945ce93..fe98be2 100644 --- a/ezmomi/ezmomi.py +++ b/ezmomi/ezmomi.py @@ -301,7 +301,7 @@ def _wait_for_ip(self, hostname): ip = None count = 0 - while not found or count <= 1000: + while count <= 1000: # TODO optimize search for the expected VM try: From 9359a23c2d609bbd29b682b8eb8c7e35826cb8e7 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Thu, 7 Aug 2014 17:53:29 -0400 Subject: [PATCH 04/12] Add --folder to the clone subcommand --- ezmomi/ezmomi.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ ezmomi/params.py | 5 +++++ 2 files changed, 50 insertions(+) diff --git a/ezmomi/ezmomi.py b/ezmomi/ezmomi.py index fe98be2..3f7684b 100644 --- a/ezmomi/ezmomi.py +++ b/ezmomi/ezmomi.py @@ -127,6 +127,7 @@ def list_objects(self): print "{0:<20} {1:<20}".format('MOID', 'Name') for c in container.view: + import epdb; epdb.st() print "{0:<20} {1:<20}".format(c._moId, c.name) def clone(self): @@ -277,6 +278,13 @@ def clone(self): clonespec.powerOn = True clonespec.template = False + # Override the destination folder if user defined + if "folder" in self.config: + foldermap = self._get_folder_map() + if self.config['folder'] in foldermap: + folder = self.config['folder'] + destfolder = foldermap[folder] + # fire the clone task tasks = [template_vm.Clone(folder=destfolder, name=self.config['hostname'], @@ -291,6 +299,43 @@ def clone(self): self.send_email() + def _get_folder_map(self): + + """ Return a mapping of full folder paths to folder objects """ + + def buildpath(folder_map, folder): + """ Recursively build out a folderpath """ + fullpath = folder + + if hasattr(folder_map[folder], "parent"): + parentname = folder_map[folder].parent.name + if not parentname in folder_map: + pass + else: + tpath = buildpath(folder_map, parentname) + fullpath = os.path.join(tpath, fullpath) + + return fullpath + + folder_map = {} + container = self.content.viewManager.CreateContainerView( + self.content.rootFolder, [eval("vim.Folder")], True) + + # make first pass map + for vf in container.view: + name = vf.name + folder_map[str(name)] = vf + + # make final map + fmap = {} + for k,v in folder_map.iteritems(): + fullpath = buildpath(folder_map, k) + if not fullpath.startswith('/'): + fullpath = '/' + fullpath + fmap[fullpath] = v + + return fmap + def _wait_for_ip(self, hostname): """ Poll a VM until it registers an IP address """ diff --git a/ezmomi/params.py b/ezmomi/params.py index 169c51a..3a5da05 100644 --- a/ezmomi/params.py +++ b/ezmomi/params.py @@ -82,6 +82,11 @@ def add_params(subparsers): type=int, help='Memory in GB' ) + clone_parser.add_argument( + '--folder', + type=str, + help='Destination folder for the new VM' + ) clone_parser.add_argument( '--domain', type=str, From 68d5faa1680612ef95226f96f549c7e4b0894731 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Thu, 7 Aug 2014 19:42:01 -0400 Subject: [PATCH 05/12] Use the task object to fetch the VM object --- ezmomi/ezmomi.py | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/ezmomi/ezmomi.py b/ezmomi/ezmomi.py index 3f7684b..eccbb55 100644 --- a/ezmomi/ezmomi.py +++ b/ezmomi/ezmomi.py @@ -290,10 +290,12 @@ def clone(self): name=self.config['hostname'], spec=clonespec )] + result = self.WaitForTasks(tasks) + vmobj = tasks[0].info.result if self.config['waitforip']: - uuid, ip = self._wait_for_ip(self.config['hostname']) + uuid, ip = self._wait_for_ip(vmobj) print "UUID: %s" % uuid print "IP: %s" % ip @@ -336,32 +338,19 @@ def buildpath(folder_map, folder): return fmap - def _wait_for_ip(self, hostname): + def _wait_for_ip(self, vmobj): - """ Poll a VM until it registers an IP address """ + """ Poll a VirtualMachine object until it registers an IP address """ - vimtype = "VirtualMachine" - vim_obj = "vim.%s" % vimtype uuid = None ip = None count = 0 - while count <= 1000: - - # TODO optimize search for the expected VM - try: - container = self.content.viewManager.CreateContainerView( - self.content.rootFolder, [eval(vim_obj)], True) - except AttributeError,e : - print "%s" % e - sys.exit(1) - - vm = [c for c in container.view if c.name == hostname] - if len(vm) < 1 or len(vm) > 1: - return None, None + while count <= 300: - uuid = vm[0].config.uuid - ip = vm[0].summary.guest.ipAddress + hostname = vmobj.name + uuid = vmobj.config.uuid + ip = vmobj.summary.guest.ipAddress if str(ip) != "None": break From 70c2303ecd232a1f8ae7c2e1e5fa5ab6cdb35941 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Tue, 12 Aug 2014 14:17:58 -0400 Subject: [PATCH 06/12] Wait for all IPs to be acquired --- ezmomi/ezmomi.py | 41 ++++++++++++++++++++++++++--------------- ezmomi/params.py | 5 +++++ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/ezmomi/ezmomi.py b/ezmomi/ezmomi.py index eccbb55..145adad 100644 --- a/ezmomi/ezmomi.py +++ b/ezmomi/ezmomi.py @@ -285,19 +285,34 @@ def clone(self): folder = self.config['folder'] destfolder = foldermap[folder] - # fire the clone task - tasks = [template_vm.Clone(folder=destfolder, - name=self.config['hostname'], - spec=clonespec - )] + tasks = [] + if self.config['dhcp'] and self.config['count']: + for x in range(0, self.config['count']): + if '%s' in self.config['hostname']: + hostname = self.config['hostname'] % x + else: + hostname = self.config['hostname'] + "-%s" % x + tasks.append(template_vm.Clone(folder=destfolder, + name=hostname, + spec=clonespec)) + else: + # fire the clone task + tasks = [template_vm.Clone(folder=destfolder, + name=self.config['hostname'], + spec=clonespec + )] result = self.WaitForTasks(tasks) - vmobj = tasks[0].info.result + vmobjs = [x.info.result for x in tasks] if self.config['waitforip']: - uuid, ip = self._wait_for_ip(vmobj) - print "UUID: %s" % uuid - print "IP: %s" % ip + for vmobj in vmobjs: + self._wait_for_ip(vmobj) + print "{0:<20} {1:<20} {2:<20}".format("Name", "IP", "UUID") + for vmobj in vmobjs: + ip = str(vmobj.summary.guest.ipAddress) + uuid = str(vmobj.config.uuid) + print "{0:<20} {1:<20} {2:<20}".format(vmobj.name, ip, uuid) self.send_email() @@ -342,32 +357,28 @@ def _wait_for_ip(self, vmobj): """ Poll a VirtualMachine object until it registers an IP address """ - uuid = None ip = None count = 0 while count <= 300: hostname = vmobj.name - uuid = vmobj.config.uuid ip = vmobj.summary.guest.ipAddress if str(ip) != "None": break else: - print "Waiting for %s [%s] to obtain an ip address" % (hostname, uuid) + print "Waiting for %s to obtain an ip address" % hostname time.sleep(2) count += 1 - return uuid,ip - def destroy(self): tasks = list() print "Finding VM named %s..." % self.config['name'] vm = self.get_obj([vim.VirtualMachine], self.config['name']) - # need to shut the VM down before destorying it + # need to shut the VM down before destroying it if vm.runtime.powerState == vim.VirtualMachinePowerState.poweredOn: tasks.append(vm.PowerOff()) diff --git a/ezmomi/params.py b/ezmomi/params.py index 3a5da05..64da16d 100644 --- a/ezmomi/params.py +++ b/ezmomi/params.py @@ -87,6 +87,11 @@ def add_params(subparsers): type=str, help='Destination folder for the new VM' ) + clone_parser.add_argument( + '--count', + type=int, + help='Number of VMs to launch [dhcp only]' + ) clone_parser.add_argument( '--domain', type=str, From 5d0ef0dd7618620d8e94c75db70af087df809a0e Mon Sep 17 00:00:00 2001 From: James Tanner Date: Tue, 12 Aug 2014 14:38:21 -0400 Subject: [PATCH 07/12] Check if waitfor ip is in the config before referencing --- ezmomi/ezmomi.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ezmomi/ezmomi.py b/ezmomi/ezmomi.py index 145adad..1114208 100644 --- a/ezmomi/ezmomi.py +++ b/ezmomi/ezmomi.py @@ -127,7 +127,6 @@ def list_objects(self): print "{0:<20} {1:<20}".format('MOID', 'Name') for c in container.view: - import epdb; epdb.st() print "{0:<20} {1:<20}".format(c._moId, c.name) def clone(self): @@ -305,14 +304,15 @@ def clone(self): result = self.WaitForTasks(tasks) vmobjs = [x.info.result for x in tasks] - if self.config['waitforip']: - for vmobj in vmobjs: - self._wait_for_ip(vmobj) - print "{0:<20} {1:<20} {2:<20}".format("Name", "IP", "UUID") - for vmobj in vmobjs: - ip = str(vmobj.summary.guest.ipAddress) - uuid = str(vmobj.config.uuid) - print "{0:<20} {1:<20} {2:<20}".format(vmobj.name, ip, uuid) + if 'waitforip' in self.config: + if self.config['waitforip']: + for vmobj in vmobjs: + self._wait_for_ip(vmobj) + print "{0:<20} {1:<20} {2:<20}".format("Name", "IP", "UUID") + for vmobj in vmobjs: + ip = str(vmobj.summary.guest.ipAddress) + uuid = str(vmobj.config.uuid) + print "{0:<20} {1:<20} {2:<20}".format(vmobj.name, ip, uuid) self.send_email() From 3e17b826a59f761229c75b241a19bcf494983885 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Tue, 12 Aug 2014 15:28:49 -0400 Subject: [PATCH 08/12] Set --folder as optional and use / as the default --- ezmomi/params.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ezmomi/params.py b/ezmomi/params.py index 64da16d..544e0f5 100644 --- a/ezmomi/params.py +++ b/ezmomi/params.py @@ -85,6 +85,8 @@ def add_params(subparsers): clone_parser.add_argument( '--folder', type=str, + required=False, + default='/', help='Destination folder for the new VM' ) clone_parser.add_argument( From f488fd5c64f5b0a1148a80301a15c54eae4f202c Mon Sep 17 00:00:00 2001 From: James Tanner Date: Wed, 13 Aug 2014 00:20:39 -0400 Subject: [PATCH 09/12] Allow for empty config files and for clone attributes to be passed as arguments --- ezmomi/ezmomi.py | 88 +++++++++++++++++++++++++++++++----------------- ezmomi/params.py | 17 ++++++++++ 2 files changed, 74 insertions(+), 31 deletions(-) diff --git a/ezmomi/ezmomi.py b/ezmomi/ezmomi.py index 1114208..84b5cbc 100644 --- a/ezmomi/ezmomi.py +++ b/ezmomi/ezmomi.py @@ -68,6 +68,10 @@ def get_configs(self, kwargs): print 'Unable to read config file. YAML syntax issue, perhaps?' sys.exit(1) + # Handle empty configs + if not config: + config = {} + # Check all required values were supplied either via command line # or config. override defaults from config.yml with any supplied # command line arguments @@ -75,7 +79,7 @@ def get_configs(self, kwargs): for key, value in kwargs.items(): if value: config[key] = value - elif (value is None) and (key not in config): + elif (value is None) and (key not in config) and key is not "ips" and key is not "domain": # compile list of parameters that were not set notset.append(key) @@ -143,42 +147,62 @@ def clone(self): ip_settings = list() # Get network settings for each IP - for key, ip_string in enumerate(self.config['ips']): - - # convert ip from string to the 'IPAddress' type - ip = IPAddress(ip_string) - - # determine network this IP is in - for network in self.config['networks']: - if ip in IPNetwork(network): - self.config['networks'][network]['ip'] = ip - ipnet = IPNetwork(network) - self.config['networks'][network]['subnet_mask'] = str( - ipnet.netmask - ) - ip_settings.append(self.config['networks'][network]) - - # throw an error if we couldn't find a network for this ip - if not any(d['ip'] == ip for d in ip_settings): - print "I don't know what network %s is in. You can supply " \ - "settings for this network in config.yml." % ip_string - sys.exit(1) + if 'ips' in self.config: + for key, ip_string in enumerate(self.config['ips']): + + # convert ip from string to the 'IPAddress' type + ip = IPAddress(ip_string) + + # determine network this IP is in + for network in self.config['networks']: + if ip in IPNetwork(network): + self.config['networks'][network]['ip'] = ip + ipnet = IPNetwork(network) + self.config['networks'][network]['subnet_mask'] = str( + ipnet.netmask + ) + ip_settings.append(self.config['networks'][network]) + + # throw an error if we couldn't find a network for this ip + if not any(d['ip'] == ip for d in ip_settings): + print "I don't know what network %s is in. You can supply " \ + "settings for this network in config.yml." % ip_string + sys.exit(1) # network to place new VM in - self.get_obj([vim.Network], ip_settings[0]['network']) - datacenter = self.get_obj([vim.Datacenter], - ip_settings[0]['datacenter'] - ) + if not self.config['dhcp']: + self.get_obj([vim.Network], ip_settings[0]['network']) + + cluster = self.get_obj([vim.ClusterComputeResource], + ip_settings[0]['cluster'] + ) + + datacenter = self.get_obj([vim.Datacenter], + ip_settings[0]['datacenter'] + ) + + datastore = self.get_obj([vim.Datastore], + ip_settings[0]['datastore'] + ) + else: + cluster = self.get_obj([vim.ClusterComputeResource], + self.config['cluster'] + ) + + datacenter = self.get_obj([vim.Datacenter], + self.config['datacenter'] + ) + + datastore = self.get_obj([vim.Datastore], + self.config['datastore'] + ) + # get the folder where VMs are kept for this datacenter destfolder = datacenter.vmFolder - cluster = self.get_obj([vim.ClusterComputeResource], - ip_settings[0]['cluster'] - ) # use same root resource pool that my desired cluster uses resource_pool = cluster.resourcePool - datastore = self.get_obj([vim.Datastore], ip_settings[0]['datastore']) template_vm = self.get_obj([vim.VirtualMachine], self.config['template'] ) @@ -258,7 +282,8 @@ def clone(self): # Hostname settings ident = vim.vm.customization.LinuxPrep() - ident.domain = self.config['domain'] + if "domain" in self.config: + ident.domain = self.config['domain'] ident.hostName = vim.vm.customization.FixedName() ident.hostName.name = self.config['hostname'] @@ -314,7 +339,8 @@ def clone(self): uuid = str(vmobj.config.uuid) print "{0:<20} {1:<20} {2:<20}".format(vmobj.name, ip, uuid) - self.send_email() + if "mailfrom" in self.config: + self.send_email() def _get_folder_map(self): diff --git a/ezmomi/params.py b/ezmomi/params.py index 544e0f5..38551c6 100644 --- a/ezmomi/params.py +++ b/ezmomi/params.py @@ -29,6 +29,7 @@ def add_params(subparsers): clone_parser.add_argument( '--port', type=str, + default='443', help='vCenter server port', ) clone_parser.add_argument( @@ -54,6 +55,7 @@ def add_params(subparsers): ) clone_parser.add_argument( '--ips', + required=False, type=str, help='Static IPs of new host, separated by a space. ' 'List primary IP first.', @@ -99,6 +101,21 @@ def add_params(subparsers): type=str, help='Domain, e.g. "example.com"' ) + clone_parser.add_argument( + '--datacenter', + type=str, + help='Datacenter' + ) + clone_parser.add_argument( + '--cluster', + type=str, + help='Cluster' + ) + clone_parser.add_argument( + '--datastore', + type=str, + help='Datastore' + ) # destroy destroy_parser = subparsers.add_parser( From 3b407b6131307683f062ef034e00e06f4f539b8a Mon Sep 17 00:00:00 2001 From: James Tanner Date: Wed, 13 Aug 2014 10:18:11 -0400 Subject: [PATCH 10/12] Allow passing server/username/password as arguments to the destroy subcommand --- ezmomi/params.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/ezmomi/params.py b/ezmomi/params.py index 38551c6..a829216 100644 --- a/ezmomi/params.py +++ b/ezmomi/params.py @@ -127,3 +127,25 @@ def add_params(subparsers): required=True, help='VM name (case-sensitive)' ) + clone_parser.add_argument( + '--server', + type=str, + help='vCenter server', + ) + clone_parser.add_argument( + '--port', + type=str, + default='443', + help='vCenter server port', + ) + clone_parser.add_argument( + '--username', + type=str, + help='vCenter username', + ) + clone_parser.add_argument( + '--password', + type=str, + help='vCenter password', + ) + From 95d6f93f951083dc3ad1699f7fa1d4294b480014 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Wed, 13 Aug 2014 10:22:21 -0400 Subject: [PATCH 11/12] Revert "Allow passing server/username/password as arguments to the destroy subcommand" This reverts commit 3b407b6131307683f062ef034e00e06f4f539b8a. --- ezmomi/params.py | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/ezmomi/params.py b/ezmomi/params.py index a829216..38551c6 100644 --- a/ezmomi/params.py +++ b/ezmomi/params.py @@ -127,25 +127,3 @@ def add_params(subparsers): required=True, help='VM name (case-sensitive)' ) - clone_parser.add_argument( - '--server', - type=str, - help='vCenter server', - ) - clone_parser.add_argument( - '--port', - type=str, - default='443', - help='vCenter server port', - ) - clone_parser.add_argument( - '--username', - type=str, - help='vCenter username', - ) - clone_parser.add_argument( - '--password', - type=str, - help='vCenter password', - ) - From 8cd3d78e45cc23b78815ff5093df9d006eae2d38 Mon Sep 17 00:00:00 2001 From: James Tanner Date: Wed, 13 Aug 2014 11:19:16 -0400 Subject: [PATCH 12/12] Add a common set of server connection parameters to the various subcommands to allow for an empty config file. Also increase the verbosity for config parsing errors. --- ezmomi/cli.py | 2 ++ ezmomi/ezmomi.py | 4 ++-- ezmomi/params.py | 50 ++++++++++++++++++++++++++++-------------------- 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/ezmomi/cli.py b/ezmomi/cli.py index 078ee05..f7028f5 100644 --- a/ezmomi/cli.py +++ b/ezmomi/cli.py @@ -2,6 +2,7 @@ Command line definitions for ezmomi ''' import argparse +from params import add_common_params from params import add_params from ezmomi import EZMomi @@ -11,6 +12,7 @@ def cli(): parser = argparse.ArgumentParser( description='Perform common vSphere API tasks' ) + subparsers = parser.add_subparsers(help='Command', dest='mode') # set up each command section diff --git a/ezmomi/ezmomi.py b/ezmomi/ezmomi.py index 84b5cbc..0b255f5 100644 --- a/ezmomi/ezmomi.py +++ b/ezmomi/ezmomi.py @@ -64,8 +64,8 @@ def get_configs(self, kwargs): 'specify the config file path by setting the EZMOMI_CONFIG ' \ 'environment variable.' sys.exit(1) - except Exception: - print 'Unable to read config file. YAML syntax issue, perhaps?' + except Exception, e: + print 'Unable to read config file. YAML syntax issue, perhaps? \n %s' % e sys.exit(1) # Handle empty configs diff --git a/ezmomi/params.py b/ezmomi/params.py index 38551c6..50fde05 100644 --- a/ezmomi/params.py +++ b/ezmomi/params.py @@ -3,6 +3,29 @@ ''' +def add_common_params(parser): + parser.add_argument( + '--server', + type=str, + help='vCenter server', + ) + parser.add_argument( + '--port', + type=str, + default='443', + help='vCenter server port', + ) + parser.add_argument( + '--username', + type=str, + help='vCenter username', + ) + parser.add_argument( + '--password', + type=str, + help='vCenter password', + ) + def add_params(subparsers): # list list_parser = subparsers.add_parser( @@ -10,6 +33,8 @@ def add_params(subparsers): help='List VMware objects on your VMware server' ) + add_common_params(list_parser) + list_parser.add_argument( '--type', required=True, @@ -21,27 +46,9 @@ def add_params(subparsers): 'clone', help='Clone a VM template to a new VM' ) - clone_parser.add_argument( - '--server', - type=str, - help='vCenter server', - ) - clone_parser.add_argument( - '--port', - type=str, - default='443', - help='vCenter server port', - ) - clone_parser.add_argument( - '--username', - type=str, - help='vCenter username', - ) - clone_parser.add_argument( - '--password', - type=str, - help='vCenter password', - ) + + add_common_params(clone_parser) + clone_parser.add_argument( '--template', type=str, @@ -122,6 +129,7 @@ def add_params(subparsers): 'destroy', help='Destroy/delete a Virtual Machine' ) + add_common_params(destroy_parser) destroy_parser.add_argument( '--name', required=True,