def main(): """ main :) """ args = prepare_arguments() if args.name_outputfile is not None: outputfile = open(args.name_outputfile, 'w') else: outputfile = sys.stdout # Reads ~/.cloudstack.ini cs = CloudStack(**read_config()) all_nics = collect_nics(cs) projects_container = cs.listProjects(listall=True) projects = projects_container["project"] for project in sorted(projects, key=lambda key: key["name"]): project_id = project["id"] all_nics = all_nics + collect_nics(cs, project_id) # pprint.pprint(all_nics) filtered_nics = filter_nics(all_nics, args) # pprint.pprint(filtered_nics) print_nics(filtered_nics, outputfile) if args.name_outputfile is not None: outputfile.close()
def test_transform(self, mock): cs = CloudStack(endpoint='https://localhost', key='foo', secret='bar', expiration=-1) mock.return_value.status_code = 200 mock.return_value.json.return_value = { 'listvirtualmachinesresponse': {}, } cs.listVirtualMachines(foo=["foo", "bar"], bar=[{'baz': 'blah', 'foo': 1000}], bytes_param=b'blah') self.assertEqual(1, mock.call_count) [request], kwargs = mock.call_args self.assertEqual(dict(cert=None, timeout=10, verify=True), kwargs) self.assertEqual('GET', request.method) self.assertFalse(request.headers) url = urlparse(request.url) qs = parse_qs(url.query, True) self.assertEqual('listVirtualMachines', qs['command'][0]) self.assertEqual('ImJ/5F0P2RDL7yn4LdLnGcEx5WE=', qs['signature'][0]) self.assertEqual('1000', qs['bar[0].foo'][0]) self.assertEqual('blah', qs['bar[0].baz'][0]) self.assertEqual('blah', qs['bytes_param'][0]) self.assertEqual('foo,bar', qs['foo'][0])
def __init__( self, key, secret, endpoint="https://api.exoscale.com/v1", max_retries=None, trace=False, ): super().__init__( endpoint=endpoint, key=key, secret=secret, max_retries=max_retries, trace=trace, ) self.cs = CloudStack( key=key, secret=secret, endpoint=endpoint, session=self.session, headers={**self.session.headers, **{"User-Agent": self.user_agent}}, trace=self.trace, fetch_result=True, )
def test_request_params_casing(self, mock): cs = CloudStack(endpoint='https://localhost', key='foo', secret='bar', timeout=20, expiration=-1) mock.return_value.status_code = 200 mock.return_value.json.return_value = { 'listvirtualmachinesresponse': {}, } machines = cs.listVirtualMachines(zoneId=2, templateId='3', temPlateidd='4', pageSize='10', fetch_list=True) self.assertEqual(machines, []) self.assertEqual(1, mock.call_count) [request], kwargs = mock.call_args self.assertEqual(dict(cert=None, timeout=20, verify=True), kwargs) self.assertEqual('GET', request.method) self.assertFalse(request.headers) url = urlparse(request.url) qs = parse_qs(url.query, True) self.assertEqual('listVirtualMachines', qs['command'][0]) self.assertEqual('mMS7XALuGkCXk7kj5SywySku0Z0=', qs['signature'][0]) self.assertEqual('3', qs['templateId'][0]) self.assertEqual('4', qs['temPlateidd'][0])
def __init__(self): parser = argparse.ArgumentParser() parser.add_argument('--host') parser.add_argument('--list', action='store_true') parser.add_argument('--project') options = parser.parse_args() try: self.cs = CloudStack(**read_config()) except CloudStackException as e: print("Error: Could not connect to CloudStack API", file=sys.stderr) project_id = '' if options.project: project_id = self.get_project_id(options.project) if options.host: data = self.get_host(options.host) print(json.dumps(data, indent=2)) elif options.list: data = self.get_list() print(json.dumps(data, indent=2)) else: print("usage: --list | --host <hostname> [--project <project>]", file=sys.stderr) sys.exit(1)
def test_signature_v3(self, mock): cs = CloudStack(endpoint='https://localhost', key='foo', secret='bar', expiration=600) mock.return_value.status_code = 200 mock.return_value.json.return_value = { 'createnetworkresponse': {}, } cs.createNetwork(name="", display_text="") self.assertEqual(1, mock.call_count) [request], _ = mock.call_args url = urlparse(request.url) qs = parse_qs(url.query, True) self.assertEqual('createNetwork', qs['command'][0]) self.assertEqual('3', qs['signatureVersion'][0]) expires = qs['expires'][0] # we ignore the timezone for Python2's lack of %z expires = datetime.datetime.strptime(expires[:19], EXPIRES_FORMAT[:-2]) self.assertTrue(expires > datetime.datetime.utcnow(), expires)
def __init__(self): super().__init__() self.cs = CloudStack( endpoint=os.getenv("CLOUDSTACK_API_ENDPOINT"), key=os.getenv("CLOUDSTACK_API_KEY"), secret=os.getenv("CLOUDSTACK_API_SECRET"), )
def test_transform(self, get): cs = CloudStack(endpoint='localhost', key='foo', secret='bar') get.return_value.status_code = 200 get.return_value.json.return_value = { 'listvirtualmachinesresponse': {}, } cs.listVirtualMachines(foo=["foo", "bar"], bar=[{ 'baz': 'blah', 'foo': 1000 }], bytes_param=b'blah') get.assert_called_once_with( 'localhost', timeout=10, cert=None, verify=True, headers=None, params={ 'command': 'listVirtualMachines', 'response': 'json', 'bar[0].foo': '1000', 'bar[0].baz': 'blah', 'foo': 'foo,bar', 'bytes_param': b'blah', 'apiKey': 'foo', 'signature': 'ImJ/5F0P2RDL7yn4LdLnGcEx5WE=', }, )
def test_request_params(self, mock): cs = CloudStack(endpoint='https://localhost', key='foo', secret='bar', timeout=20, expiration=-1) mock.return_value.status_code = 200 mock.return_value.json.return_value = { 'listvirtualmachinesresponse': {}, } machines = cs.listVirtualMachines(listall='true', headers={'Accept-Encoding': 'br'}) self.assertEqual(machines, {}) self.assertEqual(1, mock.call_count) [request], kwargs = mock.call_args self.assertEqual(dict(cert=None, timeout=20, verify=True), kwargs) self.assertEqual('GET', request.method) self.assertEqual('br', request.headers['Accept-Encoding']) url = urlparse(request.url) qs = parse_qs(url.query, True) self.assertEqual('listVirtualMachines', qs['command'][0]) self.assertEqual('B0d6hBsZTcFVCiioSxzwKA9Pke8=', qs['signature'][0]) self.assertEqual('true', qs['listall'][0])
def test_method(self, get, post): cs = CloudStack(endpoint='localhost', key='foo', secret='bar', method='post') post.return_value.status_code = 200 post.return_value.json.return_value = { 'listvirtualmachinesresponse': {}, } cs.listVirtualMachines(blah='brah') self.assertEqual(get.call_args_list, []) self.assertEqual(post.call_args_list, [ call('localhost', timeout=10, verify=True, cert=None, headers=None, data={ 'command': 'listVirtualMachines', 'blah': 'brah', 'apiKey': 'foo', 'response': 'json', 'signature': '58VvLSaVUqHnG9DhXNOAiDFwBoA=', }) ])
def test_transform_dict(self, get): cs = CloudStack(endpoint='localhost', key='foo', secret='bar') get.return_value.status_code = 200 get.return_value.json.return_value = { 'scalevirtualmachineresponse': {}, } cs.scaleVirtualMachine(id='a', details={ 'cpunumber': 1000, 'memory': '640k' }) get.assert_called_once_with( 'localhost', timeout=10, cert=None, verify=True, headers=None, params={ 'command': 'scaleVirtualMachine', 'response': 'json', 'id': 'a', 'details[0].cpunumber': '1000', 'details[0].memory': '640k', 'apiKey': 'foo', 'signature': 'ZNl66z3gFhnsx2Eo3vvCIM0kAgI=', }, )
def test_request_params_casing(self, get): cs = CloudStack(endpoint='localhost', key='foo', secret='bar', timeout=20) get.return_value.status_code = 200 get.return_value.json.return_value = { 'listvirtualmachinesresponse': {}, } machines = cs.listVirtualMachines(zoneId=2, templateId='3', temPlateidd='4', pageSize='10', fetch_list=True) self.assertEqual(machines, []) get.assert_called_once_with( 'localhost', timeout=20, verify=True, cert=None, headers=None, params={ 'apiKey': 'foo', 'response': 'json', 'command': 'listVirtualMachines', 'signature': 'mMS7XALuGkCXk7kj5SywySku0Z0=', 'templateId': '3', 'temPlateidd': '4', 'zoneId': '2', 'page': '1', 'pageSize': '10', }, )
def test_transform_empty(self, mock): cs = CloudStack(endpoint='https://localhost', key='foo', secret='bar', expiration=-1) mock.return_value.status_code = 200 mock.return_value.json.return_value = { 'createnetworkresponse': {}, } cs.createNetwork(name="", display_text="") self.assertEqual(1, mock.call_count) [request], kwargs = mock.call_args self.assertEqual(dict(cert=None, timeout=10, verify=True), kwargs) self.assertEqual('GET', request.method) self.assertFalse(request.headers) url = urlparse(request.url) qs = parse_qs(url.query, True) self.assertEqual('createNetwork', qs['command'][0]) self.assertEqual('CistTEiPt/4Rv1v4qSyILvPbhmg=', qs['signature'][0]) self.assertEqual('', qs['name'][0]) self.assertEqual('', qs['display_text'][0])
def test_method(self, mock): cs = CloudStack(endpoint='https://localhost', key='foo', secret='bar', method='post', expiration=-1) mock.return_value.status_code = 200 mock.return_value.json.return_value = { 'listvirtualmachinesresponse': {}, } cs.listVirtualMachines(blah='brah') self.assertEqual(1, mock.call_count) [request], kwargs = mock.call_args self.assertEqual(dict(cert=None, timeout=10, verify=True), kwargs) self.assertEqual('POST', request.method) self.assertEqual('application/x-www-form-urlencoded', request.headers['Content-Type']) qs = parse_qs(request.body, True) self.assertEqual('listVirtualMachines', qs['command'][0]) self.assertEqual('58VvLSaVUqHnG9DhXNOAiDFwBoA=', qs['signature'][0]) self.assertEqual('brah', qs['blah'][0])
def test_transform(self, mock): cs = CloudStack(endpoint='https://localhost', key='foo', secret='bar', expiration=-1) mock.return_value.status_code = 200 mock.return_value.json.return_value = { 'listvirtualmachinesresponse': {}, } cs.listVirtualMachines(foo=["foo", "bar"], bar=[{ 'baz': 'blah', 'foo': 1000 }], bytes_param=b'blah') self.assertEqual(1, mock.call_count) [request], kwargs = mock.call_args self.assertEqual(dict(cert=None, timeout=10, verify=True), kwargs) self.assertEqual('GET', request.method) self.assertFalse(request.headers) url = urlparse(request.url) qs = parse_qs(url.query, True) self.assertEqual('listVirtualMachines', qs['command'][0]) self.assertEqual('ImJ/5F0P2RDL7yn4LdLnGcEx5WE=', qs['signature'][0]) self.assertEqual('1000', qs['bar[0].foo'][0]) self.assertEqual('blah', qs['bar[0].baz'][0]) self.assertEqual('blah', qs['bytes_param'][0]) self.assertEqual('foo,bar', qs['foo'][0])
def test_transform_dict(self, mock): cs = CloudStack(endpoint='https://localhost', key='foo', secret='bar', expiration=-1) mock.return_value.status_code = 200 mock.return_value.json.return_value = { 'scalevirtualmachineresponse': {}, } cs.scaleVirtualMachine(id='a', details={ 'cpunumber': 1000, 'memory': '640k' }) self.assertEqual(1, mock.call_count) [request], kwargs = mock.call_args self.assertEqual(dict(cert=None, timeout=10, verify=True), kwargs) self.assertEqual('GET', request.method) self.assertFalse(request.headers) url = urlparse(request.url) qs = parse_qs(url.query, True) self.assertEqual('scaleVirtualMachine', qs['command'][0]) self.assertEqual('ZNl66z3gFhnsx2Eo3vvCIM0kAgI=', qs['signature'][0]) self.assertEqual('1000', qs['details[0].cpunumber'][0]) self.assertEqual('640k', qs['details[0].memory'][0])
def _connect(self): api_region = self.module.params.get('api_region') or os.environ.get( 'CLOUDSTACK_REGION') try: config = read_config(api_region) except KeyError: config = {} api_config = { 'endpoint': self.module.params.get('api_url') or config.get('endpoint'), 'key': self.module.params.get('api_key') or config.get('key'), 'secret': self.module.params.get('api_secret') or config.get('secret'), 'timeout': self.module.params.get('api_timeout') or config.get('timeout'), 'method': self.module.params.get('api_http_method') or config.get('method'), } self.result.update({ 'api_region': api_region, 'api_url': api_config['endpoint'], 'api_key': api_config['key'], 'api_timeout': api_config['timeout'], 'api_http_method': api_config['method'], }) if not all( [api_config['endpoint'], api_config['key'], api_config['secret']]): self.module.fail_json( msg="Missing api credentials: can not authenticate", result=self.result) self.cs = CloudStack(**api_config)
class CloudStackChaotic(Chaotic): def __init__(self) -> None: self.cs = CloudStack( endpoint=CLOUDSTACK_API_ENDPOINT, key=CLOUDSTACK_API_KEY, secret=CLOUDSTACK_API_SECRET, ) def action(self) -> None: tag = self.configs.get('tag') log.info(f"Querying with tag: {tag['key']}={tag['value']}") instances = self.cs.listVirtualMachines( tags=[tag], projectid=self.configs.get('projectid'), zoneid=self.configs.get('zoneid'), fetch_list=True, ) if instances: instance = random.choice(instances) log.info(f"Choose server {instance['name']}") if not self.dry_run: log.info(f"Stopping server {instance['name']}") self.cs.stopVirtualMachine(id=instance['id']) wait_before_restart = int( self.configs.get('wait_before_restart', 60)) log.info(f"Sleeping for {wait_before_restart} seconds") time.sleep(wait_before_restart) log.info(f"Starting server {instance['name']}") self.cs.startVirtualMachine(id=instance['id']) else: log.info("No servers found") log.info(f"done")
def test_request_params(self, get): cs = CloudStack(endpoint='localhost', key='foo', secret='bar', timeout=20) get.return_value.status_code = 200 get.return_value.json.return_value = { 'listvirtualmachinesresponse': {}, } machines = cs.listVirtualMachines(listall='true', headers={'Accept-Encoding': 'br'}) self.assertEqual(machines, {}) get.assert_called_once_with( 'localhost', timeout=20, verify=True, cert=None, headers={ 'Accept-Encoding': 'br', }, params={ 'apiKey': 'foo', 'response': 'json', 'command': 'listVirtualMachines', 'listall': 'true', 'signature': 'B0d6hBsZTcFVCiioSxzwKA9Pke8=', }, )
def test_transformt(self, get): cs = CloudStack(endpoint='localhost', key='foo', secret='bar') get.return_value.status_code = 200 get.return_value.json.return_value = { 'listvirtualmachinesresponse': {}, } cs.listVirtualMachines(foo=["foo", "bar"], bar=[{ 'baz': 'blah', 'foo': 'meh' }]) get.assert_called_once_with( 'localhost', timeout=10, cert=None, verify=True, params={ 'command': 'listVirtualMachines', 'response': 'json', 'bar[0].foo': 'meh', 'bar[0].baz': 'blah', 'foo': 'foo,bar', 'apiKey': 'foo', 'signature': 'UGUVEfCOfGfOlqoTj1D2m5adr2g=', }, )
def test_request_params_casing(self, get): cs = CloudStack(endpoint='localhost', key='foo', secret='bar', timeout=20) get.return_value.status_code = 200 get.return_value.json.return_value = { 'listvirtualmachinesresponse': {}, } machines = cs.listVirtualMachines(zoneId=2, templateId='3', temPlateidd='4') self.assertEqual(machines, {}) get.assert_called_once_with( 'localhost', timeout=20, verify=True, cert=None, params={ 'apiKey': 'foo', 'response': 'json', 'command': 'listVirtualMachines', 'signature': 'dMRxAZcs2OPK15WUulzUtnrLWD0=', 'templateId': '3', 'temPlateidd': '4', 'zoneId': '2' }, )
def __init__(self): tempdict = {} path = os.path.dirname(os.path.abspath(__file__)) # Read config try: f = open(path + "/../cloudstack.config", "r") config = f.readlines() except: print("Somethings wrong with your config file") sys.exit(2) for entry in config: entry = entry.replace("\n", "") temarray = entry.split("=") tempdict[temarray[0]] = temarray[1] if tempdict['verify'] is None: tempdict['verify'] = False self.cs = CloudStack( endpoint=tempdict['endpoint'], key=tempdict['key'], secret=tempdict['secret'], verify=False )
def __init__(self, zoneid, debug): self.zoneid = zoneid self._debug = debug self._config = read_config() self._cs = CloudStack(**self._config) self._vms = {} self._zones = {} self._lbs = {} self._templates = {} self._offerings = {} self._networks = {}
def __init__(self, endpoint=None, key=None, secret=None, profile=None, timeout=60, dry_run=True, log_to_slack=False): if profile: (endpoint, key, secret) = _load_cloud_monkey_profile(profile) self.endpoint = endpoint self.key = key self.secret = secret self.timeout = timeout self.dry_run = dry_run self.log_to_slack = log_to_slack self.cs = CloudStack(self.endpoint, self.key, self.secret, self.timeout)
def __init__(self, key=None, secret=None, endpoint=None): if key is None or secret is None or endpoint is None: self._config = read_config() self._cs = CloudStack(**self._config) else: self._cs = CloudStack(key=key, secret=secret, endpoint=endpoint) self.vms = [] self.zones = [] self.lbs = [] self.tps = [] self.nws = [] self.svs = []
def _connect(self): api_key = self.module.params.get("api_key") api_secret = self.module.params.get("secret_key") api_url = self.module.params.get("api_url") api_http_method = self.module.params.get("api_http_method") api_timeout = self.module.params.get("api_timeout") if api_key and api_secret and api_url: self.cs = CloudStack( endpoint=api_url, key=api_key, secret=api_secret, timeout=api_timeout, method=api_http_method ) else: self.cs = CloudStack(**read_config())
def _connect(self): api_key = self.module.params.get('api_key') api_secret = self.module.params.get('secret_key') api_url = self.module.params.get('api_url') api_http_method = self.module.params.get('api_http_method') if api_key and api_secret and api_url: self.cs = CloudStack(endpoint=api_url, key=api_key, secret=api_secret, method=api_http_method) else: self.cs = CloudStack(**read_config())
def test_encoding(self, get): cs = CloudStack(endpoint='localhost', key='foo', secret='bar') get.return_value.status_code = 200 get.return_value.json.return_value = { 'listvirtualmachinesresponse': {}, } cs.listVirtualMachines(listall=1, unicode_param=u'éèààû') get.assert_called_once_with('localhost', timeout=10, params={ 'apiKey': 'foo', 'response': 'json', 'command': 'listVirtualMachines', 'listall': '1', 'unicode_param': u'éèààû', 'signature': 'gABU/KFJKD3FLAgKDuxQoryu4sA='})
def _connect(self): api_key = self.module.params.get('api_key') api_secret = self.module.params.get('secret_key') api_url = self.module.params.get('api_url') api_http_method = self.module.params.get('api_http_method') if api_key and api_secret and api_url: self.cs = CloudStack( endpoint=api_url, key=api_key, secret=api_secret, method=api_http_method ) else: self.cs = CloudStack(**read_config())
def test_request_params(self, get): cs = CloudStack(endpoint='localhost', key='foo', secret='bar', timeout=20) get.return_value.status_code = 200 get.return_value.json.return_value = { 'listvirtualmachinesresponse': {}, } machines = cs.listVirtualMachines(listall='true') self.assertEqual(machines, {}) get.assert_called_once_with('localhost', timeout=20, params={ 'apiKey': 'foo', 'response': 'json', 'command': 'listVirtualMachines', 'listall': 'true', 'signature': 'B0d6hBsZTcFVCiioSxzwKA9Pke8='})
def cs_list(method, key_name, **kwargs): timeout = 300 cs = CloudStack(endpoint=API_MONITORS, key=APIKEY_MONITORS, secret=SECRET_MONITORS, timeout=timeout) querypage = 1 querypagesize = 500 values = getattr(cs, method)(listall='true', pagesize=querypagesize, page=querypage, **kwargs).get(key_name, []) if len(values) == querypagesize: all_values = [] query_tmp = values while len(query_tmp): all_values.extend(query_tmp) querypage = querypage + 1 query_tmp = getattr(cs, method)(listall='true', pagesize=querypagesize, page=querypage, **kwargs).get(key_name, []) values = all_values return values
def __init__(self): super().__init__() self.cs = CloudStack( endpoint="https://api.exoscale.com/compute", key=os.getenv("EXOSCALE_API_KEY"), secret=os.getenv("EXOSCALE_API_SECRET"), )
def _connect(self): api_key = self.module.params.get('api_key') api_secret = self.module.params.get('api_secret') api_url = self.module.params.get('api_url') api_http_method = self.module.params.get('api_http_method') api_timeout = self.module.params.get('api_timeout') if api_key and api_secret and api_url: self.cs = CloudStack(endpoint=api_url, key=api_key, secret=api_secret, timeout=api_timeout, method=api_http_method) else: api_region = self.module.params.get('api_region', 'cloudstack') self.cs = CloudStack(**read_config(api_region))
def test_transform_empty(self, get): cs = CloudStack(endpoint='localhost', key='foo', secret='bar') get.return_value.status_code = 200 get.return_value.json.return_value = { 'createnetworkresponse': {}, } cs.createNetwork(name="", display_text="") get.assert_called_once_with( 'localhost', timeout=10, cert=None, verify=True, params={ 'command': 'createNetwork', 'response': 'json', 'name': '', 'display_text': '', 'apiKey': 'foo', 'signature': 'CistTEiPt/4Rv1v4qSyILvPbhmg=', }, )
def _connect(self): api_key = self.module.params.get('api_key') api_secret = self.module.params.get('secret_key') api_url = self.module.params.get('api_url') api_http_method = self.module.params.get('api_http_method') api_timeout = self.module.params.get('api_timeout') if api_key and api_secret and api_url: self.cs = CloudStack( endpoint=api_url, key=api_key, secret=api_secret, timeout=api_timeout, method=api_http_method) else: api_region = self.module.params.get('api_region', 'cloudstack') self.cs = CloudStack(**read_config(api_region))
def test_transformt(self, get): cs = CloudStack(endpoint='localhost', key='foo', secret='bar') get.return_value.status_code = 200 get.return_value.json.return_value = { 'listvirtualmachinesresponse': {}, } cs.listVirtualMachines(foo=["foo", "bar"], bar=[{'baz': 'blah', 'foo': 'meh'}]) get.assert_called_once_with('localhost', timeout=10, params={ 'command': 'listVirtualMachines', 'response': 'json', 'bar[0].foo': 'meh', 'bar[0].baz': 'blah', 'foo': 'foo,bar', 'apiKey': 'foo', 'signature': 'UGUVEfCOfGfOlqoTj1D2m5adr2g=', })
def test_method(self, get, post): cs = CloudStack(endpoint='localhost', key='foo', secret='bar', method='post') post.return_value.status_code = 200 post.return_value.json.return_value = { 'listvirtualmachinesresponse': {}, } cs.listVirtualMachines(blah='brah') self.assertEqual(get.call_args_list, []) self.assertEqual(post.call_args_list, [ call('localhost', timeout=10, data={ 'command': 'listVirtualMachines', 'blah': 'brah', 'apiKey': 'foo', 'response': 'json', 'signature': '58VvLSaVUqHnG9DhXNOAiDFwBoA=', })] )
def test_encoding(self, mock): cs = CloudStack(endpoint='https://localhost', key='foo', secret='bar', expiration=-1) mock.return_value.status_code = 200 mock.return_value.json.return_value = { 'listvirtualmachinesresponse': {}, } cs.listVirtualMachines(listall=1, unicode_param=u'éèààû') self.assertEqual(1, mock.call_count) [request], _ = mock.call_args url = urlparse(request.url) qs = parse_qs(url.query, True) self.assertEqual('listVirtualMachines', qs['command'][0]) self.assertEqual('gABU/KFJKD3FLAgKDuxQoryu4sA=', qs['signature'][0]) self.assertEqual('éèààû', qs['unicode_param'][0])
def test_transform_dict(self, mock): cs = CloudStack(endpoint='https://localhost', key='foo', secret='bar', expiration=-1) mock.return_value.status_code = 200 mock.return_value.json.return_value = { 'scalevirtualmachineresponse': {}, } cs.scaleVirtualMachine(id='a', details={'cpunumber': 1000, 'memory': '640k'}) self.assertEqual(1, mock.call_count) [request], kwargs = mock.call_args self.assertEqual(dict(cert=None, timeout=10, verify=True), kwargs) self.assertEqual('GET', request.method) self.assertFalse(request.headers) url = urlparse(request.url) qs = parse_qs(url.query, True) self.assertEqual('scaleVirtualMachine', qs['command'][0]) self.assertEqual('ZNl66z3gFhnsx2Eo3vvCIM0kAgI=', qs['signature'][0]) self.assertEqual('1000', qs['details[0].cpunumber'][0]) self.assertEqual('640k', qs['details[0].memory'][0])
def __init__(self): parser = argparse.ArgumentParser() parser.add_argument('--host') parser.add_argument('--list', action='store_true') parser.add_argument('--tag', help="Filter machines by a tag. Should be in the form key=value.") parser.add_argument('--project') parser.add_argument('--domain') options = parser.parse_args() try: self.cs = CloudStack(**read_config()) except CloudStackException: print("Error: Could not connect to CloudStack API", file=sys.stderr) domain_id = None if options.domain: domain_id = self.get_domain_id(options.domain) project_id = None if options.project: project_id = self.get_project_id(options.project, domain_id) if options.host: data = self.get_host(options.host, project_id, domain_id) print(json.dumps(data, indent=2)) elif options.list: tags = dict() if options.tag: tags['tags[0].key'], tags['tags[0].value'] = options.tag.split('=') data = self.get_list(project_id, domain_id, **tags) print(json.dumps(data, indent=2)) else: print("usage: --list [--tag <tag>] | --host <hostname> [--project <project>] [--domain <domain_path>]", file=sys.stderr) sys.exit(1)
class CloudStackInventory(object): def __init__(self): parser = argparse.ArgumentParser() parser.add_argument('--host') parser.add_argument('--list', action='store_true') parser.add_argument('--tag', help="Filter machines by a tag. Should be in the form key=value.") parser.add_argument('--project') parser.add_argument('--domain') options = parser.parse_args() try: self.cs = CloudStack(**read_config()) except CloudStackException: print("Error: Could not connect to CloudStack API", file=sys.stderr) domain_id = None if options.domain: domain_id = self.get_domain_id(options.domain) project_id = None if options.project: project_id = self.get_project_id(options.project, domain_id) if options.host: data = self.get_host(options.host, project_id, domain_id) print(json.dumps(data, indent=2)) elif options.list: tags = dict() if options.tag: tags['tags[0].key'], tags['tags[0].value'] = options.tag.split('=') data = self.get_list(project_id, domain_id, **tags) print(json.dumps(data, indent=2)) else: print("usage: --list [--tag <tag>] | --host <hostname> [--project <project>] [--domain <domain_path>]", file=sys.stderr) sys.exit(1) def get_domain_id(self, domain): domains = self.cs.listDomains(listall=True) if domains: for d in domains['domain']: if d['path'].lower() == domain.lower(): return d['id'] print("Error: Domain %s not found." % domain, file=sys.stderr) sys.exit(1) def get_project_id(self, project, domain_id=None): projects = self.cs.listProjects(domainid=domain_id) if projects: for p in projects['project']: if p['name'] == project or p['id'] == project: return p['id'] print("Error: Project %s not found." % project, file=sys.stderr) sys.exit(1) def get_host(self, name, project_id=None, domain_id=None, **kwargs): hosts = self.cs.listVirtualMachines(projectid=project_id, domainid=domain_id, fetch_list=True, **kwargs) data = {} if not hosts: return data for host in hosts: host_name = host['displayname'] if name == host_name: data['zone'] = host['zonename'] if 'group' in host: data['group'] = host['group'] data['state'] = host['state'] data['service_offering'] = host['serviceofferingname'] data['affinity_group'] = host['affinitygroup'] data['security_group'] = host['securitygroup'] data['cpu_number'] = host['cpunumber'] data['cpu_speed'] = host['cpuspeed'] if 'cpuused' in host: data['cpu_used'] = host['cpuused'] data['memory'] = host['memory'] data['tags'] = host['tags'] data['hypervisor'] = host['hypervisor'] data['created'] = host['created'] data['nic'] = [] for nic in host['nic']: data['nic'].append({ 'ip': nic['ipaddress'], 'mac': nic['macaddress'], 'netmask': nic['netmask'], 'gateway': nic['gateway'], 'type': nic['type'], }) if nic['isdefault']: data['default_ip'] = nic['ipaddress'] break return data def get_list(self, project_id=None, domain_id=None, **kwargs): data = { 'all': { 'hosts': [], }, '_meta': { 'hostvars': {}, }, } groups = self.cs.listInstanceGroups(projectid=project_id, domainid=domain_id) if groups: for group in groups['instancegroup']: group_name = group['name'] if group_name and group_name not in data: data[group_name] = { 'hosts': [] } hosts = self.cs.listVirtualMachines(projectid=project_id, domainid=domain_id, fetch_list=True, **kwargs) if not hosts: return data for host in hosts: host_name = host['displayname'] data['all']['hosts'].append(host_name) data['_meta']['hostvars'][host_name] = {} # Make a group per zone data['_meta']['hostvars'][host_name]['zone'] = host['zonename'] group_name = host['zonename'] if group_name not in data: data[group_name] = { 'hosts': [] } data[group_name]['hosts'].append(host_name) if 'group' in host: data['_meta']['hostvars'][host_name]['group'] = host['group'] data['_meta']['hostvars'][host_name]['state'] = host['state'] data['_meta']['hostvars'][host_name]['service_offering'] = host['serviceofferingname'] data['_meta']['hostvars'][host_name]['affinity_group'] = host['affinitygroup'] data['_meta']['hostvars'][host_name]['security_group'] = host['securitygroup'] data['_meta']['hostvars'][host_name]['cpu_number'] = host['cpunumber'] data['_meta']['hostvars'][host_name]['cpu_speed'] = host['cpuspeed'] if 'cpuused' in host: data['_meta']['hostvars'][host_name]['cpu_used'] = host['cpuused'] data['_meta']['hostvars'][host_name]['created'] = host['created'] data['_meta']['hostvars'][host_name]['memory'] = host['memory'] data['_meta']['hostvars'][host_name]['tags'] = host['tags'] data['_meta']['hostvars'][host_name]['hypervisor'] = host['hypervisor'] data['_meta']['hostvars'][host_name]['created'] = host['created'] data['_meta']['hostvars'][host_name]['nic'] = [] for nic in host['nic']: data['_meta']['hostvars'][host_name]['nic'].append({ 'ip': nic['ipaddress'], 'mac': nic['macaddress'], 'netmask': nic['netmask'], 'gateway': nic['gateway'], 'type': nic['type'], }) if nic['isdefault']: data['_meta']['hostvars'][host_name]['default_ip'] = nic['ipaddress'] group_name = '' if 'group' in host: group_name = host['group'] if group_name and group_name in data: data[group_name]['hosts'].append(host_name) return data
class AnsibleCloudStack(object): def __init__(self, module): if not has_lib_cs: module.fail_json(msg="python library cs required: pip install cs") self.result = { 'changed': False, } # Common returns, will be merged with self.returns # search_for_key: replace_with_key self.common_returns = { 'id': 'id', 'name': 'name', 'created': 'created', 'zonename': 'zone', 'state': 'state', 'project': 'project', 'account': 'account', 'domain': 'domain', 'displaytext': 'display_text', 'displayname': 'display_name', 'description': 'description', } # Init returns dict for use in subclasses self.returns = {} # these values will be casted to int self.returns_to_int = {} self.module = module self._connect() self.domain = None self.account = None self.project = None self.ip_address = None self.zone = None self.vm = None self.os_type = None self.hypervisor = None self.capabilities = None self.tags = None def _connect(self): api_key = self.module.params.get('api_key') api_secret = self.module.params.get('secret_key') api_url = self.module.params.get('api_url') api_http_method = self.module.params.get('api_http_method') api_timeout = self.module.params.get('api_timeout') if api_key and api_secret and api_url: self.cs = CloudStack( endpoint=api_url, key=api_key, secret=api_secret, timeout=api_timeout, method=api_http_method) else: api_region = self.module.params.get('api_region', 'cloudstack') self.cs = CloudStack(**read_config(api_region)) def get_or_fallback(self, key=None, fallback_key=None): value = self.module.params.get(key) if not value: value = self.module.params.get(fallback_key) return value # TODO: for backward compatibility only, remove if not used anymore def _has_changed(self, want_dict, current_dict, only_keys=None): return self.has_changed( want_dict=want_dict, current_dict=current_dict, only_keys=only_keys) def has_changed(self, want_dict, current_dict, only_keys=None): for key, value in want_dict.iteritems(): # Optionally limit by a list of keys if only_keys and key not in only_keys: continue # Skip None values if value is None: continue if key in current_dict: # API returns string for int in some cases, just to make sure if isinstance(value, int): current_dict[key] = int(current_dict[key]) elif isinstance(value, str): current_dict[key] = str(current_dict[key]) # Only need to detect a singe change, not every item if value != current_dict[key]: return True return False def _get_by_key(self, key=None, my_dict=None): if my_dict is None: my_dict = {} if key: if key in my_dict: return my_dict[key] self.module.fail_json( msg="Something went wrong: %s not found" % key) return my_dict def get_project(self, key=None): if self.project: return self._get_by_key(key, self.project) project = self.module.params.get('project') if not project: return None args = {} args['account'] = self.get_account(key='name') args['domainid'] = self.get_domain(key='id') projects = self.cs.listProjects(**args) if projects: for p in projects['project']: if project.lower() in [p['name'].lower(), p['id']]: self.project = p return self._get_by_key(key, self.project) self.module.fail_json(msg="project '%s' not found" % project) def get_ip_address(self, key=None): if self.ip_address: return self._get_by_key(key, self.ip_address) ip_address = self.module.params.get('ip_address') if not ip_address: self.module.fail_json( msg="IP address param 'ip_address' is required") args = {} args['ipaddress'] = ip_address args['account'] = self.get_account(key='name') args['domainid'] = self.get_domain(key='id') args['projectid'] = self.get_project(key='id') ip_addresses = self.cs.listPublicIpAddresses(**args) if not ip_addresses: self.module.fail_json( msg="IP address '%s' not found" % args['ipaddress']) self.ip_address = ip_addresses['publicipaddress'][0] return self._get_by_key(key, self.ip_address) def get_vm(self, key=None): if self.vm: return self._get_by_key(key, self.vm) vm = self.module.params.get('vm') if not vm: self.module.fail_json(msg="Virtual machine param 'vm' is required") args = {} args['account'] = self.get_account(key='name') args['domainid'] = self.get_domain(key='id') args['projectid'] = self.get_project(key='id') args['zoneid'] = self.get_zone(key='id') vms = self.cs.listVirtualMachines(**args) if vms: for v in vms['virtualmachine']: if vm in [v['name'], v['displayname'], v['id']]: self.vm = v return self._get_by_key(key, self.vm) self.module.fail_json(msg="Virtual machine '%s' not found" % vm) def get_zone(self, key=None): if self.zone: return self._get_by_key(key, self.zone) zone = self.module.params.get('zone') zones = self.cs.listZones() # use the first zone if no zone param given if not zone: self.zone = zones['zone'][0] return self._get_by_key(key, self.zone) if zones: for z in zones['zone']: if zone in [z['name'], z['id']]: self.zone = z return self._get_by_key(key, self.zone) self.module.fail_json(msg="zone '%s' not found" % zone) def get_os_type(self, key=None): if self.os_type: return self._get_by_key(key, self.zone) os_type = self.module.params.get('os_type') if not os_type: return None os_types = self.cs.listOsTypes() if os_types: for o in os_types['ostype']: if os_type in [o['description'], o['id']]: self.os_type = o return self._get_by_key(key, self.os_type) self.module.fail_json(msg="OS type '%s' not found" % os_type) def get_hypervisor(self): if self.hypervisor: return self.hypervisor hypervisor = self.module.params.get('hypervisor') hypervisors = self.cs.listHypervisors() # use the first hypervisor if no hypervisor param given if not hypervisor: self.hypervisor = hypervisors['hypervisor'][0]['name'] return self.hypervisor for h in hypervisors['hypervisor']: if hypervisor.lower() == h['name'].lower(): self.hypervisor = h['name'] return self.hypervisor self.module.fail_json(msg="Hypervisor '%s' not found" % hypervisor) def get_account(self, key=None): if self.account: return self._get_by_key(key, self.account) account = self.module.params.get('account') if not account: return None domain = self.module.params.get('domain') if not domain: self.module.fail_json(msg="Account must be specified with Domain") args = {} args['name'] = account args['domainid'] = self.get_domain(key='id') args['listall'] = True accounts = self.cs.listAccounts(**args) if accounts: self.account = accounts['account'][0] return self._get_by_key(key, self.account) self.module.fail_json(msg="Account '%s' not found" % account) def get_domain(self, key=None): if self.domain: return self._get_by_key(key, self.domain) domain = self.module.params.get('domain') if not domain: return None args = {} args['listall'] = True domains = self.cs.listDomains(**args) if domains: for d in domains['domain']: if d['path'].lower() in [ domain.lower(), "root/" + domain.lower(), "root" + domain.lower() ]: self.domain = d return self._get_by_key(key, self.domain) self.module.fail_json(msg="Domain '%s' not found" % domain) def get_tags(self, resource=None): if not self.tags: args = {} args['projectid'] = self.get_project(key='id') args['account'] = self.get_account(key='name') args['domainid'] = self.get_domain(key='id') args['resourceid'] = resource['id'] response = self.cs.listTags(**args) self.tags = response.get('tag', []) existing_tags = [] if self.tags: for tag in self.tags: existing_tags.append({ 'key': tag['key'], 'value': tag['value'] }) return existing_tags def _process_tags(self, resource, resource_type, tags, operation="create"): if tags: self.result['changed'] = True if not self.module.check_mode: args = {} args['resourceids'] = resource['id'] args['resourcetype'] = resource_type args['tags'] = tags if operation == "create": response = self.cs.createTags(**args) else: response = self.cs.deleteTags(**args) self.poll_job(response) def _tags_that_should_exist_or_be_updated(self, resource, tags): existing_tags = self.get_tags(resource) return [tag for tag in tags if tag not in existing_tags] def _tags_that_should_not_exist(self, resource, tags): existing_tags = self.get_tags(resource) return [tag for tag in existing_tags if tag not in tags] def ensure_tags(self, resource, resource_type=None): if not resource_type or not resource: self.module.fail_json( msg="Error: Missing resource or resource_type for tags.") if 'tags' in resource: tags = self.module.params.get('tags') if tags is not None: self._process_tags( resource, resource_type, self._tags_that_should_not_exist(resource, tags), operation="delete") self._process_tags( resource, resource_type, self._tags_that_should_exist_or_be_updated(resource, tags)) self.tags = None resource['tags'] = self.get_tags(resource) return resource def get_capabilities(self, key=None): if self.capabilities: return self._get_by_key(key, self.capabilities) capabilities = self.cs.listCapabilities() self.capabilities = capabilities['capability'] return self._get_by_key(key, self.capabilities) # TODO: for backward compatibility only, remove if not used anymore def _poll_job(self, job=None, key=None): return self.poll_job(job=job, key=key) def poll_job(self, job=None, key=None): if 'jobid' in job: while True: res = self.cs.queryAsyncJobResult(jobid=job['jobid']) if res['jobstatus'] != 0 and 'jobresult' in res: if 'errortext' in res['jobresult']: self.module.fail_json( msg="Failed: '%s'" % res['jobresult']['errortext']) if key and key in res['jobresult']: job = res['jobresult'][key] break time.sleep(2) return job def get_result(self, resource): if resource: returns = self.common_returns.copy() returns.update(self.returns) for search_key, return_key in returns.iteritems(): if search_key in resource: self.result[return_key] = resource[search_key] # Bad bad API does not always return int when it should. for search_key, return_key in self.returns_to_int.iteritems(): if search_key in resource: self.result[return_key] = int(resource[search_key]) # Special handling for tags if 'tags' in resource: self.result['tags'] = [] for tag in resource['tags']: result_tag = {} result_tag['key'] = tag['key'] result_tag['value'] = tag['value'] self.result['tags'].append(result_tag) return self.result
class CloudStackInventory(object): def __init__(self): parser = argparse.ArgumentParser() parser.add_argument('--host') parser.add_argument('--list', action='store_true') parser.add_argument('--project') options = parser.parse_args() try: self.cs = CloudStack(**read_config()) except CloudStackException as e: print("Error: Could not connect to CloudStack API", file=sys.stderr) project_id = '' if options.project: project_id = self.get_project_id(options.project) if options.host: data = self.get_host(options.host) print(json.dumps(data, indent=2)) elif options.list: data = self.get_list() print(json.dumps(data, indent=2)) else: print("usage: --list | --host <hostname> [--project <project>]", file=sys.stderr) sys.exit(1) def get_project_id(self, project): projects = self.cs.listProjects() if projects: for p in projects['project']: if p['name'] == project or p['id'] == project: return p['id'] print("Error: Project %s not found." % project, file=sys.stderr) sys.exit(1) def get_host(self, name, project_id=''): hosts = self.cs.listVirtualMachines(projectid=project_id) data = {} if not hosts: return data for host in hosts['virtualmachine']: host_name = host['displayname'] if name == host_name: data['zone'] = host['zonename'] if 'group' in host: data['group'] = host['group'] data['state'] = host['state'] data['service_offering'] = host['serviceofferingname'] data['affinity_group'] = host['affinitygroup'] data['security_group'] = host['securitygroup'] data['cpu_number'] = host['cpunumber'] data['cpu_speed'] = host['cpuspeed'] if 'cpuused' in host: data['cpu_used'] = host['cpuused'] data['memory'] = host['memory'] data['tags'] = host['tags'] data['hypervisor'] = host['hypervisor'] data['created'] = host['created'] data['nic'] = [] for nic in host['nic']: data['nic'].append({ 'ip': nic['ipaddress'], 'mac': nic['macaddress'], 'netmask': nic['netmask'], 'gateway': nic['gateway'], 'type': nic['type'], }) if nic['isdefault']: data['default_ip'] = nic['ipaddress'] break; return data def get_list(self, project_id=''): data = { 'all': { 'hosts': [], }, '_meta': { 'hostvars': {}, }, } groups = self.cs.listInstanceGroups(projectid=project_id) if groups: for group in groups['instancegroup']: group_name = group['name'] if group_name and not group_name in data: data[group_name] = { 'hosts': [] } hosts = self.cs.listVirtualMachines(projectid=project_id) if not hosts: return data for host in hosts['virtualmachine']: host_name = host['displayname'] data['all']['hosts'].append(host_name) data['_meta']['hostvars'][host_name] = {} data['_meta']['hostvars'][host_name]['zone'] = host['zonename'] if 'group' in host: data['_meta']['hostvars'][host_name]['group'] = host['group'] data['_meta']['hostvars'][host_name]['state'] = host['state'] data['_meta']['hostvars'][host_name]['service_offering'] = host['serviceofferingname'] data['_meta']['hostvars'][host_name]['affinity_group'] = host['affinitygroup'] data['_meta']['hostvars'][host_name]['security_group'] = host['securitygroup'] data['_meta']['hostvars'][host_name]['cpu_number'] = host['cpunumber'] data['_meta']['hostvars'][host_name]['cpu_speed'] = host['cpuspeed'] if 'cpuused' in host: data['_meta']['hostvars'][host_name]['cpu_used'] = host['cpuused'] data['_meta']['hostvars'][host_name]['created'] = host['created'] data['_meta']['hostvars'][host_name]['memory'] = host['memory'] data['_meta']['hostvars'][host_name]['tags'] = host['tags'] data['_meta']['hostvars'][host_name]['hypervisor'] = host['hypervisor'] data['_meta']['hostvars'][host_name]['created'] = host['created'] data['_meta']['hostvars'][host_name]['nic'] = [] for nic in host['nic']: data['_meta']['hostvars'][host_name]['nic'].append({ 'ip': nic['ipaddress'], 'mac': nic['macaddress'], 'netmask': nic['netmask'], 'gateway': nic['gateway'], 'type': nic['type'], }) if nic['isdefault']: data['_meta']['hostvars'][host_name]['default_ip'] = nic['ipaddress'] group_name = '' if 'group' in host: group_name = host['group'] if group_name and group_name in data: data[group_name]['hosts'].append(host_name) return data
class AnsibleCloudStack: def __init__(self, module): if not has_lib_cs: module.fail_json(msg="python library cs required: pip install cs") self.module = module self._connect() self.project_id = None self.ip_address_id = None self.zone_id = None self.vm_id = None self.os_type_id = None self.hypervisor = None def _connect(self): api_key = self.module.params.get('api_key') api_secret = self.module.params.get('secret_key') api_url = self.module.params.get('api_url') api_http_method = self.module.params.get('api_http_method') if api_key and api_secret and api_url: self.cs = CloudStack( endpoint=api_url, key=api_key, secret=api_secret, method=api_http_method ) else: self.cs = CloudStack(**read_config()) def get_project_id(self): if self.project_id: return self.project_id project = self.module.params.get('project') if not project: return None projects = self.cs.listProjects() if projects: for p in projects['project']: if project in [ p['name'], p['displaytext'], p['id'] ]: self.project_id = p['id'] return self.project_id self.module.fail_json(msg="project '%s' not found" % project) def get_ip_address_id(self): if self.ip_address_id: return self.ip_address_id ip_address = self.module.params.get('ip_address') if not ip_address: self.module.fail_json(msg="IP address param 'ip_address' is required") args = {} args['ipaddress'] = ip_address args['projectid'] = self.get_project_id() ip_addresses = self.cs.listPublicIpAddresses(**args) if not ip_addresses: self.module.fail_json(msg="IP address '%s' not found" % args['ipaddress']) self.ip_address_id = ip_addresses['publicipaddress'][0]['id'] return self.ip_address_id def get_vm_id(self): if self.vm_id: return self.vm_id vm = self.module.params.get('vm') if not vm: self.module.fail_json(msg="Virtual machine param 'vm' is required") args = {} args['projectid'] = self.get_project_id() vms = self.cs.listVirtualMachines(**args) if vms: for v in vms['virtualmachine']: if vm in [ v['name'], v['displaytext'] v['id'] ]: self.vm_id = v['id'] return self.vm_id self.module.fail_json(msg="Virtual machine '%s' not found" % vm)
class AnsibleCloudStack(object): def __init__(self, module): if not has_lib_cs: module.fail_json(msg="python library cs required: pip install cs") self.result = {"changed": False} # Common returns, will be merged with self.returns # search_for_key: replace_with_key self.common_returns = { "id": "id", "name": "name", "created": "created", "zonename": "zone", "state": "state", "project": "project", "account": "account", "domain": "domain", "displaytext": "display_text", "displayname": "display_name", "description": "description", } # Init returns dict for use in subclasses self.returns = {} self.module = module self._connect() self.domain = None self.account = None self.project = None self.ip_address = None self.zone = None self.vm = None self.os_type = None self.hypervisor = None self.capabilities = None def _connect(self): api_key = self.module.params.get("api_key") api_secret = self.module.params.get("secret_key") api_url = self.module.params.get("api_url") api_http_method = self.module.params.get("api_http_method") api_timeout = self.module.params.get("api_timeout") if api_key and api_secret and api_url: self.cs = CloudStack( endpoint=api_url, key=api_key, secret=api_secret, timeout=api_timeout, method=api_http_method ) else: api_region = self.module.params.get("api_region", "cloudstack") self.cs = CloudStack(**read_config(api_region)) def get_or_fallback(self, key=None, fallback_key=None): value = self.module.params.get(key) if not value: value = self.module.params.get(fallback_key) return value # TODO: for backward compatibility only, remove if not used anymore def _has_changed(self, want_dict, current_dict, only_keys=None): return self.has_changed(want_dict=want_dict, current_dict=current_dict, only_keys=only_keys) def has_changed(self, want_dict, current_dict, only_keys=None): for key, value in want_dict.iteritems(): # Optionally limit by a list of keys if only_keys and key not in only_keys: continue # Skip None values if value is None: continue if key in current_dict: # API returns string for int in some cases, just to make sure if isinstance(value, int): current_dict[key] = int(current_dict[key]) elif isinstance(value, str): current_dict[key] = str(current_dict[key]) # Only need to detect a singe change, not every item if value != current_dict[key]: return True return False def _get_by_key(self, key=None, my_dict={}): if key: if key in my_dict: return my_dict[key] self.module.fail_json(msg="Something went wrong: %s not found" % key) return my_dict def get_project(self, key=None): if self.project: return self._get_by_key(key, self.project) project = self.module.params.get("project") if not project: return None args = {} args["account"] = self.get_account(key="name") args["domainid"] = self.get_domain(key="id") projects = self.cs.listProjects(**args) if projects: for p in projects["project"]: if project.lower() in [p["name"].lower(), p["id"]]: self.project = p return self._get_by_key(key, self.project) self.module.fail_json(msg="project '%s' not found" % project) def get_ip_address(self, key=None): if self.ip_address: return self._get_by_key(key, self.ip_address) ip_address = self.module.params.get("ip_address") if not ip_address: self.module.fail_json(msg="IP address param 'ip_address' is required") args = {} args["ipaddress"] = ip_address args["account"] = self.get_account(key="name") args["domainid"] = self.get_domain(key="id") args["projectid"] = self.get_project(key="id") ip_addresses = self.cs.listPublicIpAddresses(**args) if not ip_addresses: self.module.fail_json(msg="IP address '%s' not found" % args["ipaddress"]) self.ip_address = ip_addresses["publicipaddress"][0] return self._get_by_key(key, self.ip_address) def get_vm(self, key=None): if self.vm: return self._get_by_key(key, self.vm) vm = self.module.params.get("vm") if not vm: self.module.fail_json(msg="Virtual machine param 'vm' is required") args = {} args["account"] = self.get_account(key="name") args["domainid"] = self.get_domain(key="id") args["projectid"] = self.get_project(key="id") args["zoneid"] = self.get_zone(key="id") vms = self.cs.listVirtualMachines(**args) if vms: for v in vms["virtualmachine"]: if vm in [v["name"], v["displayname"], v["id"]]: self.vm = v return self._get_by_key(key, self.vm) self.module.fail_json(msg="Virtual machine '%s' not found" % vm) def get_zone(self, key=None): if self.zone: return self._get_by_key(key, self.zone) zone = self.module.params.get("zone") zones = self.cs.listZones() # use the first zone if no zone param given if not zone: self.zone = zones["zone"][0] return self._get_by_key(key, self.zone) if zones: for z in zones["zone"]: if zone in [z["name"], z["id"]]: self.zone = z return self._get_by_key(key, self.zone) self.module.fail_json(msg="zone '%s' not found" % zone) def get_os_type(self, key=None): if self.os_type: return self._get_by_key(key, self.zone) os_type = self.module.params.get("os_type") if not os_type: return None os_types = self.cs.listOsTypes() if os_types: for o in os_types["ostype"]: if os_type in [o["description"], o["id"]]: self.os_type = o return self._get_by_key(key, self.os_type) self.module.fail_json(msg="OS type '%s' not found" % os_type) def get_hypervisor(self): if self.hypervisor: return self.hypervisor hypervisor = self.module.params.get("hypervisor") hypervisors = self.cs.listHypervisors() # use the first hypervisor if no hypervisor param given if not hypervisor: self.hypervisor = hypervisors["hypervisor"][0]["name"] return self.hypervisor for h in hypervisors["hypervisor"]: if hypervisor.lower() == h["name"].lower(): self.hypervisor = h["name"] return self.hypervisor self.module.fail_json(msg="Hypervisor '%s' not found" % hypervisor) def get_account(self, key=None): if self.account: return self._get_by_key(key, self.account) account = self.module.params.get("account") if not account: return None domain = self.module.params.get("domain") if not domain: self.module.fail_json(msg="Account must be specified with Domain") args = {} args["name"] = account args["domainid"] = self.get_domain(key="id") args["listall"] = True accounts = self.cs.listAccounts(**args) if accounts: self.account = accounts["account"][0] return self._get_by_key(key, self.account) self.module.fail_json(msg="Account '%s' not found" % account) def get_domain(self, key=None): if self.domain: return self._get_by_key(key, self.domain) domain = self.module.params.get("domain") if not domain: return None args = {} args["listall"] = True domains = self.cs.listDomains(**args) if domains: for d in domains["domain"]: if d["path"].lower() in [domain.lower(), "root/" + domain.lower(), "root" + domain.lower()]: self.domain = d return self._get_by_key(key, self.domain) self.module.fail_json(msg="Domain '%s' not found" % domain) def get_tags(self, resource=None): existing_tags = self.cs.listTags(resourceid=resource["id"]) if existing_tags: return existing_tags["tag"] return [] def _delete_tags(self, resource, resource_type, tags): existing_tags = resource["tags"] tags_to_delete = [] for existing_tag in existing_tags: if existing_tag["key"] in tags: if existing_tag["value"] != tags[key]: tags_to_delete.append(existing_tag) else: tags_to_delete.append(existing_tag) if tags_to_delete: self.result["changed"] = True if not self.module.check_mode: args = {} args["resourceids"] = resource["id"] args["resourcetype"] = resource_type args["tags"] = tags_to_delete self.cs.deleteTags(**args) def _create_tags(self, resource, resource_type, tags): tags_to_create = [] for i, tag_entry in enumerate(tags): tag = {"key": tag_entry["key"], "value": tag_entry["value"]} tags_to_create.append(tag) if tags_to_create: self.result["changed"] = True if not self.module.check_mode: args = {} args["resourceids"] = resource["id"] args["resourcetype"] = resource_type args["tags"] = tags_to_create self.cs.createTags(**args) def ensure_tags(self, resource, resource_type=None): if not resource_type or not resource: self.module.fail_json(msg="Error: Missing resource or resource_type for tags.") if "tags" in resource: tags = self.module.params.get("tags") if tags is not None: self._delete_tags(resource, resource_type, tags) self._create_tags(resource, resource_type, tags) resource["tags"] = self.get_tags(resource) return resource def get_disk_offering(self, key=None): disk_offering = self.module.params.get("disk_offering") if not disk_offering: return None disk_offerings = self.cs.listDiskOfferings() if disk_offerings: for d in disk_offerings["diskoffering"]: if disk_offering in [d["displaytext"], d["name"], d["id"]]: return self._get_by_key(key, d) self.module.fail_json(msg="Disk offering '%s' not found" % disk_offering) def get_capabilities(self, key=None): if self.capabilities: return self._get_by_key(key, self.capabilities) capabilities = self.cs.listCapabilities() self.capabilities = capabilities["capability"] return self._get_by_key(key, self.capabilities) # TODO: for backward compatibility only, remove it if not used anymore def _poll_job(self, job=None, key=None): return self.poll_job(job=job, key=key) def poll_job(self, job=None, key=None): if "jobid" in job: while True: res = self.cs.queryAsyncJobResult(jobid=job["jobid"]) if res["jobstatus"] != 0 and "jobresult" in res: if "errortext" in res["jobresult"]: self.module.fail_json(msg="Failed: '%s'" % res["jobresult"]["errortext"]) if key and key in res["jobresult"]: job = res["jobresult"][key] break time.sleep(2) return job def get_result(self, resource): if resource: returns = self.common_returns.copy() returns.update(self.returns) for search_key, return_key in returns.iteritems(): if search_key in resource: self.result[return_key] = resource[search_key] # Special handling for tags if "tags" in resource: self.result["tags"] = [] for tag in resource["tags"]: result_tag = {} result_tag["key"] = tag["key"] result_tag["value"] = tag["value"] self.result["tags"].append(result_tag) return self.result
class AnsibleCloudStack: def __init__(self, module): if not has_lib_cs: module.fail_json(msg="python library cs required: pip install cs") self.module = module self._connect() self.project_id = None self.ip_address_id = None self.zone_id = None self.vm_id = None self.os_type_id = None self.hypervisor = None def _connect(self): api_key = self.module.params.get('api_key') api_secret = self.module.params.get('api_secret') api_url = self.module.params.get('api_url') api_http_method = self.module.params.get('api_http_method') if api_key and api_secret and api_url: self.cs = CloudStack( endpoint=api_url, key=api_key, secret=api_secret, method=api_http_method ) else: self.cs = CloudStack(**read_config()) def get_project_id(self): if self.project_id: return self.project_id project = self.module.params.get('project') if not project: return None projects = self.cs.listProjects() if projects: for p in projects['project']: if project in [ p['name'], p['displaytext'], p['id'] ]: self.project_id = p['id'] return self.project_id self.module.fail_json(msg="project '%s' not found" % project) def get_ip_address_id(self): if self.ip_address_id: return self.ip_address_id ip_address = self.module.params.get('ip_address') if not ip_address: self.module.fail_json(msg="IP address param 'ip_address' is required") args = {} args['ipaddress'] = ip_address args['projectid'] = self.get_project_id() ip_addresses = self.cs.listPublicIpAddresses(**args) if not ip_addresses: self.module.fail_json(msg="IP address '%s' not found" % args['ipaddress']) self.ip_address_id = ip_addresses['publicipaddress'][0]['id'] return self.ip_address_id def get_vm_id(self): if self.vm_id: return self.vm_id vm = self.module.params.get('vm') if not vm: self.module.fail_json(msg="Virtual machine param 'vm' is required") args = {} args['projectid'] = self.get_project_id() vms = self.cs.listVirtualMachines(**args) if vms: for v in vms['virtualmachine']: if vm in [ v['name'], v['displayname'], v['id'] ]: self.vm_id = v['id'] return self.vm_id self.module.fail_json(msg="Virtual machine '%s' not found" % vm) def get_zone_id(self): if self.zone_id: return self.zone_id zone = self.module.params.get('zone') zones = self.cs.listZones() # use the first zone if no zone param given if not zone: self.zone_id = zones['zone'][0]['id'] return self.zone_id if zones: for z in zones['zone']: if zone in [ z['name'], z['id'] ]: self.zone_id = z['id'] return self.zone_id self.module.fail_json(msg="zone '%s' not found" % zone) def get_os_type_id(self): if self.os_type_id: return self.os_type_id os_type = self.module.params.get('os_type') if not os_type: return None os_types = self.cs.listOsTypes() if os_types: for o in os_types['ostype']: if os_type in [ o['description'], o['id'] ]: self.os_type_id = o['id'] return self.os_type_id self.module.fail_json(msg="OS type '%s' not found" % os_type) def get_hypervisor(self): if self.hypervisor: return self.hypervisor hypervisor = self.module.params.get('hypervisor') hypervisors = self.cs.listHypervisors() # use the first hypervisor if no hypervisor param given if not hypervisor: self.hypervisor = hypervisors['hypervisor'][0]['name'] return self.hypervisor for h in hypervisors['hypervisor']: if hypervisor.lower() == h['name'].lower(): self.hypervisor = h['name'] return self.hypervisor self.module.fail_json(msg="Hypervisor '%s' not found" % hypervisor) def _poll_job(self, job=None, key=None): if 'jobid' in job: while True: res = self.cs.queryAsyncJobResult(jobid=job['jobid']) if res['jobstatus'] != 0 and 'jobresult' in res: if 'errortext' in res['jobresult']: self.module.fail_json(msg="Failed: '%s'" % res['jobresult']['errortext']) if key and key in res['jobresult']: job = res['jobresult'][key] break time.sleep(2) return job
def get_stats(): timeout = 300 stats = dict() hvmrunning = defaultdict(int) hvmstopped = defaultdict(int) hvmstopping = defaultdict(int) hvmstarting = defaultdict(int) cs = CloudStack(endpoint=API_MONITORS, key=APIKEY_MONITORS, secret=SECRET_MONITORS, timeout=timeout) logger('verb', "get_stats calls API %s KEY %s SECRET %s" % (API_MONITORS, APIKEY_MONITORS, SECRET_MONITORS)) try: logger('verb', "Performing listhosts API call") hypervisors = cs_list(cs, 'listHosts', 'host', type='Routing', resourcestate='Enabled', state='Up') logger('verb', "Completed listhosts API call") except Exception: logger('warn', "status err Unable to connect to CloudStack URL at %s for Hosts" % API_MONITORS) for h in hypervisors: metricnameMemUsed = METRIC_DELIM.join([h['name'].lower(), h['podname'].lower(), re.sub(r"\s+", '-', h['zonename'].lower()), 'memoryused']) metricnameMemTotal = METRIC_DELIM.join([h['name'].lower(), h['podname'].lower(), re.sub(r"\s+", '-', h['zonename'].lower()), 'memorytotal']) metricnameMemAlloc = METRIC_DELIM.join([h['name'].lower(), h['podname'].lower(), re.sub(r"\s+", '-', h['zonename'].lower()), 'memoryallocated']) metricnameMemAllocPercent = METRIC_DELIM.join([h['name'].lower(), h['podname'].lower(), re.sub(r"\s+", '-', h['zonename'].lower()), 'memoryallocatedpercent']) metricnameCpuAlloc = METRIC_DELIM.join([h['name'].lower(), h['podname'].lower(), re.sub(r"\s+", '-', h['zonename'].lower()), 'cpuallocated']) try: memorytotal = int(h['memorytotal']) memoryallocated = int(h['memoryallocated']) stats[metricnameMemUsed] = h['memoryused'] stats[metricnameMemTotal] = memorytotal stats[metricnameMemAlloc] = memoryallocated stats[metricnameMemAllocPercent] = round(memoryallocated / memorytotal, 4) if memorytotal > 0 else 0 cpuallocated = h['cpuallocated'].replace("%", "") stats[metricnameCpuAlloc] = cpuallocated logger('verb', "readings : %s memory used %s " % (h['name'], h['memoryused'])) except (TypeError, ValueError, KeyError): pass # collect disk metrics try: logger('verb', "Performing liststoragepools API call") pools = cs_list(cs, 'listStoragePools', 'storagepool') logger('verb', "Completed liststoragepools API call") except Exception: logger('warn', "status err Unable to connect to CloudStack URL at %s for storage pools" % API_MONITORS) for h in pools: name = h['name'].split()[0] # to avoid "Local Storage" in the pool name metricnameDiskAlloc = METRIC_DELIM.join([name.lower(), h['podname'].lower(), re.sub(r"\s+", '-', h['zonename'].lower()), 'disksizeallocated']) metricnameDiskAllocPercent = METRIC_DELIM.join([name.lower(), h['podname'].lower(), re.sub(r"\s+", '-', h['zonename'].lower()), 'disksizeallocatedpercent']) metricnameDiskUsed = METRIC_DELIM.join([name.lower(), h['podname'].lower(), re.sub(r"\s+", '-', h['zonename'].lower()), 'disksizeused']) metricnameDiskTotal = METRIC_DELIM.join([name.lower(), h['podname'].lower(), re.sub(r"\s+", '-', h['zonename'].lower()), 'disksizetotal']) try: disksizeallocated = int(h['disksizeallocated']) disksizetotal = int(h['disksizetotal']) stats[metricnameDiskAlloc] = disksizeallocated stats[metricnameDiskUsed] = h['disksizeused'] stats[metricnameDiskTotal] = h['disksizetotal'] stats[metricnameDiskAllocPercent] = round(disksizeallocated / disksizetotal, 4) if disksizetotal > 0 else 0 except (TypeError, ValueError, KeyError): pass # collect number of active console sessions try: logger('verb', "Performing listSystemVms API call") systemvms = cs_list(cs, 'listSystemVms', 'systemvm', systemvmtype='consoleproxy') logger('verb', "Completed listSystemVms API call") except Exception: logger('warn', "status err Unable to connect to CloudStack URL at %s for SystemVms" % API_MONITORS) for systemvm in systemvms: metricnameSessions = METRIC_DELIM.join(['activeviewersessions', systemvm['zonename'].lower(), systemvm['name'].lower(), 'activeviewersessions']) if 'activeviewersessions' in systemvm: stats[metricnameSessions] = systemvm['activeviewersessions'] # collect number of zones, available public ips and VMs try: logger('verb', "Performing listZones API call") zones = cs_list(cs, 'listZones', 'zone', showcapacities='true') logger('verb', "Completed listZones API call") except Exception: logger('warn', "status err Unable to connect to CloudStack URL at %s for ListZone" % API_MONITORS) for zone in zones: metricnameIpAllocated = METRIC_DELIM.join(['zonepublicipallocated', zone['name'].lower(), 'zonepublicipallocated']) metricnameIpTotal = METRIC_DELIM.join(['zonepubliciptotal', zone['name'].lower(), 'zonepubliciptotal']) metricnameIpAllocatedPercent = METRIC_DELIM.join(['zonepublicippercent', zone['name'].lower(), 'zonepublicippercent']) metricnameVmZoneTotalRunning = METRIC_DELIM.join(['zonevmtotalrunning', zone['name'].lower(), 'zonevmtotalrunning']) metricnameVmZoneTotalRunningMicro = METRIC_DELIM.join(['zonevmtotalrunningmicro', zone['name'].lower(), 'zonevmtotalrunningmicro']) metricnameVmZoneTotalRunningTiny = METRIC_DELIM.join(['zonevmtotalrunningtiny', zone['name'].lower(), 'zonevmtotalrunningtiny']) metricnameVmZoneTotalRunningSmall = METRIC_DELIM.join(['zonevmtotalrunningsmall', zone['name'].lower(), 'zonevmtotalrunningsmall']) metricnameVmZoneTotalRunningMedium = METRIC_DELIM.join(['zonevmtotalrunningmedium', zone['name'].lower(), 'zonevmtotalrunningmedium']) metricnameVmZoneTotalRunningLarge = METRIC_DELIM.join(['zonevmtotalrunninglarge', zone['name'].lower(), 'zonevmtotalrunninglarge']) metricnameVmZoneTotalRunningXLarge = METRIC_DELIM.join(['zonevmtotalrunningxlarge', zone['name'].lower(), 'zonevmtotalrunningxlarge']) metricnameVmZoneTotalRunningHuge = METRIC_DELIM.join(['zonevmtotalrunninghuge', zone['name'].lower(), 'zonevmtotalrunninghuge']) metricnameVmZoneTotalRunningMega = METRIC_DELIM.join(['zonevmtotalrunningmega', zone['name'].lower(), 'zonevmtotalrunningmega']) metricnameVmZoneTotalRunningTitan = METRIC_DELIM.join(['zonevmtotalrunningtitan', zone['name'].lower(), 'zonevmtotalrunningtitan']) metricnameVmZoneTotalStopped = METRIC_DELIM.join(['zonevmtotalstopped', zone['name'].lower(), 'zonevmtotalstopped']) metricnameVmZoneTotalStoppedMicro = METRIC_DELIM.join(['zonevmtotalstoppedmicro', zone['name'].lower(), 'zonevmtotalstoppedmicro']) metricnameVmZoneTotalStoppedTiny = METRIC_DELIM.join(['zonevmtotalstoppedtiny', zone['name'].lower(), 'zonevmtotalstoppedtiny']) metricnameVmZoneTotalStoppedSmall = METRIC_DELIM.join(['zonevmtotalstoppedsmall', zone['name'].lower(), 'zonevmtotalstoppedsmall']) metricnameVmZoneTotalStoppedMedium = METRIC_DELIM.join(['zonevmtotalstoppedmedium', zone['name'].lower(), 'zonevmtotalstoppedmedium']) metricnameVmZoneTotalStoppedLarge = METRIC_DELIM.join(['zonevmtotalstoppedlarge', zone['name'].lower(), 'zonevmtotalstoppedlarge']) metricnameVmZoneTotalStoppedXLarge = METRIC_DELIM.join(['zonevmtotalstoppedxlarge', zone['name'].lower(), 'zonevmtotalstoppedxlarge']) metricnameVmZoneTotalStoppedHuge = METRIC_DELIM.join(['zonevmtotalstoppedhuge', zone['name'].lower(), 'zonevmtotalstoppedhuge']) metricnameVmZoneTotalStoppedMega = METRIC_DELIM.join(['zonevmtotalstoppedmega', zone['name'].lower(), 'zonevmtotalstoppedmega']) metricnameVmZoneTotalStoppedTitan = METRIC_DELIM.join(['zonevmtotalstoppedtitan', zone['name'].lower(), 'zonevmtotalstoppedtitan']) metricnameVmZoneTotalStopping = METRIC_DELIM.join(['zonevmtotalstopping', zone['name'].lower(), 'zonevmtotalstopping']) metricnameVmZoneTotalStarting = METRIC_DELIM.join(['zonevmtotalstarting', zone['name'].lower(), 'zonevmtotalstarting']) metricnameVmZoneTotalMicro = METRIC_DELIM.join(['zonevmtotalmicro', zone['name'].lower(), 'zonevmtotalmicro']) metricnameVmZoneTotalTiny = METRIC_DELIM.join(['zonevmtotaltiny', zone['name'].lower(), 'zonevmtotaltiny']) metricnameVmZoneTotalSmall = METRIC_DELIM.join(['zonevmtotalsmall', zone['name'].lower(), 'zonevmtotalsmall']) metricnameVmZoneTotalMedium = METRIC_DELIM.join(['zonevmtotalmedium', zone['name'].lower(), 'zonevmtotalmedium']) metricnameVmZoneTotalLarge = METRIC_DELIM.join(['zonevmtotallarge', zone['name'].lower(), 'zonevmtotallarge']) metricnameVmZoneTotalXLarge = METRIC_DELIM.join(['zonevmtotalxlarge', zone['name'].lower(), 'zonevmtotalxlarge']) metricnameVmZoneTotalHuge = METRIC_DELIM.join(['zonevmtotalhuge', zone['name'].lower(), 'zonevmtotalhuge']) metricnameVmZoneTotalMega = METRIC_DELIM.join(['zonevmtotalmega', zone['name'].lower(), 'zonevmtotalmega']) metricnameVmZoneTotalTitan = METRIC_DELIM.join(['zonevmtotaltitan', zone['name'].lower(), 'zonevmtotaltitan']) metricnameVmZoneTotal = METRIC_DELIM.join(['zonevmtotal', zone['name'].lower(), 'zonevmtotal']) metricnameZonesCount = METRIC_DELIM.join(['zonescount', 'zonescount']) metricnameHostZoneTotal = METRIC_DELIM.join(['zonehosttotal', zone['name'].lower(), 'zonehosttotal']) metricnameVMZoneRAMavgSize = METRIC_DELIM.join(['zonevmramavgsize', zone['name'].lower(), 'zonevmramavgsize']) metricnameVMZoneCPUavgSize = METRIC_DELIM.join(['zonevmcpuavgsize', zone['name'].lower(), 'zonevmcpuavgsize']) # collect number of virtual machines zoneid = zone['id'] try: logger('verb', "Performing listVirtualMachines API call") virtualmachines = cs_list(cs, 'listVirtualMachines', 'virtualmachine', details='all', zoneid=zoneid) logger('verb', "Completed listVirtualMachines API call") except Exception: logger('warn', "status err Unable to connect to CloudStack URL at %s for ListVms" % API_MONITORS) virtualMachineZoneRunningCount = 0 virtualMachineZoneRunningMicroCount = 0 virtualMachineZoneRunningTinyCount = 0 virtualMachineZoneRunningSmallCount = 0 virtualMachineZoneRunningMediumCount = 0 virtualMachineZoneRunningLargeCount = 0 virtualMachineZoneRunningXLargeCount = 0 virtualMachineZoneRunningHugeCount = 0 virtualMachineZoneRunningMegaCount = 0 virtualMachineZoneRunningTitanCount = 0 virtualMachineZoneStoppedCount = 0 virtualMachineZoneStoppedMicroCount = 0 virtualMachineZoneStoppedTinyCount = 0 virtualMachineZoneStoppedSmallCount = 0 virtualMachineZoneStoppedMediumCount = 0 virtualMachineZoneStoppedLargeCount = 0 virtualMachineZoneStoppedXLargeCount = 0 virtualMachineZoneStoppedHugeCount = 0 virtualMachineZoneStoppedMegaCount = 0 virtualMachineZoneStoppedTitanCount = 0 virtualMachineZoneStartingCount = 0 virtualMachineZoneStoppingCount = 0 virtualMachineZoneMicro = 0 virtualMachineZoneTiny = 0 virtualMachineZoneSmall = 0 virtualMachineZoneMedium = 0 virtualMachineZoneLarge = 0 virtualMachineZoneXLarge = 0 virtualMachineZoneHuge = 0 virtualMachineZoneMega = 0 virtualMachineZoneTitan = 0 cpu = 0 ram = 0 for virtualmachine in virtualmachines: cpu += virtualmachine['cpunumber'] ram += virtualmachine['memory'] if virtualmachine['state'] == 'Running': virtualMachineZoneRunningCount += 1 elif virtualmachine['state'] == 'Stopped': virtualMachineZoneStoppedCount += 1 elif virtualmachine['state'] == 'Stopping': virtualMachineZoneStartingCount += 1 elif virtualmachine['state'] == 'Starting': virtualMachineZoneStoppingCount += 1 if virtualmachine['serviceofferingname'] == 'Micro': virtualMachineZoneMicro += 1 if virtualmachine['state'] == 'Running': virtualMachineZoneRunningMicroCount += 1 else: virtualMachineZoneStoppedMicroCount += 1 elif virtualmachine['serviceofferingname'] == 'Tiny': virtualMachineZoneTiny += 1 if virtualmachine['state'] == 'Running': virtualMachineZoneRunningTinyCount += 1 else: virtualMachineZoneStoppedTinyCount += 1 elif virtualmachine['serviceofferingname'] == 'Small': virtualMachineZoneSmall += 1 if virtualmachine['state'] == 'Running': virtualMachineZoneRunningSmallCount += 1 else: virtualMachineZoneStoppedSmallCount += 1 elif virtualmachine['serviceofferingname'] == 'Medium': virtualMachineZoneMedium += 1 if virtualmachine['state'] == 'Running': virtualMachineZoneRunningMediumCount += 1 else: virtualMachineZoneStoppedMediumCount += 1 elif virtualmachine['serviceofferingname'] == 'Large': virtualMachineZoneLarge += 1 if virtualmachine['state'] == 'Running': virtualMachineZoneRunningLargeCount += 1 else: virtualMachineZoneStoppedLargeCount += 1 elif virtualmachine['serviceofferingname'] == 'Extra-large': virtualMachineZoneXLarge += 1 if virtualmachine['state'] == 'Running': virtualMachineZoneRunningXLargeCount += 1 else: virtualMachineZoneStoppedXLargeCount += 1 elif virtualmachine['serviceofferingname'] == 'Huge': virtualMachineZoneHuge += 1 if virtualmachine['state'] == 'Running': virtualMachineZoneRunningHugeCount += 1 else: virtualMachineZoneStoppedHugeCount += 1 elif virtualmachine['serviceofferingname'] == 'Mega': virtualMachineZoneMega += 1 if virtualmachine['state'] == 'Running': virtualMachineZoneRunningMegaCount += 1 else: virtualMachineZoneStoppedMegaCount += 1 elif virtualmachine['serviceofferingname'] == 'Titan': virtualMachineZoneTitan += 1 if virtualmachine['state'] == 'Running': virtualMachineZoneRunningTitanCount += 1 else: virtualMachineZoneStoppedTitanCount += 1 if len(virtualmachines) == 0: ramavg = 0 cpuavg = 0 else: ram = (ram / 1024) ramavg = (ram / len(virtualmachines)) cpuavg = (cpu / len(virtualmachines)) stats[metricnameVMZoneRAMavgSize] = ramavg stats[metricnameVMZoneCPUavgSize] = cpuavg stats[metricnameVmZoneTotal] = len(virtualmachines) stats[metricnameVmZoneTotalRunning] = virtualMachineZoneRunningCount stats[metricnameVmZoneTotalRunningMicro] = virtualMachineZoneRunningMicroCount stats[metricnameVmZoneTotalRunningTiny] = virtualMachineZoneRunningTinyCount stats[metricnameVmZoneTotalRunningSmall] = virtualMachineZoneRunningSmallCount stats[metricnameVmZoneTotalRunningMedium] = virtualMachineZoneRunningMediumCount stats[metricnameVmZoneTotalRunningLarge] = virtualMachineZoneRunningLargeCount stats[metricnameVmZoneTotalRunningXLarge] = virtualMachineZoneRunningXLargeCount stats[metricnameVmZoneTotalRunningHuge] = virtualMachineZoneRunningHugeCount stats[metricnameVmZoneTotalRunningMega] = virtualMachineZoneRunningMegaCount stats[metricnameVmZoneTotalRunningTitan] = virtualMachineZoneRunningTitanCount stats[metricnameVmZoneTotalStopped] = virtualMachineZoneStoppedCount stats[metricnameVmZoneTotalStoppedMicro] = virtualMachineZoneStoppedMicroCount stats[metricnameVmZoneTotalStoppedTiny] = virtualMachineZoneStoppedTinyCount stats[metricnameVmZoneTotalStoppedSmall] = virtualMachineZoneStoppedSmallCount stats[metricnameVmZoneTotalStoppedMedium] = virtualMachineZoneStoppedMediumCount stats[metricnameVmZoneTotalStoppedLarge] = virtualMachineZoneStoppedLargeCount stats[metricnameVmZoneTotalStoppedXLarge] = virtualMachineZoneStoppedXLargeCount stats[metricnameVmZoneTotalStoppedHuge] = virtualMachineZoneStoppedHugeCount stats[metricnameVmZoneTotalStoppedMega] = virtualMachineZoneStoppedMegaCount stats[metricnameVmZoneTotalStoppedTitan] = virtualMachineZoneStoppedTitanCount stats[metricnameVmZoneTotalStopping] = virtualMachineZoneStoppingCount stats[metricnameVmZoneTotalStarting] = virtualMachineZoneStartingCount stats[metricnameVmZoneTotalMicro] = virtualMachineZoneMicro stats[metricnameVmZoneTotalTiny] = virtualMachineZoneTiny stats[metricnameVmZoneTotalSmall] = virtualMachineZoneSmall stats[metricnameVmZoneTotalMedium] = virtualMachineZoneMedium stats[metricnameVmZoneTotalLarge] = virtualMachineZoneLarge stats[metricnameVmZoneTotalXLarge] = virtualMachineZoneXLarge stats[metricnameVmZoneTotalHuge] = virtualMachineZoneHuge stats[metricnameVmZoneTotalMega] = virtualMachineZoneMega stats[metricnameVmZoneTotalTitan] = virtualMachineZoneTitan # collect number of root volumes try: logger('verb', "Performing listVolumes API call") rootvolumes = cs_list(cs, 'listVolumes', 'volume', type='ROOT', zoneid=zoneid) logger('verb', "Completed listVolumes API call") except Exception: logger('warn', "status err Unable to connect to CloudStack URL at %s for ListVolumes" % API_MONITORS) rootvolsize = 0 for rootvolume in rootvolumes: rootvolsize += rootvolume['size'] if rootvolume['vmstate'] == 'Running': # add to a dict to get the Running VMs per hypervisor host = rootvolume['storage'] hvmrunning[host] += 1 elif rootvolume['vmstate'] == 'Stopped' and not rootvolume['state'] == 'Allocated': # add to a dict to get the Stopped VMs per hypervisor host = rootvolume['storage'] hvmstopped[host] += 1 elif rootvolume['vmstate'] == 'Stopping': # add to a dict to get the Stopping VMs per hypervisor host = rootvolume['storage'] hvmstopping[host] += 1 elif rootvolume['vmstate'] == 'Starting': # add to a dict to get the Starting VMs per hypervisor host = rootvolume['storage'] hvmstarting[host] += 1 if len(rootvolumes) != 0: rootvolsize = (rootvolsize / 1073741824) rootavgsize = rootvolsize / len(rootvolumes) else: rootvolsize = 0 rootavgsize = 0 metricnameRootAvgSizeZone = METRIC_DELIM.join(['zonerootdiskavgsize', zone['name'].lower(), 'zonerootdiskavgsize']) stats[metricnameRootAvgSizeZone] = rootavgsize # add metric VMs per hypervisor for h in hypervisors: virtualMachineHTotalCount = 0 metricnameVmHTotal = METRIC_DELIM.join([h['name'].lower(), h['podname'].lower(), re.sub(r"\s+", '-', h['zonename'].lower()), 'hvmtotal']) metricnameVmHTotalRunning = METRIC_DELIM.join([h['name'].lower(), h['podname'].lower(), re.sub(r"\s+", '-', h['zonename'].lower()), 'hvmtotalrunning']) metricnameVmHTotalStarting = METRIC_DELIM.join([h['name'].lower(), h['podname'].lower(), re.sub(r"\s+", '-', h['zonename'].lower()), 'hvmtotalstarting']) metricnameVmHTotalStopping = METRIC_DELIM.join([h['name'].lower(), h['podname'].lower(), re.sub(r"\s+", '-', h['zonename'].lower()), 'hvmtotalstopping']) metricnameVmHTotalStopped = METRIC_DELIM.join([h['name'].lower(), h['podname'].lower(), re.sub(r"\s+", '-', h['zonename'].lower()), 'hvmtotalstopped']) hname = h['name'].lower() if hname in hvmrunning: virtualMachineHTotalCount = virtualMachineHTotalCount + hvmrunning[hname] stats[metricnameVmHTotalRunning] = hvmrunning[hname] else: stats[metricnameVmHTotalRunning] = 0 if hname in hvmstarting: virtualMachineHTotalCount = virtualMachineHTotalCount + hvmstarting[hname] stats[metricnameVmHTotalStarting] = hvmstarting[hname] else: stats[metricnameVmHTotalStarting] = 0 if hname in hvmstopping: virtualMachineHTotalCount = virtualMachineHTotalCount + hvmstopping[hname] stats[metricnameVmHTotalStopping] = hvmstopping[hname] else: stats[metricnameVmHTotalStopping] = 0 if hname in hvmstopped: virtualMachineHTotalCount = virtualMachineHTotalCount + hvmstopped[hname] stats[metricnameVmHTotalStopped] = hvmstopped[hname] else: stats[metricnameVmHTotalStopped] = 0 stats[metricnameVmHTotal] = virtualMachineHTotalCount for capacity in zone['capacity']: if capacity['type'] == 8: stats[metricnameIpTotal] = capacity['capacitytotal'] stats[metricnameIpAllocated] = capacity['capacityused'] stats[metricnameIpAllocatedPercent] = capacity['percentused'] stats[metricnameZonesCount] = len(zones) stats[metricnameHostZoneTotal] = len(hypervisors) # collect accounts try: logger('verb', "Performing accountStats API call") accounts_stats = cs.accountStats()['accountstats'] logger('verb', "Completed accountStats API call") except Exception: logger('err', "status err Unable to connect to CloudStack URL at %s for accountStats") stats[metric_name('accounts', 'accountscount')] = accounts_stats['total'] stats[metric_name('accounts', 'accountenabled')] = accounts_stats['enabled'] stats[metric_name('accounts', 'accountdisabled')] = accounts_stats['disabled'] # collect capacity try: capacity = cs.listCapacity(sharedonly=True)['capacity'] except Exception: logger('err', "status err Unable to connect to CloudStack URL at %s for ListCapacity") types = {0: 'memory', 1: 'cpu', 2: 'disk', 5: 'privateip', 6: 'ss', 9: 'diskalloc'} for c in capacity: def name(typ, metric): return metric_name('zonecapacity', c['zonename'].lower(), 'zonecapa{0}{1}'.format(types[typ], metric)) if c['type'] not in types: continue for metric, key in [ ('total', 'capacitytotal'), ('used', 'capacityused'), ('percentused', 'percentused'), ]: stats[name(c['type'], metric)] = c[key] return stats
class CloudStackInventory(object): def __init__(self): parser = argparse.ArgumentParser() parser.add_argument('--host') parser.add_argument('--list', action='store_true') options = parser.parse_args() try: self.cs = CloudStack(**read_config()) except CloudStackException as e: print("Error: Could not connect to CloudStack API", file=sys.stderr) if options.host: data = self.get_host(options.host) print(json.dumps(data, indent=2)) elif options.list: data = self.get_list() print(json.dumps(data, indent=2)) else: print("usage: --list | --host <hostname>", file=sys.stderr) sys.exit(1) def add_group(self, data, group_name, router_name): if group_name not in data: data[group_name] = { 'hosts': [] } data[group_name]['hosts'].append(router_name) return data def get_host(self, name): routers = [] routers_projects = self.cs.listRouters(projectid=-1, listall=True) if routers_projects and 'router' in routers_projects: routers = routers + routers_projects['router'] routers_accounts = self.cs.listRouters(listall=True) if routers_accounts and 'router' in routers_accounts: routers = routers + routers_accounts['router'] data = {} for router in routers: router_name = router['name'] if name == router_name: data['zone'] = router['zonename'] if 'linklocalip' in router: data['ansible_ssh_host'] = router['linklocalip'] data['state'] = router['state'] data['redundant_state'] = router['redundantstate'] if 'account' in router: data['account'] = router['account'] if 'project' in router: data['project'] = router['project'] data['service_offering'] = router['serviceofferingname'] data['role'] = router['role'] data['nic'] = [] for nic in router['nic']: data['nic'].append({ 'ip': nic['ipaddress'], 'mac': nic['macaddress'], 'netmask': nic['netmask'], }) if nic['isdefault']: data['default_ip'] = nic['ipaddress'] break; return data def get_list(self): data = { 'all': { 'hosts': [], }, '_meta': { 'hostvars': {}, }, } routers = [] routers_projects = self.cs.listRouters(projectid=-1, listall=True) if routers_projects and 'router' in routers_projects: routers = routers + routers_projects['router'] routers_accounts = self.cs.listRouters(listall=True) if routers_accounts and 'router' in routers_accounts: routers = routers + routers_accounts['router'] for router in routers: if router['state'] != 'Running': continue router_name = router['name'] data['all']['hosts'].append(router_name) # Make a group per domain data = self.add_group(data, router['domain'], router_name) data['_meta']['hostvars'][router_name] = {} data['_meta']['hostvars'][router_name]['group'] = router['domain'] data['_meta']['hostvars'][router_name]['domain'] = router['domain'] if 'networkdomain' in router: data['_meta']['hostvars'][router_name]['networkdomain'] = router['networkdomain'] data['_meta']['hostvars'][router_name]['zone'] = router['zonename'] # Make a group per zone data = self.add_group(data, router['zonename'], router_name) if 'project' in router: data['_meta']['hostvars'][router_name]['project'] = router['project'] # Make a group per project data = self.add_group(data, router['project'], router_name) if 'account' in router: data['_meta']['hostvars'][router_name]['account'] = router['account'] # Make a group per account data = self.add_group(data, router['account'], router_name) data['_meta']['hostvars'][router_name]['ansible_ssh_host'] = router['linklocalip'] data['_meta']['hostvars'][router_name]['state'] = router['state'] if 'redundantstate' in router: data['_meta']['hostvars'][router_name]['redundant_state'] = router['redundantstate'] if router['redundantstate'] in [ 'MASTER', 'BACKUP' ]: data = self.add_group(data, 'redundant_routers', router_name) if router['redundantstate'] in [ 'MASTER' ]: data = self.add_group(data, 'redundant_master_routers', router_name) if router['redundantstate'] in [ 'BACKUP' ]: data = self.add_group(data, 'redundant_backup_routers', router_name) if router['redundantstate'] in [ 'UNKNOWN' ]: data = self.add_group(data, 'non_redundant_routers', router_name) data['_meta']['hostvars'][router_name]['service_offering'] = router['serviceofferingname'] data['_meta']['hostvars'][router_name]['nic'] = [] for nic in router['nic']: data['_meta']['hostvars'][router_name]['nic'].append({ 'ip': nic['ipaddress'], 'mac': nic['macaddress'], 'netmask': nic['netmask'], }) if nic['isdefault']: data['_meta']['hostvars'][router_name]['default_ip'] = nic['ipaddress'] return data
class AnsibleCloudStack: def __init__(self, module): if not has_lib_cs: module.fail_json(msg="python library cs required: pip install cs") self.module = module self._connect() self.project = None self.ip_address = None self.zone = None self.vm = None self.os_type = None self.hypervisor = None self.capabilities = None def _connect(self): api_key = self.module.params.get('api_key') api_secret = self.module.params.get('secret_key') api_url = self.module.params.get('api_url') api_http_method = self.module.params.get('api_http_method') if api_key and api_secret and api_url: self.cs = CloudStack( endpoint=api_url, key=api_key, secret=api_secret, method=api_http_method ) else: self.cs = CloudStack(**read_config()) def _has_changed(self, want_dict, current_dict, only_keys=None): for key, value in want_dict.iteritems(): # Optionally limit by a list of keys if only_keys and key not in only_keys: continue; if key in current_dict: # API returns string for int in some cases, just to make sure if isinstance(value, int): current_dict[key] = int(current_dict[key]) elif isinstance(value, str): current_dict[key] = str(current_dict[key]) # Only need to detect a singe change, not every item if value != current_dict[key]: return True return False def _get_by_key(self, key=None, my_dict={}): if key: if key in my_dict: return my_dict[key] self.module.fail_json(msg="Something went wrong: %s not found" % key) return my_dict # TODO: for backward compatibility only, remove if not used anymore def get_project_id(self): return self.get_project(key='id') def get_project(self, key=None): if self.project: return self._get_by_key(key, self.project) project = self.module.params.get('project') if not project: return None projects = self.cs.listProjects(listall=True) if projects: for p in projects['project']: if project in [ p['name'], p['displaytext'], p['id'] ]: self.project = p return self._get_by_key(key, self.project) self.module.fail_json(msg="project '%s' not found" % project) # TODO: for backward compatibility only, remove if not used anymore def get_ip_address_id(self): return self.get_ip_address(key='id') def get_ip_address(self, key=None): if self.ip_address: return self._get_by_key(key, self.ip_address) ip_address = self.module.params.get('ip_address') if not ip_address: self.module.fail_json(msg="IP address param 'ip_address' is required") args = {} args['ipaddress'] = ip_address args['projectid'] = self.get_project(key='id') ip_addresses = self.cs.listPublicIpAddresses(**args) if not ip_addresses: self.module.fail_json(msg="IP address '%s' not found" % args['ipaddress']) self.ip_address = ip_addresses['publicipaddress'][0] return self._get_by_key(key, self.ip_address) # TODO: for backward compatibility only, remove if not used anymore def get_vm_id(self): return self.get_vm(key='id') def get_vm(self, key=None): if self.vm: return self._get_by_key(key, self.vm) vm = self.module.params.get('vm') if not vm: self.module.fail_json(msg="Virtual machine param 'vm' is required") args = {} args['projectid'] = self.get_project(key='id') args['zoneid'] = self.get_zone(key='id') vms = self.cs.listVirtualMachines(**args) if vms: for v in vms['virtualmachine']: if vm in [ v['name'], v['displayname'], v['id'] ]: self.vm = v return self._get_by_key(key, self.vm) self.module.fail_json(msg="Virtual machine '%s' not found" % vm) # TODO: for backward compatibility only, remove if not used anymore def get_zone_id(self): return self.get_zone(key='id') def get_zone(self, key=None): if self.zone: return self._get_by_key(key, self.zone) zone = self.module.params.get('zone') zones = self.cs.listZones() # use the first zone if no zone param given if not zone: self.zone = zones['zone'][0] return self._get_by_key(key, self.zone) if zones: for z in zones['zone']: if zone in [ z['name'], z['id'] ]: self.zone = z return self._get_by_key(key, self.zone) self.module.fail_json(msg="zone '%s' not found" % zone) # TODO: for backward compatibility only, remove if not used anymore def get_os_type_id(self): return self.get_os_type(key='id') def get_os_type(self, key=None): if self.os_type: return self._get_by_key(key, self.zone) os_type = self.module.params.get('os_type') if not os_type: return None os_types = self.cs.listOsTypes() if os_types: for o in os_types['ostype']: if os_type in [ o['description'], o['id'] ]: self.os_type = o return self._get_by_key(key, self.os_type) self.module.fail_json(msg="OS type '%s' not found" % os_type) def get_hypervisor(self): if self.hypervisor: return self.hypervisor hypervisor = self.module.params.get('hypervisor') hypervisors = self.cs.listHypervisors() # use the first hypervisor if no hypervisor param given if not hypervisor: self.hypervisor = hypervisors['hypervisor'][0]['name'] return self.hypervisor for h in hypervisors['hypervisor']: if hypervisor.lower() == h['name'].lower(): self.hypervisor = h['name'] return self.hypervisor self.module.fail_json(msg="Hypervisor '%s' not found" % hypervisor) def get_capabilities(self, key=None): if self.capabilities: return self._get_by_key(key, self.capabilities) capabilities = self.cs.listCapabilities() self.capabilities = capabilities['capability'] return self._get_by_key(key, self.capabilities) def _poll_job(self, job=None, key=None): if 'jobid' in job: while True: res = self.cs.queryAsyncJobResult(jobid=job['jobid']) if res['jobstatus'] != 0 and 'jobresult' in res: if 'errortext' in res['jobresult']: self.module.fail_json(msg="Failed: '%s'" % res['jobresult']['errortext']) if key and key in res['jobresult']: job = res['jobresult'][key] break time.sleep(2) return job
class AnsibleCloudStack(object): def __init__(self, module): if not has_lib_cs: module.fail_json(msg="python library cs required: pip install cs") self.result = { 'changed': False, 'diff' : { 'before': dict(), 'after': dict() } } # Common returns, will be merged with self.returns # search_for_key: replace_with_key self.common_returns = { 'id': 'id', 'name': 'name', 'created': 'created', 'zonename': 'zone', 'state': 'state', 'project': 'project', 'account': 'account', 'domain': 'domain', 'displaytext': 'display_text', 'displayname': 'display_name', 'description': 'description', } # Init returns dict for use in subclasses self.returns = {} # these values will be casted to int self.returns_to_int = {} # these keys will be compared case sensitive in self.has_changed() self.case_sensitive_keys = [ 'id', 'displaytext', 'displayname', 'description', ] self.module = module self._connect() # Helper for VPCs self._vpc_networks_ids = None self.domain = None self.account = None self.project = None self.ip_address = None self.network = None self.vpc = None self.zone = None self.vm = None self.vm_default_nic = None self.os_type = None self.hypervisor = None self.capabilities = None def _connect(self): api_key = self.module.params.get('api_key') api_secret = self.module.params.get('api_secret') api_url = self.module.params.get('api_url') api_http_method = self.module.params.get('api_http_method') api_timeout = self.module.params.get('api_timeout') if api_key and api_secret and api_url: self.cs = CloudStack( endpoint=api_url, key=api_key, secret=api_secret, timeout=api_timeout, method=api_http_method ) else: api_region = self.module.params.get('api_region', 'cloudstack') self.cs = CloudStack(**read_config(api_region)) def get_or_fallback(self, key=None, fallback_key=None): value = self.module.params.get(key) if not value: value = self.module.params.get(fallback_key) return value # TODO: for backward compatibility only, remove if not used anymore def _has_changed(self, want_dict, current_dict, only_keys=None): return self.has_changed(want_dict=want_dict, current_dict=current_dict, only_keys=only_keys) def has_changed(self, want_dict, current_dict, only_keys=None): result = False for key, value in want_dict.iteritems(): # Optionally limit by a list of keys if only_keys and key not in only_keys: continue # Skip None values if value is None: continue if key in current_dict: if isinstance(value, (int, float, long, complex)): # ensure we compare the same type if isinstance(value, int): current_dict[key] = int(current_dict[key]) elif isinstance(value, float): current_dict[key] = float(current_dict[key]) elif isinstance(value, long): current_dict[key] = long(current_dict[key]) elif isinstance(value, complex): current_dict[key] = complex(current_dict[key]) if value != current_dict[key]: self.result['diff']['before'][key] = current_dict[key] self.result['diff']['after'][key] = value result = True else: if self.case_sensitive_keys and key in self.case_sensitive_keys: if value != current_dict[key].encode('utf-8'): self.result['diff']['before'][key] = current_dict[key].encode('utf-8') self.result['diff']['after'][key] = value result = True # Test for diff in case insensitive way elif value.lower() != current_dict[key].encode('utf-8').lower(): self.result['diff']['before'][key] = current_dict[key].encode('utf-8') self.result['diff']['after'][key] = value result = True else: self.result['diff']['before'][key] = None self.result['diff']['after'][key] = value result = True return result def _get_by_key(self, key=None, my_dict=None): if my_dict is None: my_dict = {} if key: if key in my_dict: return my_dict[key] self.module.fail_json(msg="Something went wrong: %s not found" % key) return my_dict def get_vpc(self, key=None): """Return a VPC dictionary or the value of given key of.""" if self.vpc: return self._get_by_key(key, self.vpc) vpc = self.module.params.get('vpc') if not vpc: vpc = os.environ.get('CLOUDSTACK_VPC') if not vpc: return None args = { 'account': self.get_account(key='name'), 'domainid': self.get_domain(key='id'), 'projectid': self.get_project(key='id'), 'zoneid': self.get_zone(key='id'), } vpcs = self.cs.listVPCs(**args) if not vpcs: self.module.fail_json(msg="No VPCs available.") for v in vpcs['vpc']: if vpc in [v['displaytext'], v['name'], v['id']]: self.vpc = v return self._get_by_key(key, self.vpc) self.module.fail_json(msg="VPC '%s' not found" % vpc) def is_vm_in_vpc(self, vm): for n in vm.get('nic'): if n.get('isdefault', False): return self.is_vpc_network(network_id=n['networkid']) self.module.fail_json(msg="VM has no default nic") def is_vpc_network(self, network_id): """Returns True if network is in VPC.""" # This is an efficient way to query a lot of networks at a time if self._vpc_networks_ids is None: args = { 'account': self.get_account(key='name'), 'domainid': self.get_domain(key='id'), 'projectid': self.get_project(key='id'), 'zoneid': self.get_zone(key='id'), } vpcs = self.cs.listVPCs(**args) self._vpc_networks_ids = [] if vpcs: for vpc in vpcs['vpc']: for n in vpc.get('network',[]): self._vpc_networks_ids.append(n['id']) return network_id in self._vpc_networks_ids def get_network(self, key=None): """Return a network dictionary or the value of given key of.""" if self.network: return self._get_by_key(key, self.network) network = self.module.params.get('network') if not network: return None args = { 'account': self.get_account(key='name'), 'domainid': self.get_domain(key='id'), 'projectid': self.get_project(key='id'), 'zoneid': self.get_zone(key='id'), 'vpcid': self.get_vpc(key='id') } networks = self.cs.listNetworks(**args) if not networks: self.module.fail_json(msg="No networks available.") for n in networks['network']: # ignore any VPC network if vpc param is not given if 'vpcid' in n and not self.get_vpc(key='id'): continue if network in [n['displaytext'], n['name'], n['id']]: self.network = n return self._get_by_key(key, self.network) self.module.fail_json(msg="Network '%s' not found" % network) def get_project(self, key=None): if self.project: return self._get_by_key(key, self.project) project = self.module.params.get('project') if not project: project = os.environ.get('CLOUDSTACK_PROJECT') if not project: return None args = {} args['account'] = self.get_account(key='name') args['domainid'] = self.get_domain(key='id') projects = self.cs.listProjects(**args) if projects: for p in projects['project']: if project.lower() in [ p['name'].lower(), p['id'] ]: self.project = p return self._get_by_key(key, self.project) self.module.fail_json(msg="project '%s' not found" % project) def get_ip_address(self, key=None): if self.ip_address: return self._get_by_key(key, self.ip_address) ip_address = self.module.params.get('ip_address') if not ip_address: self.module.fail_json(msg="IP address param 'ip_address' is required") args = { 'ipaddress': ip_address, 'account': self.get_account(key='name'), 'domainid': self.get_domain(key='id'), 'projectid': self.get_project(key='id'), 'vpcid': self.get_vpc(key='id'), } ip_addresses = self.cs.listPublicIpAddresses(**args) if not ip_addresses: self.module.fail_json(msg="IP address '%s' not found" % args['ipaddress']) self.ip_address = ip_addresses['publicipaddress'][0] return self._get_by_key(key, self.ip_address) def get_vm_guest_ip(self): vm_guest_ip = self.module.params.get('vm_guest_ip') default_nic = self.get_vm_default_nic() if not vm_guest_ip: return default_nic['ipaddress'] for secondary_ip in default_nic['secondaryip']: if vm_guest_ip == secondary_ip['ipaddress']: return vm_guest_ip self.module.fail_json(msg="Secondary IP '%s' not assigned to VM" % vm_guest_ip) def get_vm_default_nic(self): if self.vm_default_nic: return self.vm_default_nic nics = self.cs.listNics(virtualmachineid=self.get_vm(key='id')) if nics: for n in nics['nic']: if n['isdefault']: self.vm_default_nic = n return self.vm_default_nic self.module.fail_json(msg="No default IP address of VM '%s' found" % self.module.params.get('vm')) def get_vm(self, key=None): if self.vm: return self._get_by_key(key, self.vm) vm = self.module.params.get('vm') if not vm: self.module.fail_json(msg="Virtual machine param 'vm' is required") vpc_id = self.get_vpc(key='id') args = { 'account': self.get_account(key='name'), 'domainid': self.get_domain(key='id'), 'projectid': self.get_project(key='id'), 'zoneid': self.get_zone(key='id'), 'vpcid': vpc_id, } vms = self.cs.listVirtualMachines(**args) if vms: for v in vms['virtualmachine']: # Due the limitation of the API, there is no easy way (yet) to get only those VMs # not belonging to a VPC. if not vpc_id and self.is_vm_in_vpc(vm=v): continue if vm.lower() in [ v['name'].lower(), v['displayname'].lower(), v['id'] ]: self.vm = v return self._get_by_key(key, self.vm) self.module.fail_json(msg="Virtual machine '%s' not found" % vm) def get_zone(self, key=None): if self.zone: return self._get_by_key(key, self.zone) zone = self.module.params.get('zone') if not zone: zone = os.environ.get('CLOUDSTACK_ZONE') zones = self.cs.listZones() # use the first zone if no zone param given if not zone: self.zone = zones['zone'][0] return self._get_by_key(key, self.zone) if zones: for z in zones['zone']: if zone.lower() in [ z['name'].lower(), z['id'] ]: self.zone = z return self._get_by_key(key, self.zone) self.module.fail_json(msg="zone '%s' not found" % zone) def get_os_type(self, key=None): if self.os_type: return self._get_by_key(key, self.zone) os_type = self.module.params.get('os_type') if not os_type: return None os_types = self.cs.listOsTypes() if os_types: for o in os_types['ostype']: if os_type in [ o['description'], o['id'] ]: self.os_type = o return self._get_by_key(key, self.os_type) self.module.fail_json(msg="OS type '%s' not found" % os_type) def get_hypervisor(self): if self.hypervisor: return self.hypervisor hypervisor = self.module.params.get('hypervisor') hypervisors = self.cs.listHypervisors() # use the first hypervisor if no hypervisor param given if not hypervisor: self.hypervisor = hypervisors['hypervisor'][0]['name'] return self.hypervisor for h in hypervisors['hypervisor']: if hypervisor.lower() == h['name'].lower(): self.hypervisor = h['name'] return self.hypervisor self.module.fail_json(msg="Hypervisor '%s' not found" % hypervisor) def get_account(self, key=None): if self.account: return self._get_by_key(key, self.account) account = self.module.params.get('account') if not account: account = os.environ.get('CLOUDSTACK_ACCOUNT') if not account: return None domain = self.module.params.get('domain') if not domain: self.module.fail_json(msg="Account must be specified with Domain") args = {} args['name'] = account args['domainid'] = self.get_domain(key='id') args['listall'] = True accounts = self.cs.listAccounts(**args) if accounts: self.account = accounts['account'][0] return self._get_by_key(key, self.account) self.module.fail_json(msg="Account '%s' not found" % account) def get_domain(self, key=None): if self.domain: return self._get_by_key(key, self.domain) domain = self.module.params.get('domain') if not domain: domain = os.environ.get('CLOUDSTACK_DOMAIN') if not domain: return None args = {} args['listall'] = True domains = self.cs.listDomains(**args) if domains: for d in domains['domain']: if d['path'].lower() in [ domain.lower(), "root/" + domain.lower(), "root" + domain.lower() ]: self.domain = d return self._get_by_key(key, self.domain) self.module.fail_json(msg="Domain '%s' not found" % domain) def get_tags(self, resource=None): existing_tags = [] for tag in resource.get('tags',[]): existing_tags.append({'key': tag['key'], 'value': tag['value']}) return existing_tags def _process_tags(self, resource, resource_type, tags, operation="create"): if tags: self.result['changed'] = True if not self.module.check_mode: args = {} args['resourceids'] = resource['id'] args['resourcetype'] = resource_type args['tags'] = tags if operation == "create": response = self.cs.createTags(**args) else: response = self.cs.deleteTags(**args) self.poll_job(response) def _tags_that_should_exist_or_be_updated(self, resource, tags): existing_tags = self.get_tags(resource) return [tag for tag in tags if tag not in existing_tags] def _tags_that_should_not_exist(self, resource, tags): existing_tags = self.get_tags(resource) return [tag for tag in existing_tags if tag not in tags] def ensure_tags(self, resource, resource_type=None): if not resource_type or not resource: self.module.fail_json(msg="Error: Missing resource or resource_type for tags.") if 'tags' in resource: tags = self.module.params.get('tags') if tags is not None: self._process_tags(resource, resource_type, self._tags_that_should_not_exist(resource, tags), operation="delete") self._process_tags(resource, resource_type, self._tags_that_should_exist_or_be_updated(resource, tags)) resource['tags'] = tags return resource def get_capabilities(self, key=None): if self.capabilities: return self._get_by_key(key, self.capabilities) capabilities = self.cs.listCapabilities() self.capabilities = capabilities['capability'] return self._get_by_key(key, self.capabilities) # TODO: for backward compatibility only, remove if not used anymore def _poll_job(self, job=None, key=None): return self.poll_job(job=job, key=key) def poll_job(self, job=None, key=None): if 'jobid' in job: while True: res = self.cs.queryAsyncJobResult(jobid=job['jobid']) if res['jobstatus'] != 0 and 'jobresult' in res: if 'errortext' in res['jobresult']: self.module.fail_json(msg="Failed: '%s'" % res['jobresult']['errortext']) if key and key in res['jobresult']: job = res['jobresult'][key] break time.sleep(2) return job def get_result(self, resource): if resource: returns = self.common_returns.copy() returns.update(self.returns) for search_key, return_key in returns.iteritems(): if search_key in resource: self.result[return_key] = resource[search_key] # Bad bad API does not always return int when it should. for search_key, return_key in self.returns_to_int.iteritems(): if search_key in resource: self.result[return_key] = int(resource[search_key]) # Special handling for tags if 'tags' in resource: self.result['tags'] = [] for tag in resource['tags']: result_tag = {} result_tag['key'] = tag['key'] result_tag['value'] = tag['value'] self.result['tags'].append(result_tag) return self.result
try: from cs import CloudStack, CloudStackException, read_config except ImportError: print 'python library required: cs' print 'pip install <library>' sys.exit(1) parser = argparse.ArgumentParser() parser.add_argument('--project') parser.add_argument('--zone') args = parser.parse_args() try: cs = CloudStack(**read_config()) project_id = '' if args.project: projects = cs.listProjects(listall=True) if projects: for p in projects['project']: if p['name'] == args.project: project_id = p['id'] break if not project_id: print "project %s not found" % args.project sys.exit(1) zone_id = ''