summaryrefslogtreecommitdiffstats
path: root/opensteak/tools/opensteak
diff options
context:
space:
mode:
Diffstat (limited to 'opensteak/tools/opensteak')
-rw-r--r--opensteak/tools/opensteak/__init__.py18
-rw-r--r--opensteak/tools/opensteak/argparser.py46
-rw-r--r--opensteak/tools/opensteak/conf.py72
-rw-r--r--opensteak/tools/opensteak/foreman.py60
-rw-r--r--opensteak/tools/opensteak/foreman_objects/__init__.py18
-rw-r--r--opensteak/tools/opensteak/foreman_objects/api.py197
-rw-r--r--opensteak/tools/opensteak/foreman_objects/architectures.py49
-rw-r--r--opensteak/tools/opensteak/foreman_objects/compute_resources.py62
-rw-r--r--opensteak/tools/opensteak/foreman_objects/domains.py44
-rw-r--r--opensteak/tools/opensteak/foreman_objects/freeip.py79
-rw-r--r--opensteak/tools/opensteak/foreman_objects/hostgroups.py103
-rw-r--r--opensteak/tools/opensteak/foreman_objects/hosts.py142
-rw-r--r--opensteak/tools/opensteak/foreman_objects/item.py135
-rw-r--r--opensteak/tools/opensteak/foreman_objects/itemHost.py141
-rw-r--r--opensteak/tools/opensteak/foreman_objects/itemHostsGroup.py50
-rw-r--r--opensteak/tools/opensteak/foreman_objects/itemOverrideValues.py61
-rw-r--r--opensteak/tools/opensteak/foreman_objects/itemSmartClassParameter.py62
-rw-r--r--opensteak/tools/opensteak/foreman_objects/objects.py136
-rw-r--r--opensteak/tools/opensteak/foreman_objects/operatingsystems.py66
-rw-r--r--opensteak/tools/opensteak/foreman_objects/puppetClasses.py46
-rw-r--r--opensteak/tools/opensteak/foreman_objects/smart_proxies.py36
-rw-r--r--opensteak/tools/opensteak/foreman_objects/subnets.py67
-rw-r--r--opensteak/tools/opensteak/printer.py141
-rw-r--r--opensteak/tools/opensteak/templateparser.py34
-rw-r--r--opensteak/tools/opensteak/virsh.py174
25 files changed, 2039 insertions, 0 deletions
diff --git a/opensteak/tools/opensteak/__init__.py b/opensteak/tools/opensteak/__init__.py
new file mode 100644
index 000000000..01f9c9a12
--- /dev/null
+++ b/opensteak/tools/opensteak/__init__.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+# This directory is a Python package.
diff --git a/opensteak/tools/opensteak/argparser.py b/opensteak/tools/opensteak/argparser.py
new file mode 100644
index 000000000..de980b6b6
--- /dev/null
+++ b/opensteak/tools/opensteak/argparser.py
@@ -0,0 +1,46 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+# @author: Pawel Chomicki <pawel.chomicki@nokia.com>
+
+"""
+Parse arguments from CLI
+"""
+
+import argparse
+
+class OpenSteakArgParser:
+
+ def __init__(self):
+ """
+ Parse the command line
+ """
+ self.parser = argparse.ArgumentParser(description='This script will create config files for a VM in current folder.', usage='%(prog)s [options] name')
+ self.parser.add_argument('name', help='Set the name of the machine')
+ self.parser.add_argument('-i', '--ip', help='Set the ip address of the machine. (Default is 192.168.42.42)', default='192.168.42.42')
+ self.parser.add_argument('-n', '--netmask', help='Set the netmask in short format. (Default is 24)', default='24')
+ self.parser.add_argument('-g', '--gateway', help='Set the gateway to ping internet. (Default is 192.168.42.1)', default='192.168.42.1')
+ self.parser.add_argument('-p', '--password', help='Set the ssh password. Login is ubuntu. (Default password is moutarde)', default='moutarde')
+ self.parser.add_argument('-u', '--cpu', help='Set number of CPU for the VM. (Default is 2)', default='2')
+ self.parser.add_argument('-r', '--ram', help='Set quantity of RAM for the VM in kB. (Default is 2097152)', default='2097152')
+ self.parser.add_argument('-o', '--iso', help='Use this iso file. (Default is trusty-server-cloudimg-amd64-disk1.img)', default='trusty-server-cloudimg-amd64-disk1.img')
+ self.parser.add_argument('-d', '--disksize', help='Create a disk with that size. (Default is 5G)', default='5G')
+ self.parser.add_argument('-f', '--force', help='Force creation without asking questions. This is dangerous as it will delete old VM with same name.', default=False, action='store_true')
+
+ def parse(self):
+ return self.parser.parse_args()
+
diff --git a/opensteak/tools/opensteak/conf.py b/opensteak/tools/opensteak/conf.py
new file mode 100644
index 000000000..65eaf433b
--- /dev/null
+++ b/opensteak/tools/opensteak/conf.py
@@ -0,0 +1,72 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+from yaml import load, dump
+try:
+ from yaml import CLoader as Loader, CDumper as Dumper
+except ImportError:
+ from yaml import Loader, Dumper
+
+
+class OpenSteakConfig:
+ """OpenSteak config class
+ Use this object as a dict
+ """
+
+ def __init__(self,
+ config_file="/usr/local/opensteak/infra/config/common.yaml",
+ autosave=False):
+ """ Function __init__
+ Load saved opensteak config.
+
+ @param PARAM: DESCRIPTION
+ @return RETURN: DESCRIPTION
+ @param config_file: the yaml config file to read.
+ default is '/usr/local/opensteak/infra/config/common.yaml'
+ @param autosave: save automaticly the config at destroy
+ default is False
+ """
+ self.config_file = config_file
+ self.autosave = autosave
+ with open(self.config_file, 'r') as stream:
+ self._data = load(stream, Loader=Loader)
+
+ def __getitem__(self, index):
+ """Get an item of the configuration"""
+ return self._data[index]
+
+ def __setitem__(self, index, value):
+ """Set an item of the configuration"""
+ self._data[index] = value
+
+ def list(self):
+ """Set an item of the configuration"""
+ return self._data.keys()
+
+ def dump(self):
+ """Dump the configuration"""
+ return dump(self._data, Dumper=Dumper)
+
+ def save(self):
+ """Save the configuration to the file"""
+ with open(self.config_file, 'w') as f:
+ f.write(dump(self._data, Dumper=Dumper))
+
+ def __del__(self):
+ if self.autosave:
+ self.save()
diff --git a/opensteak/tools/opensteak/foreman.py b/opensteak/tools/opensteak/foreman.py
new file mode 100644
index 000000000..b7cbf42de
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman.py
@@ -0,0 +1,60 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+from opensteak.foreman_objects.api import Api
+from opensteak.foreman_objects.objects import ForemanObjects
+from opensteak.foreman_objects.domains import Domains
+from opensteak.foreman_objects.smart_proxies import SmartProxies
+from opensteak.foreman_objects.operatingsystems import OperatingSystems
+from opensteak.foreman_objects.hostgroups import HostGroups
+from opensteak.foreman_objects.hosts import Hosts
+from opensteak.foreman_objects.architectures import Architectures
+from opensteak.foreman_objects.subnets import Subnets
+from opensteak.foreman_objects.puppetClasses import PuppetClasses
+from opensteak.foreman_objects.compute_resources import ComputeResources
+
+
+class OpenSteakForeman:
+ """
+ HostGroup class
+ """
+ def __init__(self, password, login='admin', ip='127.0.0.1'):
+ """ Function __init__
+ Init the API with the connection params
+ @param password: authentication password
+ @param password: authentication login - default is admin
+ @param ip: api ip - default is localhost
+ @return RETURN: self
+ """
+ self.api = Api(login=login, password=password, ip=ip,
+ printErrors=False)
+ self.domains = Domains(self.api)
+ self.smartProxies = SmartProxies(self.api)
+ self.puppetClasses = PuppetClasses(self.api)
+ self.operatingSystems = OperatingSystems(self.api)
+ self.architectures = Architectures(self.api)
+ self.subnets = Subnets(self.api)
+ self.hostgroups = HostGroups(self.api)
+ self.hosts = Hosts(self.api)
+ self.computeResources = ComputeResources(self.api)
+ self.environments = ForemanObjects(self.api,
+ 'environments',
+ 'environment')
+ self.smartClassParameters = ForemanObjects(self.api,
+ 'smart_class_parameters',
+ 'smart_class_parameter')
diff --git a/opensteak/tools/opensteak/foreman_objects/__init__.py b/opensteak/tools/opensteak/foreman_objects/__init__.py
new file mode 100644
index 000000000..01f9c9a12
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/__init__.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+# This directory is a Python package.
diff --git a/opensteak/tools/opensteak/foreman_objects/api.py b/opensteak/tools/opensteak/foreman_objects/api.py
new file mode 100644
index 000000000..dc9973484
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/api.py
@@ -0,0 +1,197 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+import json
+import requests
+from requests_futures.sessions import FuturesSession
+from pprint import pformat
+
+
+class Api:
+ """
+ Api class
+ Class to deal with the foreman API v2
+ """
+ def __init__(self, password, login='admin', ip='127.0.0.1', printErrors=False):
+ """ Function __init__
+ Init the API with the connection params
+
+ @param password: authentication password
+ @param password: authentication login - default is admin
+ @param ip: api ip - default is localhost
+ @return RETURN: self
+ """
+ self.base_url = 'http://{}/api/v2/'.format(ip)
+ self.headers = {'Accept': 'version=2',
+ 'Content-Type': 'application/json; charset=UTF-8'}
+ self.auth = (login, password)
+ self.errorMsg = ''
+ self.printErrors = printErrors
+
+ def list(self, obj, filter=False, only_id=False, limit=20):
+ """ Function list
+ Get the list of an object
+
+ @param obj: object name ('hosts', 'puppetclasses'...)
+ @param filter: filter for objects
+ @param only_id: boolean to only return dict with name/id
+ @return RETURN: the list of the object
+ """
+ self.url = '{}{}/?per_page={}'.format(self.base_url, obj, limit)
+ if filter:
+ self.url += '&search={}'.format(filter)
+ self.resp = requests.get(url=self.url, auth=self.auth,
+ headers=self.headers)
+ if only_id:
+ if self.__process_resp__(obj) is False:
+ return False
+ if type(self.res['results']) is list:
+ return dict((x['name'], x['id']) for x in self.res['results'])
+ elif type(self.res['results']) is dict:
+ r = {}
+ for v in self.res['results'].values():
+ for vv in v:
+ r[vv['name']] = vv['id']
+ return r
+ else:
+ return False
+ else:
+ return self.__process_resp__(obj)
+
+ def get(self, obj, id, sub_object=None):
+ """ Function get
+ Get an object by id
+
+ @param obj: object name ('hosts', 'puppetclasses'...)
+ @param id: the id of the object (name or id)
+ @return RETURN: the targeted object
+ """
+ self.url = '{}{}/{}'.format(self.base_url, obj, id)
+ if sub_object:
+ self.url += '/' + sub_object
+ self.resp = requests.get(url=self.url, auth=self.auth,
+ headers=self.headers)
+ if self.__process_resp__(obj):
+ return self.res
+ return False
+
+ def get_id_by_name(self, obj, name):
+ """ Function get_id_by_name
+ Get the id of an object
+
+ @param obj: object name ('hosts', 'puppetclasses'...)
+ @param id: the id of the object (name or id)
+ @return RETURN: the targeted object
+ """
+ list = self.list(obj, filter='name = "{}"'.format(name),
+ only_id=True, limit=1)
+ return list[name] if name in list.keys() else False
+
+ def set(self, obj, id, payload, action='', async=False):
+ """ Function set
+ Set an object by id
+
+ @param obj: object name ('hosts', 'puppetclasses'...)
+ @param id: the id of the object (name or id)
+ @param action: specific action of an object ('power'...)
+ @param payload: the dict of the payload
+ @param async: should this request be async, if true use
+ return.result() to get the response
+ @return RETURN: the server response
+ """
+ self.url = '{}{}/{}'.format(self.base_url, obj, id)
+ if action:
+ self.url += '/{}'.format(action)
+ self.payload = json.dumps(payload)
+ if async:
+ session = FuturesSession()
+ return session.put(url=self.url, auth=self.auth,
+ headers=self.headers, data=self.payload)
+ else:
+ self.resp = requests.put(url=self.url, auth=self.auth,
+ headers=self.headers, data=self.payload)
+ if self.__process_resp__(obj):
+ return self.res
+ return False
+
+ def create(self, obj, payload, async=False):
+ """ Function create
+ Create an new object
+
+ @param obj: object name ('hosts', 'puppetclasses'...)
+ @param payload: the dict of the payload
+ @param async: should this request be async, if true use
+ return.result() to get the response
+ @return RETURN: the server response
+ """
+ self.url = self.base_url + obj
+ self.payload = json.dumps(payload)
+ if async:
+ session = FuturesSession()
+ return session.post(url=self.url, auth=self.auth,
+ headers=self.headers, data=self.payload)
+ else:
+ self.resp = requests.post(url=self.url, auth=self.auth,
+ headers=self.headers,
+ data=self.payload)
+ return self.__process_resp__(obj)
+
+ def delete(self, obj, id):
+ """ Function delete
+ Delete an object by id
+
+ @param obj: object name ('hosts', 'puppetclasses'...)
+ @param id: the id of the object (name or id)
+ @return RETURN: the server response
+ """
+ self.url = '{}{}/{}'.format(self.base_url, obj, id)
+ self.resp = requests.delete(url=self.url,
+ auth=self.auth,
+ headers=self.headers, )
+ return self.__process_resp__(obj)
+
+ def __process_resp__(self, obj):
+ """ Function __process_resp__
+ Process the response sent by the server and store the result
+
+ @param obj: object name ('hosts', 'puppetclasses'...)
+ @return RETURN: the server response
+ """
+ self.last_obj = obj
+ if self.resp.status_code > 299:
+ self.errorMsg = ">> Error {} for object '{}'".format(self.resp.status_code,
+ self.last_obj)
+ try:
+ self.ret = json.loads(self.resp.text)
+ self.errorMsg += pformat(self.ret[list(self.ret.keys())[0]])
+ except:
+ self.ret = self.resp.text
+ self.errorMsg += self.ret
+ if self.printErrors:
+ print(self.errorMsg)
+ return False
+ self.res = json.loads(self.resp.text)
+ if 'results' in self.res.keys():
+ return self.res['results']
+ return self.res
+
+ def __str__(self):
+ ret = pformat(self.base_url) + "\n"
+ ret += pformat(self.headers) + "\n"
+ ret += pformat(self.auth) + "\n"
+ return ret
diff --git a/opensteak/tools/opensteak/foreman_objects/architectures.py b/opensteak/tools/opensteak/foreman_objects/architectures.py
new file mode 100644
index 000000000..5e4303e17
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/architectures.py
@@ -0,0 +1,49 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+from opensteak.foreman_objects.objects import ForemanObjects
+
+
+class Architectures(ForemanObjects):
+ """
+ Architectures class
+ """
+ objName = 'architectures'
+ payloadObj = 'architecture'
+
+ def checkAndCreate(self, key, payload, osIds):
+ """ Function checkAndCreate
+ Check if an architectures exists and create it if not
+
+ @param key: The targeted architectures
+ @param payload: The targeted architectures description
+ @param osIds: The list of os ids liked with this architecture
+ @return RETURN: The id of the object
+ """
+ if key not in self:
+ self[key] = payload
+ oid = self[key]['id']
+ if not oid:
+ return False
+ #~ To be sure the OS list is good, we ensure our os are in the list
+ for os in self[key]['operatingsystems']:
+ osIds.add(os['id'])
+ self[key]["operatingsystem_ids"] = list(osIds)
+ if (len(self[key]['operatingsystems']) is not len(osIds)):
+ return False
+ return oid
diff --git a/opensteak/tools/opensteak/foreman_objects/compute_resources.py b/opensteak/tools/opensteak/foreman_objects/compute_resources.py
new file mode 100644
index 000000000..9ada9c481
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/compute_resources.py
@@ -0,0 +1,62 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+from opensteak.foreman_objects.objects import ForemanObjects
+from opensteak.foreman_objects.item import ForemanItem
+
+
+class ComputeResources(ForemanObjects):
+ """
+ HostGroups class
+ """
+ objName = 'compute_resources'
+ payloadObj = 'compute_resource'
+
+ def list(self):
+ """ Function list
+ list the hostgroups
+
+ @return RETURN: List of ForemanItemHostsGroup objects
+ """
+ return list(map(lambda x: ForemanItem(self.api, x['id'], x),
+ self.api.list(self.objName)))
+
+ def __getitem__(self, key):
+ """ Function __getitem__
+ Get an hostgroup
+
+ @param key: The hostgroup name or ID
+ @return RETURN: The ForemanItemHostsGroup object of an host
+ """
+ # Because Hostgroup did not support get by name we need to do it by id
+ if type(key) is not int:
+ key = self.getId(key)
+ ret = self.api.get(self.objName, key)
+ return ForemanItem(self.api, key, ret)
+
+ def __delitem__(self, key):
+ """ Function __delitem__
+ Delete an hostgroup
+
+ @param key: The hostgroup name or ID
+ @return RETURN: The API result
+ """
+ # Because Hostgroup did not support get by name we need to do it by id
+ if type(key) is not int:
+ key = self.getId(key)
+ return self.api.delete(self.objName, key)
diff --git a/opensteak/tools/opensteak/foreman_objects/domains.py b/opensteak/tools/opensteak/foreman_objects/domains.py
new file mode 100644
index 000000000..753833fc5
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/domains.py
@@ -0,0 +1,44 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+from opensteak.foreman_objects.objects import ForemanObjects
+
+
+class Domains(ForemanObjects):
+ """
+ Domain class
+ """
+ objName = 'domains'
+ payloadObj = 'domain'
+
+ def load(self, id='0', name=''):
+ """ Function load
+ To be rewriten
+
+ @param id: The Domain ID
+ @return RETURN: DESCRIPTION
+ """
+
+ if name:
+ id = self.__getIdByName__(name)
+ self.data = self.foreman.get('domains', id)
+ if 'parameters' in self.data:
+ self.params = self.data['parameters']
+ else:
+ self.params = []
+ self.name = self.data['name']
diff --git a/opensteak/tools/opensteak/foreman_objects/freeip.py b/opensteak/tools/opensteak/foreman_objects/freeip.py
new file mode 100644
index 000000000..86c003fec
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/freeip.py
@@ -0,0 +1,79 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+#~ from foreman.api import Api
+import requests
+from bs4 import BeautifulSoup
+import sys
+import json
+
+class FreeIP:
+ """ FreeIP return an available IP in the targeted network """
+
+ def __init__ (self, login, password):
+ """ Init: get authenticity token """
+ with requests.session() as self.session:
+ try:
+ #~ 1/ Get login token and authentify
+ payload = {}
+ log_soup = BeautifulSoup(self.session.get('https://127.0.0.1/users/login', verify=False).text)
+ payload['utf8'] = log_soup.findAll('input',attrs={'name':'utf8'})[0].get('value')
+ payload['authenticity_token'] = log_soup.findAll('input',attrs={'name':'authenticity_token'})[0].get('value')
+ if payload['authenticity_token'] == None:
+ raise requests.exceptions.RequestException("Bad catch of authenticity_token")
+ payload['commit']='Login'
+ payload['login[login]'] = login
+ payload['login[password]'] = password
+ #~ 2/ Log in
+ r = self.session.post('https://127.0.0.1/users/login', verify=False, data=payload)
+ if r.status_code != 200:
+ raise requests.exceptions.RequestException("Bad login or password")
+ #~ Get token for host creation
+ log_soup = BeautifulSoup(self.session.get('https://127.0.0.1/hosts/new', verify=False).text)
+ self.authenticity_token = log_soup.findAll('input',attrs={'name':'authenticity_token'})[0].get('value')
+ if payload['authenticity_token'] == None:
+ raise requests.exceptions.RequestException("Bad catch of authenticity_token")
+ except requests.exceptions.RequestException as e:
+ print("Error connection Foreman to get a free ip")
+ print(e)
+ sys.exit(1)
+ pass
+
+ def get(self, subnet, mac = ""):
+ payload = {"host_mac": mac, "subnet_id": subnet}
+ payload['authenticity_token'] = self.authenticity_token
+ try:
+ self.last_ip = json.loads(self.session.post('https://127.0.0.1/subnets/freeip', verify=False, data=payload).text)['ip']
+ if payload['authenticity_token'] == None:
+ raise requests.exceptions.RequestException("Error getting free IP")
+ except requests.exceptions.RequestException as e:
+ print("Error connection Foreman to get a free ip")
+ print(e)
+ sys.exit(1)
+ return self.last_ip
+
+
+
+if __name__ == "__main__":
+ import pprint
+ import sys
+ if len(sys.argv) == 4:
+ f = FreeIP(sys.argv[1], sys.argv[2])
+ print(f.get(sys.argv[3]))
+ else:
+ print('Error: Usage\npython {} foreman_user foreman_password subnet'.format(sys.argv[0]))
diff --git a/opensteak/tools/opensteak/foreman_objects/hostgroups.py b/opensteak/tools/opensteak/foreman_objects/hostgroups.py
new file mode 100644
index 000000000..55b8ba6b3
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/hostgroups.py
@@ -0,0 +1,103 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+from opensteak.foreman_objects.objects import ForemanObjects
+from opensteak.foreman_objects.itemHostsGroup import ItemHostsGroup
+from pprint import pprint as pp
+
+
+class HostGroups(ForemanObjects):
+ """
+ HostGroups class
+ """
+ objName = 'hostgroups'
+ payloadObj = 'hostgroup'
+
+ def list(self):
+ """ Function list
+ list the hostgroups
+
+ @return RETURN: List of ItemHostsGroup objects
+ """
+ return list(map(lambda x: ItemHostsGroup(self.api, x['id'], x),
+ self.api.list(self.objName)))
+
+ def __getitem__(self, key):
+ """ Function __getitem__
+ Get an hostgroup
+
+ @param key: The hostgroup name or ID
+ @return RETURN: The ItemHostsGroup object of an host
+ """
+ # Because Hostgroup did not support get by name we need to do it by id
+ if type(key) is not int:
+ key = self.getId(key)
+ ret = self.api.get(self.objName, key)
+ return ItemHostsGroup(self.api, key, ret)
+
+ def __delitem__(self, key):
+ """ Function __delitem__
+ Delete an hostgroup
+
+ @param key: The hostgroup name or ID
+ @return RETURN: The API result
+ """
+ # Because Hostgroup did not support get by name we need to do it by id
+ if type(key) is not int:
+ key = self.getId(key)
+ return self.api.delete(self.objName, key)
+
+ def checkAndCreate(self, key, payload,
+ hostgroupConf,
+ hostgroupParent,
+ puppetClassesId):
+ """ Function checkAndCreate
+ check And Create procedure for an hostgroup
+ - check the hostgroup is not existing
+ - create the hostgroup
+ - Add puppet classes from puppetClassesId
+ - Add params from hostgroupConf
+
+ @param key: The hostgroup name or ID
+ @param payload: The description of the hostgroup
+ @param hostgroupConf: The configuration of the host group from the
+ foreman.conf
+ @param hostgroupParent: The id of the parent hostgroup
+ @param puppetClassesId: The dict of puppet classes ids in foreman
+ @return RETURN: The ItemHostsGroup object of an host
+ """
+ if key not in self:
+ self[key] = payload
+ oid = self[key]['id']
+ if not oid:
+ return False
+
+ # Create Hostgroup classes
+ hostgroupClassIds = self[key]['puppetclass_ids']
+ if 'classes' in hostgroupConf.keys():
+ if not self[key].checkAndCreateClasses(puppetClassesId.values()):
+ print("Failed in classes")
+ return False
+
+ # Set params
+ if 'params' in hostgroupConf.keys():
+ if not self[key].checkAndCreateParams(hostgroupConf['params']):
+ print("Failed in params")
+ return False
+
+ return oid
diff --git a/opensteak/tools/opensteak/foreman_objects/hosts.py b/opensteak/tools/opensteak/foreman_objects/hosts.py
new file mode 100644
index 000000000..95d47af9d
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/hosts.py
@@ -0,0 +1,142 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+from opensteak.foreman_objects.objects import ForemanObjects
+from opensteak.foreman_objects.itemHost import ItemHost
+import time
+
+
+class Hosts(ForemanObjects):
+ """
+ Host sclass
+ """
+ objName = 'hosts'
+ payloadObj = 'host'
+
+ def list(self):
+ """ Function list
+ list the hosts
+
+ @return RETURN: List of ItemHost objects
+ """
+ return list(map(lambda x: ItemHost(self.api, x['id'], x),
+ self.api.list(self.objName)))
+
+ def __getitem__(self, key):
+ """ Function __getitem__
+ Get an host
+
+ @param key: The host name or ID
+ @return RETURN: The ItemHost object of an host
+ """
+ return ItemHost(self.api, key, self.api.get(self.objName, key))
+
+ def __printProgression__(self, status, msg, eol):
+ """ Function __printProgression__
+ Print the creation progression or not
+ It uses the foreman.printer lib
+
+ @param status: Status of the message
+ @param msg: Message
+ @param eol: End Of Line (to get a new line or not)
+ @return RETURN: None
+ """
+ if self.printHostProgress:
+ self.__printProgression__(status, msg, eol=eol)
+
+ def createVM(self, key, attributes, printHostProgress=False):
+ """ Function createVM
+ Create a Virtual Machine
+
+ The creation of a VM with libVirt is a bit complexe.
+ We first create the element in foreman, the ask to start before
+ the result of the creation.
+ To do so, we make async calls to the API and check the results
+
+ @param key: The host name or ID
+ @param attributes:The payload of the host creation
+ @param printHostProgress: The link to opensteak.printerlib
+ to print or not the
+ progression of the host creation
+ @return RETURN: The API result
+ """
+
+ self.printHostProgress = printHostProgress
+ self.async = True
+ # Create the VM in foreman
+ self.__printProgression__('In progress',
+ key + ' creation: push in Foreman', eol='\r')
+ future1 = self.api.create('hosts', attributes, async=True)
+
+ # Wait before asking to power on the VM
+ sleep = 5
+ for i in range(0, sleep):
+ time.sleep(1)
+ self.__printProgression__('In progress',
+ key + ' creation: start in {0}s'
+ .format(sleep - i),
+ eol='\r')
+
+ # Power on the VM
+ self.__printProgression__('In progress',
+ key + ' creation: starting', eol='\r')
+ future2 = self[key].powerOn()
+
+ # Show Power on result
+ if future2.result().status_code is 200:
+ self.__printProgression__('In progress',
+ key + ' creation: wait for end of boot',
+ eol='\r')
+ else:
+ self.__printProgression__(False,
+ key + ' creation: Error',
+ failed=str(future2.result().status_code))
+ return False
+ # Show creation result
+ if future1.result().status_code is 200:
+ self.__printProgression__('In progress',
+ key + ' creation: created',
+ eol='\r')
+ else:
+ self.__printProgression__(False,
+ key + ' creation: Error',
+ failed=str(future1.result().status_code))
+ return False
+
+ # Wait for puppet catalog to be applied
+ loop_stop = False
+ while not loop_stop:
+ status = self[key].getStatus()
+ if status == 'No Changes' or status == 'Active':
+ self.__printProgression__(True,
+ key + ' creation: provisioning OK')
+ loop_stop = True
+ elif status == 'Error':
+ self.__printProgression__(False,
+ key + ' creation: Error',
+ failed="Error during provisioning")
+ loop_stop = True
+ return False
+ else:
+ self.__printProgression__('In progress',
+ key + ' creation: provisioning ({})'
+ .format(status),
+ eol='\r')
+ time.sleep(5)
+
+ return True
diff --git a/opensteak/tools/opensteak/foreman_objects/item.py b/opensteak/tools/opensteak/foreman_objects/item.py
new file mode 100644
index 000000000..f418f8c11
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/item.py
@@ -0,0 +1,135 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# David Blaisonneau <david.blaisonneau@orange.com>
+# Arnaud Morin <arnaud1.morin@orange.com>
+
+from pprint import pprint as pp
+
+
+class ForemanItem(dict):
+ """
+ Item class
+ Represent the content of a foreman object as a dict
+ """
+
+ def __init__(self, api, key,
+ objName, payloadObj,
+ *args, **kwargs):
+ """ Function __init__
+ Represent the content of a foreman object as a dict
+
+ @param api: The foreman api
+ @param key: The object Key
+ @param *args, **kwargs: the dict representation
+ @return RETURN: Itself
+ """
+ self.api = api
+ self.key = key
+ if objName:
+ self.objName = objName
+ if payloadObj:
+ self.payloadObj = payloadObj
+ self.store = dict()
+ if args[0]:
+ self.update(dict(*args, **kwargs))
+ # We get the smart class parameters for the good items
+ if objName in ['hosts', 'hostgroups',
+ 'puppet_classes', 'environments']:
+ from opensteak.foreman_objects.itemSmartClassParameter\
+ import ItemSmartClassParameter
+ scp_ids = map(lambda x: x['id'],
+ self.api.list('{}/{}/smart_class_parameters'
+ .format(self.objName, key)))
+ scp_items = list(map(lambda x: ItemSmartClassParameter(self.api, x,
+ self.api.get('smart_class_parameters', x)),
+ scp_ids))
+ scp = {'{}::{}'.format(x['puppetclass']['name'],
+ x['parameter']): x
+ for x in scp_items}
+ self.update({'smart_class_parameters_dict': scp})
+
+ def __setitem__(self, key, attributes):
+ """ Function __setitem__
+ Set a parameter of a foreman object as a dict
+
+ @param key: The key to modify
+ @param attribute: The data
+ @return RETURN: The API result
+ """
+ if key is 'puppetclass_ids':
+ payload = {"puppetclass_id": attributes,
+ self.payloadObj + "_class":
+ {"puppetclass_id": attributes}}
+ return self.api.create("{}/{}/{}"
+ .format(self.objName,
+ self.key,
+ "puppetclass_ids"),
+ payload)
+ elif key is 'parameters':
+ payload = {"parameter": attributes}
+ return self.api.create("{}/{}/{}"
+ .format(self.objName,
+ self.key,
+ "parameters"),
+ payload)
+ else:
+ payload = {self.payloadObj: {key: attributes}}
+ return self.api.set(self.objName, self.key, payload)
+
+ def getParam(self, name=None):
+ """ Function getParam
+ Return a dict of parameters or a parameter value
+
+ @param key: The parameter name
+ @return RETURN: dict of parameters or a parameter value
+ """
+ if 'parameters' in self.keys():
+ l = {x['name']: x['value'] for x in self['parameters']}
+ if name:
+ if name in l.keys():
+ return l[name]
+ else:
+ return False
+ else:
+ return l
+
+ def checkAndCreateClasses(self, classes):
+ """ Function checkAndCreateClasses
+ Check and add puppet classe
+
+ @param key: The parameter name
+ @param classes: The classes ids list
+ @return RETURN: boolean
+ """
+ actual_classes = self['puppetclass_ids']
+ for v in classes:
+ if v not in actual_classes:
+ self['puppetclass_ids'] = v
+ return list(classes).sort() is list(self['puppetclass_ids']).sort()
+
+ def checkAndCreateParams(self, params):
+ """ Function checkAndCreateParams
+ Check and add global parameters
+
+ @param key: The parameter name
+ @param params: The params dict
+ @return RETURN: boolean
+ """
+ actual_params = self['param_ids']
+ for k, v in params.items():
+ if k not in actual_params:
+ self['parameters'] = {"name": k, "value": v}
+ return self['param_ids'].sort() == list(params.values()).sort()
diff --git a/opensteak/tools/opensteak/foreman_objects/itemHost.py b/opensteak/tools/opensteak/foreman_objects/itemHost.py
new file mode 100644
index 000000000..c531e5cf4
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/itemHost.py
@@ -0,0 +1,141 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+import base64
+from string import Template
+from opensteak.foreman_objects.item import ForemanItem
+
+
+class ItemHost(ForemanItem):
+ """
+ ItemHostsGroup class
+ Represent the content of a foreman hostgroup as a dict
+ """
+
+ objName = 'hosts'
+ payloadObj = 'host'
+
+ def __init__(self, api, key, *args, **kwargs):
+ """ Function __init__
+ Represent the content of a foreman object as a dict
+
+ @param api: The foreman api
+ @param key: The object Key
+ @param *args, **kwargs: the dict representation
+ @return RETURN: Itself
+ """
+ ForemanItem.__init__(self, api, key,
+ self.objName, self.payloadObj,
+ *args, **kwargs)
+ self.update({'puppetclass_ids':
+ self.api.list('{}/{}/puppetclass_ids'
+ .format(self.objName, key))})
+ self.update({'param_ids':
+ list(self.api.list('{}/{}/parameters'
+ .format(self.objName, key),
+ only_id=True)
+ .keys())})
+
+
+ def getStatus(self):
+ """ Function getStatus
+ Get the status of an host
+
+ @return RETURN: The host status
+ """
+ return self.api.get('hosts', self.key, 'status')['status']
+
+ def powerOn(self):
+ """ Function powerOn
+ Power on a host
+
+ @return RETURN: The API result
+ """
+ return self.api.set('hosts', self.key,
+ {"power_action": "start"},
+ 'power', async=self.async)
+
+ def getParamFromEnv(self, var, default=''):
+ """ Function getParamFromEnv
+ Search a parameter in the host environment
+
+ @param var: the var name
+ @param hostgroup: the hostgroup item linked to this host
+ @param default: default value
+ @return RETURN: the value
+ """
+ if self.getParam(var):
+ return self.getParam(var)
+ if self.hostgroup:
+ if self.hostgroup.getParam(var):
+ return self.hostgroup.getParam(var)
+ if self.domain.getParam('password'):
+ return self.domain.getParam('password')
+ else:
+ return default
+
+ def getUserData(self,
+ hostgroup,
+ domain,
+ defaultPwd='',
+ defaultSshKey='',
+ proxyHostname='',
+ tplFolder='templates_metadata/'):
+ """ Function getUserData
+ Generate a userdata script for metadata server from Foreman API
+
+ @param domain: the domain item linked to this host
+ @param hostgroup: the hostgroup item linked to this host
+ @param defaultPwd: the default password if no password is specified
+ in the host>hostgroup>domain params
+ @param defaultSshKey: the default ssh key if no password is specified
+ in the host>hostgroup>domain params
+ @param proxyHostname: hostname of the smartproxy
+ @param tplFolder: the templates folder
+ @return RETURN: the user data
+ """
+ if 'user-data' in self.keys():
+ return self['user-data']
+ else:
+ self.hostgroup = hostgroup
+ self.domain = domain
+ if proxyHostname == '':
+ proxyHostname = 'foreman.' + domain
+ password = self.getParamFromEnv('password', defaultPwd)
+ sshauthkeys = self.getParamFromEnv('global_sshkey', defaultSshKey)
+ with open(tplFolder+'puppet.conf', 'rb') as puppet_file:
+ p = MyTemplate(puppet_file.read())
+ enc_puppet_file = base64.b64encode(p.substitute(
+ foremanHostname=proxyHostname))
+ with open(tplFolder+'cloud-init.tpl', 'r') as content_file:
+ s = MyTemplate(content_file.read())
+ if sshauthkeys:
+ sshauthkeys = ' - '+sshauthkeys
+ self.userdata = s.substitute(
+ password=password,
+ fqdn=self['name'],
+ sshauthkeys=sshauthkeys,
+ foremanurlbuilt="http://{}/unattended/built"
+ .format(proxyHostname),
+ puppet_conf_content=enc_puppet_file.decode('utf-8'))
+ return self.userdata
+
+
+class MyTemplate(Template):
+ delimiter = '%'
+ idpattern = r'[a-z][_a-z0-9]*'
diff --git a/opensteak/tools/opensteak/foreman_objects/itemHostsGroup.py b/opensteak/tools/opensteak/foreman_objects/itemHostsGroup.py
new file mode 100644
index 000000000..d6a641c03
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/itemHostsGroup.py
@@ -0,0 +1,50 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+from opensteak.foreman_objects.item import ForemanItem
+
+
+class ItemHostsGroup(ForemanItem):
+ """
+ ItemHostsGroup class
+ Represent the content of a foreman hostgroup as a dict
+ """
+
+ objName = 'hostgroups'
+ payloadObj = 'hostgroup'
+
+ def __init__(self, api, key, *args, **kwargs):
+ """ Function __init__
+ Represent the content of a foreman object as a dict
+
+ @param api: The foreman api
+ @param key: The object Key
+ @param *args, **kwargs: the dict representation
+ @return RETURN: Itself
+ """
+ ForemanItem.__init__(self, api, key,
+ self.objName, self.payloadObj,
+ *args, **kwargs)
+ self.update({'puppetclass_ids':
+ self.api.list('{}/{}/puppetclass_ids'
+ .format(self.objName, key))})
+ self.update({'param_ids':
+ list(self.api.list('{}/{}/parameters'
+ .format(self.objName, key),
+ only_id=True)
+ .keys())})
diff --git a/opensteak/tools/opensteak/foreman_objects/itemOverrideValues.py b/opensteak/tools/opensteak/foreman_objects/itemOverrideValues.py
new file mode 100644
index 000000000..936185e98
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/itemOverrideValues.py
@@ -0,0 +1,61 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+
+from opensteak.foreman_objects.item import ForemanItem
+from pprint import pprint as pp
+
+class ItemOverrideValues(ForemanItem):
+ """
+ ItemOverrideValues class
+ Represent the content of a foreman smart class parameter as a dict
+ """
+
+ objName = 'override_values'
+ payloadObj = 'override_value'
+
+ def __init__(self, api, key, parentName, parentKey, *args, **kwargs):
+ """ Function __init__
+ Represent the content of a foreman object as a dict
+
+ @param api: The foreman api
+ @param key: The object Key
+ @param parentName: The object parent name (eg: smart_class_parameter)
+ @param parentKey: The object parent key
+ @param *args, **kwargs: the dict representation
+ @return RETURN: Itself
+ """
+ self.parentName = parentName
+ self.parentKey = parentKey
+ ForemanItem.__init__(self, api, key,
+ self.objName, self.payloadObj,
+ *args, **kwargs)
+
+ def __setitem__(self, key, attributes):
+ """ Function __setitem__
+ Set a parameter of a foreman object as a dict
+
+ @param key: The key to modify
+ @param attribute: The data
+ @return RETURN: The API result
+ """
+ payload = {self.payloadObj: {key: attributes}}
+ return self.api.set('{}/{}/{}'.format(self.parentName,
+ self.parentKey,
+ self.objName),
+ self.key, payload)
diff --git a/opensteak/tools/opensteak/foreman_objects/itemSmartClassParameter.py b/opensteak/tools/opensteak/foreman_objects/itemSmartClassParameter.py
new file mode 100644
index 000000000..2d7ca2ab9
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/itemSmartClassParameter.py
@@ -0,0 +1,62 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+
+from opensteak.foreman_objects.item import ForemanItem
+from opensteak.foreman_objects.itemOverrideValues import ItemOverrideValues
+
+
+class ItemSmartClassParameter(ForemanItem):
+ """
+ ItemSmartClassParameter class
+ Represent the content of a foreman smart class parameter as a dict
+ """
+
+ objName = 'smart_class_parameters'
+ payloadObj = 'smart_class_parameter'
+
+ def __init__(self, api, key, *args, **kwargs):
+ """ Function __init__
+ Represent the content of a foreman object as a dict
+
+ @param api: The foreman api
+ @param key: The object Key
+ @param *args, **kwargs: the dict representation
+ @return RETURN: Itself
+ """
+ ForemanItem.__init__(self, api, key,
+ self.objName, self.payloadObj,
+ *args, **kwargs)
+ self.update({'override_values':
+ list(map(lambda x: ItemOverrideValues(self.api,
+ x['id'],
+ self.objName,
+ key,
+ x),
+ self['override_values']))})
+
+ def __setitem__(self, key, attributes):
+ """ Function __setitem__
+ Set a parameter of a foreman object as a dict
+
+ @param key: The key to modify
+ @param attribute: The data
+ @return RETURN: The API result
+ """
+ payload = {self.payloadObj: {key: attributes}}
+ return self.api.set(self.objName, self.key, payload)
diff --git a/opensteak/tools/opensteak/foreman_objects/objects.py b/opensteak/tools/opensteak/foreman_objects/objects.py
new file mode 100644
index 000000000..c20c5a138
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/objects.py
@@ -0,0 +1,136 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+from opensteak.foreman_objects.item import ForemanItem
+
+
+class ForemanObjects:
+ """
+ ForemanObjects class
+ Parent class for Foreman Objects
+ """
+
+ def __init__(self, api, objName=None, payloadObj=None):
+ """ Function __init__
+ Init the foreman object
+
+ @param api: The foreman API
+ @param objName: The object name (linked with the Foreman API)
+ @param payloadObj: The object name inside the payload (in general
+ the singular of objName)
+ @return RETURN: Itself
+ """
+
+ self.api = api
+ if objName:
+ self.objName = objName
+ if payloadObj:
+ self.payloadObj = payloadObj
+ # For asynchronous creations
+ self.async = False
+
+ def __iter__(self):
+ """ Function __iter__
+
+ @return RETURN: The iteration of objects list
+ """
+ return iter(self.list())
+
+ def __getitem__(self, key):
+ """ Function __getitem__
+
+ @param key: The targeted object
+ @return RETURN: A ForemanItem
+ """
+ return ForemanItem(self.api,
+ key,
+ self.objName,
+ self.payloadObj,
+ self.api.get(self.objName, key))
+
+ def __setitem__(self, key, attributes):
+ """ Function __setitem__
+
+ @param key: The targeted object
+ @param attributes: The attributes to apply to the object
+ @return RETURN: API result if the object was not present, or False
+ """
+ if key not in self:
+ payload = {self.payloadObj: {'name': key}}
+ payload[self.payloadObj].update(attributes)
+ return self.api.create(self.objName, payload, async=self.async)
+ return False
+
+ def __delitem__(self, key):
+ """ Function __delitem__
+
+ @return RETURN: API result
+ """
+ return self.api.delete(self.objName, key)
+
+ def __contains__(self, key):
+ """ Function __contains__
+
+ @param key: The targeted object
+ @return RETURN: True if the object exists
+ """
+ return bool(key in self.listName().keys())
+
+ def getId(self, key):
+ """ Function getId
+ Get the id of an object
+
+ @param key: The targeted object
+ @return RETURN: The ID
+ """
+ return self.api.get_id_by_name(self.objName, key)
+
+ def list(self, limit=20):
+ """ Function list
+ Get the list of all objects
+
+ @param key: The targeted object
+ @param limit: The limit of items to return
+ @return RETURN: A ForemanItem list
+ """
+ return list(map(lambda x:
+ ForemanItem(self.api, x['id'],
+ self.objName, self.payloadObj,
+ x),
+ self.api.list(self.objName, limit=limit)))
+
+ def listName(self):
+ """ Function listName
+ Get the list of all objects name with Ids
+
+ @param key: The targeted object
+ @return RETURN: A dict of obejct name:id
+ """
+ return self.api.list(self.objName, limit=999999, only_id=True)
+
+ def checkAndCreate(self, key, payload):
+ """ Function checkAndCreate
+ Check if an object exists and create it if not
+
+ @param key: The targeted object
+ @param payload: The targeted object description
+ @return RETURN: The id of the object
+ """
+ if key not in self:
+ self[key] = payload
+ return self[key]['id']
diff --git a/opensteak/tools/opensteak/foreman_objects/operatingsystems.py b/opensteak/tools/opensteak/foreman_objects/operatingsystems.py
new file mode 100644
index 000000000..8cce606e6
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/operatingsystems.py
@@ -0,0 +1,66 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+from opensteak.foreman_objects.objects import ForemanObjects
+from opensteak.foreman_objects.item import ForemanItem
+
+
+class OperatingSystems(ForemanObjects):
+ """
+ OperatingSystems class
+ """
+ objName = 'operatingsystems'
+ payloadObj = 'operatingsystem'
+
+ def __getitem__(self, key):
+ """ Function __getitem__
+
+ @param key: The operating system id/name
+ @return RETURN: The item
+ """
+ ret = self.api.list(self.objName,
+ filter='title = "{}"'.format(key))
+ if len(ret):
+ return ForemanItem(self.api, key,
+ self.objName, self.payloadObj,
+ ret[0])
+ else:
+ return None
+
+ def __setitem__(self, key, attributes):
+ """ Function __getitem__
+
+ @param key: The operating system id/name
+ @param attributes: The content of the operating system to create
+ @return RETURN: The API result
+ """
+ if key not in self:
+ payload = {self.payloadObj: {'title': key}}
+ payload[self.payloadObj].update(attributes)
+ return self.api.create(self.objName, payload)
+ return False
+
+ def listName(self):
+ """ Function listName
+ Get the list of all objects name with Ids
+
+ @param key: The targeted object
+ @return RETURN: A dict of obejct name:id
+ """
+ return { x['title']: x['id'] for x in self.api.list(self.objName,
+ limit=999999)}
diff --git a/opensteak/tools/opensteak/foreman_objects/puppetClasses.py b/opensteak/tools/opensteak/foreman_objects/puppetClasses.py
new file mode 100644
index 000000000..7f397f27a
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/puppetClasses.py
@@ -0,0 +1,46 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+from opensteak.foreman_objects.objects import ForemanObjects
+from opensteak.foreman_objects.item import ForemanItem
+from pprint import pprint as pp
+
+
+class PuppetClasses(ForemanObjects):
+ """
+ OperatingSystems class
+ """
+ objName = 'puppetclasses'
+ payloadObj = 'puppetclass'
+
+ def list(self, limit=20):
+ """ Function list
+ Get the list of all objects
+
+ @param key: The targeted object
+ @param limit: The limit of items to return
+ @return RETURN: A ForemanItem list
+ """
+ puppetClassList = list()
+ for v in self.api.list(self.objName, limit=limit).values():
+ puppetClassList.extend(v)
+ return list(map(lambda x:
+ ForemanItem(self.api, x['id'],
+ self.objName, self.payloadObj,
+ x),
+ puppetClassList))
diff --git a/opensteak/tools/opensteak/foreman_objects/smart_proxies.py b/opensteak/tools/opensteak/foreman_objects/smart_proxies.py
new file mode 100644
index 000000000..2d6518b48
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/smart_proxies.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+from opensteak.foreman_objects.objects import ForemanObjects
+
+
+class SmartProxies(ForemanObjects):
+ """
+ Domain class
+ """
+ objName = 'smart_proxies'
+ payloadObj = 'smart_proxy'
+
+ def importPuppetClasses(self, smartProxyId):
+ """ Function importPuppetClasses
+ Force the reload of puppet classes
+
+ @param smartProxyId: smartProxy Id
+ @return RETURN: the API result
+ """
+ return self.api.create('smart_proxies/{}/import_puppetclasses'.format(smartProxyId), '{}')
diff --git a/opensteak/tools/opensteak/foreman_objects/subnets.py b/opensteak/tools/opensteak/foreman_objects/subnets.py
new file mode 100644
index 000000000..b1cac5445
--- /dev/null
+++ b/opensteak/tools/opensteak/foreman_objects/subnets.py
@@ -0,0 +1,67 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+from opensteak.foreman_objects.objects import ForemanObjects
+
+
+class Subnets(ForemanObjects):
+ """
+ Subnets class
+ """
+ objName = 'subnets'
+ payloadObj = 'subnet'
+
+ def checkAndCreate(self, key, payload, domainId):
+ """ Function checkAndCreate
+ Check if a subnet exists and create it if not
+
+ @param key: The targeted subnet
+ @param payload: The targeted subnet description
+ @param domainId: The domainId to be attached wiuth the subnet
+ @return RETURN: The id of the subnet
+ """
+ if key not in self:
+ self[key] = payload
+ oid = self[key]['id']
+ if not oid:
+ return False
+ #~ Ensure subnet contains the domain
+ subnetDomainIds = []
+ for domain in self[key]['domains']:
+ subnetDomainIds.append(domain['id'])
+ if domainId not in subnetDomainIds:
+ subnetDomainIds.append(domainId)
+ self[key]["domain_ids"] = subnetDomainIds
+ if len(self[key]["domains"]) is not len(subnetDomainIds):
+ return False
+ return oid
+
+ def removeDomain(self, subnetId, domainId):
+ """ Function removeDomain
+ Delete a domain from a subnet
+
+ @param subnetId: The subnet Id
+ @param domainId: The domainId to be attached wiuth the subnet
+ @return RETURN: boolean
+ """
+ subnetDomainIds = []
+ for domain in self[subnetId]['domains']:
+ subnetDomainIds.append(domain['id'])
+ subnetDomainIds.remove(domainId)
+ self[subnetId]["domain_ids"] = subnetDomainIds
+ return len(self[subnetId]["domains"]) is len(subnetDomainIds)
diff --git a/opensteak/tools/opensteak/printer.py b/opensteak/tools/opensteak/printer.py
new file mode 100644
index 000000000..98c5af54e
--- /dev/null
+++ b/opensteak/tools/opensteak/printer.py
@@ -0,0 +1,141 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+import sys
+
+
+class OpenSteakPrinter:
+ """ Just a nice message printer """
+ HEADER = '\033[95m'
+ OKBLUE = '\033[94m'
+ OKGREEN = '\033[92m'
+ WARNING = '\033[93m'
+ FAIL = '\033[91m'
+ ENDC = '\033[0m'
+ BOLD = '\033[1m'
+ UNDERLINE = '\033[4m'
+
+ TABSIZE = 4
+
+ def header(self, msg):
+ """ Function header
+ Print a header for a block
+
+ @param msg: The message to print in the header (limited to 78 chars)
+ @return RETURN: None
+ """
+ print("""
+#
+# {}
+#
+""".format(msg[0:78]))
+
+ def config(self, msg, name, value=None, indent=0):
+ """ Function config
+ Print a line with the value of a parameter
+
+ @param msg: The message to print in the header (limited to 78 chars)
+ @param name: The name of the prameter
+ @param value: The value of the parameter
+ @param indent: Tab size at the beginning of the line
+ @return RETURN: None
+ """
+ ind = ' ' * indent * self.TABSIZE
+ if value is None:
+ print('{} - {} = {}'.format(ind, msg, name))
+ elif value is False:
+ print('{} [{}KO{}] {} > {} (NOT found)'.
+ format(ind, self.FAIL, self.ENDC, msg, name))
+ else:
+ print('{} [{}OK{}] {} > {} = {}'.
+ format(ind, self.OKGREEN, self.ENDC, msg, name, str(value)))
+
+ def list(self, msg, indent=0):
+ """ Function list
+ Print a list item
+
+ @param msg: The message to print in the header (limited to 78 chars)
+ @param indent: Tab size at the beginning of the line
+ @return RETURN: None
+ """
+ print(' ' * indent * self.TABSIZE, '-', msg)
+
+ def list_id(self, dic, indent=0):
+ """ Function list_id
+ Print a list of dict items
+
+ @param dic: The dict to print
+ @param indent: Tab size at the beginning of the line
+ @return RETURN: None
+ """
+ for (k, v) in dic.items():
+ self.list("{}: {}".format(k, v), indent=indent)
+
+ def status(self, res, msg, failed="", eol="\n", quit=True, indent=0):
+ """ Function status
+ Print status message
+ - OK/KO if the result is a boolean
+ - Else the result text
+
+ @param res: The status to show
+ @param msg: The message to show
+ @param eol: End of line
+ @param quit: Exit the system in case of failure
+ @param indent: Tab size at the beginning of the line
+ @return RETURN: None
+ """
+ ind = ' ' * indent * self.TABSIZE
+ if res is True:
+ msg = '{} [{}OK{}] {}'.format(ind, self.OKGREEN, self.ENDC, msg)
+ elif res:
+ msg = '{} [{}{}{}] {}'.format(ind, self.OKBLUE, res,
+ self.ENDC, msg)
+ else:
+ msg = '{} [{}KO{}] {}'.format(ind, self.FAIL, self.ENDC, msg)
+ if failed:
+ msg += '\n > {}'.format(failed)
+ msg = msg.ljust(140) + eol
+ sys.stdout.write(msg)
+ if res is False and quit is True:
+ sys.exit(0)
+
+ def ask_validation(self, prompt=None, resp=False):
+ """ Function ask_validation
+ Ask a validation message
+
+ @param prompt: The question to ask ('Continue ?') if None
+ @param resp: The default value (Default is False)
+ @return RETURN: Trie or False
+ """
+ if prompt is None:
+ prompt = 'Continue ?'
+ if resp:
+ prompt += ' [{}Y{}/n]: '.format(self.BOLD, self.ENDC)
+ else:
+ prompt += ' [y/{}N{}]: '.format(self.BOLD, self.ENDC)
+ while True:
+ ans = input(prompt)
+ if not ans:
+ ans = 'y' if resp else 'n'
+ if ans not in ['y', 'Y', 'n', 'N']:
+ print('please enter y or n.')
+ continue
+ if ans == 'y' or ans == 'Y':
+ return True
+ if ans == 'n' or ans == 'N':
+ sys.exit(0)
diff --git a/opensteak/tools/opensteak/templateparser.py b/opensteak/tools/opensteak/templateparser.py
new file mode 100644
index 000000000..720f008da
--- /dev/null
+++ b/opensteak/tools/opensteak/templateparser.py
@@ -0,0 +1,34 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+"""
+Template parser
+"""
+
+from string import Template
+
+class OpenSteakTemplateParser:
+
+ def __init__(self, filein, fileout, dictionary):
+ """
+ Parse the files with the dictionary
+ """
+ fin = open(filein)
+ fout = open(fileout,'w')
+ template = Template(fin.read())
+ fout.write(template.substitute(dictionary))
diff --git a/opensteak/tools/opensteak/virsh.py b/opensteak/tools/opensteak/virsh.py
new file mode 100644
index 000000000..594b84299
--- /dev/null
+++ b/opensteak/tools/opensteak/virsh.py
@@ -0,0 +1,174 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# Authors:
+# @author: David Blaisonneau <david.blaisonneau@orange.com>
+# @author: Arnaud Morin <arnaud1.morin@orange.com>
+
+"""
+Virsh library
+"""
+
+import subprocess
+import os
+
+class OpenSteakVirsh:
+
+ virsh = "/usr/bin/virsh"
+ genisoimage = "/usr/bin/genisoimage"
+ environment = ""
+
+ ###
+ # INIT
+ ###
+ def __init__(self):
+ self.environment = dict(os.environ) # Copy current environment
+ self.environment['LANG'] = 'en_US.UTF-8'
+
+
+ ###
+ # VOLUMES
+ ###
+ def volumeList(self, pool="default"):
+ """
+ Return all volumes from a pool
+ """
+ p = subprocess.Popen([self.virsh, "-q", "vol-list", pool], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=self.environment)
+ stdout, stderr = p.communicate()
+
+ # Split lines
+ lines = stdout.splitlines()
+
+ # Foreach line, split with space and construct a dictionnary
+ newLines = {}
+ for line in lines:
+ name, path = line.split(maxsplit=1)
+ newLines[name.strip()] = path.strip()
+
+ return newLines
+
+ def volumeDelete(self, path):
+ """
+ Delete a volume
+ """
+ p = subprocess.Popen([self.virsh, "-q", "vol-delete", path], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=self.environment)
+ stdout, stderr = p.communicate()
+
+ return {"stdout":stdout, "stderr":stderr}
+
+ def volumeClone(self, origin, name, pool="default"):
+ """
+ Clone a volume
+ """
+ p = subprocess.Popen([self.virsh, "-q", "vol-clone", "--pool", pool, origin, name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=self.environment)
+ stdout, stderr = p.communicate()
+
+ return {"stdout":stdout, "stderr":stderr}
+
+ def volumeResize(self, name, size, pool="default"):
+ """
+ Resize a volume
+ """
+ p = subprocess.Popen([self.virsh, "-q", "vol-resize", "--pool", pool, name, size], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=self.environment)
+ stdout, stderr = p.communicate()
+
+ return {"stdout":stdout, "stderr":stderr}
+
+ ###
+ # POOLS
+ ###
+ def poolRefresh(self, pool="default"):
+ """
+ Refresh a pool
+ """
+ p = subprocess.Popen([self.virsh, "-q", "pool-refresh", pool], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=self.environment)
+ stdout, stderr = p.communicate()
+
+ return {"stdout":stdout, "stderr":stderr}
+
+ ###
+ # DOMAINS
+ ###
+ def domainList(self):
+ """
+ Return all domains (VM)
+ """
+ p = subprocess.Popen([self.virsh, "-q", "list", "--all"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=self.environment)
+ stdout, stderr = p.communicate()
+
+ # Split lines
+ lines = stdout.splitlines()
+
+ # Foreach line, split with space and construct a dictionnary
+ newLines = {}
+ for line in lines:
+ id, name, status = line.split(maxsplit=2)
+ newLines[name.strip()] = status.strip()
+
+ return newLines
+
+ def domainDefine(self, xml):
+ """
+ Define a domain (create a VM)
+ """
+ p = subprocess.Popen([self.virsh, "-q", "define", xml], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=self.environment)
+ stdout, stderr = p.communicate()
+
+ return {"stdout":stdout, "stderr":stderr}
+
+ def domainUndefine(self, name):
+ """
+ Undefine a domain (delete a VM)
+ """
+ p = subprocess.Popen([self.virsh, "-q", "undefine", name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=self.environment)
+ stdout, stderr = p.communicate()
+
+ return {"stdout":stdout, "stderr":stderr}
+
+ def domainStart(self, name):
+ """
+ Define a domain (create a VM)
+ """
+ p = subprocess.Popen([self.virsh, "-q", "start", name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=self.environment)
+ stdout, stderr = p.communicate()
+
+ return {"stdout":stdout, "stderr":stderr}
+
+ def domainDestroy(self, name):
+ """
+ Destroy a domain (stop a VM)
+ """
+ p = subprocess.Popen([self.virsh, "-q", "destroy", name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=self.environment)
+ stdout, stderr = p.communicate()
+
+ return {"stdout":stdout, "stderr":stderr}
+
+ ###
+ # ISO
+ ###
+ def generateConfiguration(self, name, files):
+ """
+ Generate an ISO file
+ """
+
+ commandArray = [self.genisoimage, "-quiet", "-o", "/var/lib/libvirt/images/{0}-configuration.iso".format(name), "-volid", "cidata", "-joliet", "-rock"]
+ for k, f in files.items():
+ commandArray.append(f)
+
+ # Generate the iso file
+ p = subprocess.Popen(commandArray, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, env=self.environment)
+ stdout, stderr = p.communicate()
+
+ return {"stdout":stdout, "stderr":stderr}
+