Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : master
---------------------------------------------------------------
commit e11d5a5861d0b720093b947e09b3ee57bc80679d
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Wed Apr 1 18:34:28 2015 +0200
[backend] [WIP] playbooks for the new cloud
---------------------------------------------------------------
.../playbooks/WIP/provision/files/builder.repo | 23 +
.../playbooks/WIP/provision/files/buildsys.pub | 1 +
.../provision/files/mock}/site-defaults.cfg | 0
.../playbooks/WIP/provision/filter_plugins/os.py | 24 +
backend/conf/playbooks/WIP/provision/inventory | 1 +
.../WIP/provision/library/nova_compute.py | 587 ++++++++++++++++++++
.../provision}/provision_builder_tasks.yml | 44 +-
.../playbooks/WIP/provision/spinup_nova_pb.yml | 86 +++
.../playbooks/WIP/provision/spinup_nova_task.yml | 28 +
9 files changed, 777 insertions(+), 17 deletions(-)
diff --git a/backend/conf/playbooks/WIP/provision/files/builder.repo
b/backend/conf/playbooks/WIP/provision/files/builder.repo
new file mode 100644
index 0000000..b1d401e
--- /dev/null
+++ b/backend/conf/playbooks/WIP/provision/files/builder.repo
@@ -0,0 +1,23 @@
+[builder-infrastructure]
+name=Builder Packages from Fedora Infrastructure $releasever - $basearch
+baseurl=http://infrastructure.fedoraproject.org/repo/builder-rpms/$releasever/$basearch/
+enabled=1
+gpgcheck=1
+gpgkey=http://infrastructure.fedoraproject.org/repo/RPM-GPG-KEY-INFRASTRUCTURE
+
+[msuchy-Mock]
+name=Copr repo for Mock owned by msuchy
+description=Mock for RHEL6 with patch from
https://bugzilla.redhat.com/show_bug.cgi?id=1028438 and
https://bugzilla.redhat.com/show_bug.cgi?id=1034805
+baseurl=http://172.16.5.5/results/msuchy/Mock/epel-6-$basearch/
+skip_if_unavailable=True
+gpgcheck=0
+enabled=1
+
+[msuchy-scl-utils]
+name=Copr repo for scl-utils owned by msuchy
+description=scl-utils with patch from
https://bugzilla.redhat.com/show_bug.cgi?id=985233
+baseurl=http://172.16.5.5/results/msuchy/scl-utils/epel-6-$basearch/
+skip_if_unavailable=True
+gpgcheck=0
+enabled=1
+
diff --git a/backend/conf/playbooks/WIP/provision/files/buildsys.pub
b/backend/conf/playbooks/WIP/provision/files/buildsys.pub
new file mode 100644
index 0000000..10790ee
--- /dev/null
+++ b/backend/conf/playbooks/WIP/provision/files/buildsys.pub
@@ -0,0 +1 @@
+ssh-rsa
AAAAB3NzaC1yc2EAAAADAQABAAABAQCeTO0ddXuhDZYM9HyM0a47aeV2yIVWhTpddrQ7/RAIs99XyrsicQLABzmdMBfiZnP0FnHBF/e+2xEkT8hHJpX6bX81jjvs2bb8KP18Nh8vaXI3QospWrRygpu1tjzqZT0Llh4ZVFscum8TrMw4VWXclzdDw6x7csCBjSttqq8F3iTJtQ9XM9/5tCAAOzGBKJrsGKV1CNIrfUo5CSzY+IUVIr8XJ93IB2ZQVASK34T/49egmrWlNB32fqAbDMC+XNmobgn6gO33Yq5Ly7Dk4kqTUx2TEaqDkZfhsVu0YcwV81bmqsltRvpj6bIXrEoMeav7nbuqKcPLTxWEY/2icePF
diff --git a/backend/conf/playbooks/files/site-defaults.cfg
b/backend/conf/playbooks/WIP/provision/files/mock/site-defaults.cfg
similarity index 100%
copy from backend/conf/playbooks/files/site-defaults.cfg
copy to backend/conf/playbooks/WIP/provision/files/mock/site-defaults.cfg
diff --git a/backend/conf/playbooks/WIP/provision/filter_plugins/os.py
b/backend/conf/playbooks/WIP/provision/filter_plugins/os.py
new file mode 100644
index 0000000..0d3dab0
--- /dev/null
+++ b/backend/conf/playbooks/WIP/provision/filter_plugins/os.py
@@ -0,0 +1,24 @@
+from novaclient.v1_1.client import Client
+
+def nova_result_to_builder_ip(nova_result, network_name):
+ return nova_result["addresses"][network_name][0]["addr"]
+
+def network_name_to_id(network_name, username, password, tenant_name, auth_url):
+ nt = Client(username, password, tenant_name, auth_url, insecure=True)
+ # import ipdb; ipdb.set_trace()
+ return nt.networks.find(label=network_name).id
+
+
+
+class FilterModule(object):
+ def filters(self):
+ return {
+ "nova_result_to_builder_ip": nova_result_to_builder_ip,
+ # "flavor_id_to_name": flavor_id_to_name,
+ # "flavor_name_to_id": flavor_name_to_id,
+ # "image_id_to_name": image_id_to_name,
+ # "image_name_to_id": image_name_to_id,
+ "network_name_to_id": network_name_to_id,
+ # "network_id_to_name": network_id_to_name,
+ }
+
diff --git a/backend/conf/playbooks/WIP/provision/inventory
b/backend/conf/playbooks/WIP/provision/inventory
new file mode 100644
index 0000000..2fbb50c
--- /dev/null
+++ b/backend/conf/playbooks/WIP/provision/inventory
@@ -0,0 +1 @@
+localhost
diff --git a/backend/conf/playbooks/WIP/provision/library/nova_compute.py
b/backend/conf/playbooks/WIP/provision/library/nova_compute.py
new file mode 100644
index 0000000..4c1e977
--- /dev/null
+++ b/backend/conf/playbooks/WIP/provision/library/nova_compute.py
@@ -0,0 +1,587 @@
+#!/usr/bin/python
+#coding: utf-8 -*-
+
+# (c) 2013, Benno Joy <benno(a)ansible.com>
+# (c) 2013, John Dewey <john(a)dewey.ws>
+#
+# This module is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This software is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this software. If not, see <
http://www.gnu.org/licenses/>.
+
+import operator
+import os
+
+try:
+ from novaclient.v1_1 import client as nova_client
+ from novaclient.v1_1 import floating_ips
+ from novaclient import exceptions
+ from novaclient import utils
+ import time
+except ImportError:
+ print("failed=True msg='novaclient is required for this module'")
+
+DOCUMENTATION = '''
+---
+module: nova_compute
+version_added: "1.2"
+short_description: Create/Delete VMs from OpenStack
+description:
+ - Create or Remove virtual machines from Openstack.
+options:
+ login_username:
+ description:
+ - login username to authenticate to keystone
+ required: true
+ default: admin
+ login_password:
+ description:
+ - Password of login user
+ required: true
+ default: 'yes'
+ login_tenant_name:
+ description:
+ - The tenant name of the login user
+ required: true
+ default: 'yes'
+ auth_url:
+ description:
+ - The keystone url for authentication
+ required: false
+ default: 'http://127.0.0.1:35357/v2.0/'
+ region_name:
+ description:
+ - Name of the region
+ required: false
+ default: None
+ state:
+ description:
+ - Indicate desired state of the resource
+ choices: ['present', 'absent']
+ default: present
+ name:
+ description:
+ - Name that has to be given to the instance
+ required: true
+ default: None
+ image_id:
+ description:
+ - The id of the base image to boot. Mutually exclusive with image_name
+ required: true
+ default: None
+ image_name:
+ description:
+ - The name of the base image to boot. Mutually exclusive with image_id
+ required: true
+ default: None
+ version_added: "1.8"
+ image_exclude:
+ description:
+ - Text to use to filter image names, for the case, such as HP, where there are
multiple image names matching the common identifying portions. image_exclude is a negative
match filter - it is text that may not exist in the image name. Defaults to
"(deprecated)"
+ version_added: "1.8"
+ flavor_id:
+ description:
+ - The id of the flavor in which the new VM has to be created. Mutually exclusive
with flavor_ram
+ required: false
+ default: 1
+ flavor_ram:
+ description:
+ - The minimum amount of ram in MB that the flavor in which the new VM has to be
created must have. Mutually exclusive with flavor_id
+ required: false
+ default: 1
+ version_added: "1.8"
+ flavor_include:
+ description:
+ - Text to use to filter flavor names, for the case, such as Rackspace, where
there are multiple flavors that have the same ram count. flavor_include is a positive
match filter - it must exist in the flavor name.
+ version_added: "1.8"
+ key_name:
+ description:
+ - The key pair name to be used when creating a VM
+ required: false
+ default: None
+ security_groups:
+ description:
+ - The name of the security group to which the VM should be added
+ required: false
+ default: None
+ nics:
+ description:
+ - A list of network id's to which the VM's interface should be attached
+ required: false
+ default: None
+ auto_floating_ip:
+ description:
+ - Should a floating ip be auto created and assigned
+ required: false
+ default: 'yes'
+ version_added: "1.8"
+ floating_ips:
+ description:
+ - list of valid floating IPs that pre-exist to assign to this node
+ required: false
+ default: None
+ version_added: "1.8"
+ floating_ip_pools:
+ description:
+ - list of floating IP pools from which to choose a floating IP
+ required: false
+ default: None
+ version_added: "1.8"
+ availability_zone:
+ description:
+ - Name of the availability zone
+ required: false
+ default: None
+ version_added: "1.8"
+ meta:
+ description:
+ - A list of key value pairs that should be provided as a metadata to the new VM
+ required: false
+ default: None
+ wait:
+ description:
+ - If the module should wait for the VM to be created.
+ required: false
+ default: 'yes'
+ wait_for:
+ description:
+ - The amount of time the module should wait for the VM to get into active state
+ required: false
+ default: 180
+ config_drive:
+ description:
+ - Whether to boot the server with config drive enabled
+ required: false
+ default: 'no'
+ version_added: "1.8"
+ user_data:
+ description:
+ - Opaque blob of data which is made available to the instance
+ required: false
+ default: None
+ version_added: "1.6"
+requirements: ["novaclient"]
+'''
+
+EXAMPLES = '''
+# Creates a new VM and attaches to a network and passes metadata to the instance
+- nova_compute:
+ state: present
+ login_username: admin
+ login_password: admin
+ login_tenant_name: admin
+ name: vm1
+ image_id: 4f905f38-e52a-43d2-b6ec-754a13ffb529
+ key_name: ansible_key
+ wait_for: 200
+ flavor_id: 4
+ nics:
+ - net-id: 34605f38-e52a-25d2-b6ec-754a13ffb723
+ meta:
+ hostname: test1
+ group: uge_master
+
+# Creates a new VM in HP Cloud AE1 region availability zone az2 and automatically assigns
a floating IP
+- name: launch a nova instance
+ hosts: localhost
+ tasks:
+ - name: launch an instance
+ nova_compute:
+ state: present
+ login_username: username
+ login_password: Equality7-2521
+ login_tenant_name: username-project1
+ name: vm1
+ auth_url:
https://region-b.geo-1.identity.hpcloudsvc.com:35357/v2.0/
+ region_name: region-b.geo-1
+ availability_zone: az2
+ image_id: 9302692b-b787-4b52-a3a6-daebb79cb498
+ key_name: test
+ wait_for: 200
+ flavor_id: 101
+ security_groups: default
+ auto_floating_ip: yes
+
+# Creates a new VM in HP Cloud AE1 region availability zone az2 and assigns a pre-known
floating IP
+- name: launch a nova instance
+ hosts: localhost
+ tasks:
+ - name: launch an instance
+ nova_compute:
+ state: present
+ login_username: username
+ login_password: Equality7-2521
+ login_tenant_name: username-project1
+ name: vm1
+ auth_url:
https://region-b.geo-1.identity.hpcloudsvc.com:35357/v2.0/
+ region_name: region-b.geo-1
+ availability_zone: az2
+ image_id: 9302692b-b787-4b52-a3a6-daebb79cb498
+ key_name: test
+ wait_for: 200
+ flavor_id: 101
+ floating-ips:
+ - 12.34.56.79
+
+# Creates a new VM with 4G of RAM on Ubuntu Trusty, ignoring deprecated images
+- name: launch a nova instance
+ hosts: localhost
+ tasks:
+ - name: launch an instance
+ nova_compute:
+ name: vm1
+ state: present
+ login_username: username
+ login_password: Equality7-2521
+ login_tenant_name: username-project1
+ auth_url:
https://region-b.geo-1.identity.hpcloudsvc.com:35357/v2.0/
+ region_name: region-b.geo-1
+ image_name: Ubuntu Server 14.04
+ image_exclude: deprecated
+ flavor_ram: 4096
+
+# Creates a new VM with 4G of RAM on Ubuntu Trusty on a Rackspace Performance node in
DFW
+- name: launch a nova instance
+ hosts: localhost
+ tasks:
+ - name: launch an instance
+ nova_compute:
+ name: vm1
+ state: present
+ login_username: username
+ login_password: Equality7-2521
+ login_tenant_name: username-project1
+ auth_url:
https://identity.api.rackspacecloud.com/v2.0/
+ region_name: DFW
+ image_name: Ubuntu 14.04 LTS (Trusty Tahr) (PVHVM)
+ flavor_ram: 4096
+ flavor_include: Performance
+'''
+
+
+
+def _delete_server(module, nova):
+ name = None
+ server_list = None
+ try:
+ server_list = nova.servers.list(True, {'name':
module.params['name']})
+ if server_list:
+ server = [x for x in server_list if x.name == module.params['name']]
+ nova.servers.delete(server.pop())
+ except Exception, e:
+ module.fail_json( msg = "Error in deleting vm: %s" % e.message)
+ if module.params['wait'] == 'no':
+ module.exit_json(changed = True, result = "deleted")
+ expire = time.time() + int(module.params['wait_for'])
+ while time.time() < expire:
+ name = nova.servers.list(True, {'name': module.params['name']})
+ if not name:
+ module.exit_json(changed = True, result = "deleted")
+ time.sleep(5)
+ module.fail_json(msg = "Timed out waiting for server to get deleted, please
check manually")
+
+
+def _add_floating_ip_from_pool(module, nova, server):
+
+ # instantiate FloatingIPManager object
+ floating_ip_obj = floating_ips.FloatingIPManager(nova)
+
+ # empty dict and list
+ usable_floating_ips = {}
+ pools = []
+
+ # user specified
+ pools = module.params['floating_ip_pools']
+
+ # get the list of all floating IPs. Mileage may
+ # vary according to Nova Compute configuration
+ # per cloud provider
+ all_floating_ips = floating_ip_obj.list()
+
+ # iterate through all pools of IP address. Empty
+ # string means all and is the default value
+ for pool in pools:
+ # temporary list per pool
+ pool_ips = []
+ # loop through all floating IPs
+ for f_ip in all_floating_ips:
+ # if not reserved and the correct pool, add
+ if f_ip.instance_id is None and (f_ip.pool == pool):
+ pool_ips.append(f_ip.ip)
+ # only need one
+ break
+
+ # if the list is empty, add for this pool
+ if not pool_ips:
+ try:
+ new_ip = nova.floating_ips.create(pool)
+ except Exception, e:
+ module.fail_json(msg = "Unable to create floating ip")
+ pool_ips.append(new_ip.ip)
+ # Add to the main list
+ usable_floating_ips[pool] = pool_ips
+
+ # finally, add ip(s) to instance for each pool
+ for pool in usable_floating_ips:
+ for ip in usable_floating_ips[pool]:
+ try:
+ server.add_floating_ip(ip)
+ # We only need to assign one ip - but there is an inherent
+ # race condition and some other cloud operation may have
+ # stolen an available floating ip
+ break
+ except Exception, e:
+ module.fail_json(msg = "Error attaching IP %s to instance %s: %s
" % (ip, server.id, e.message))
+
+
+def _add_floating_ip_list(module, server, ips):
+ # add ip(s) to instance
+ for ip in ips:
+ try:
+ server.add_floating_ip(ip)
+ except Exception, e:
+ module.fail_json(msg = "Error attaching IP %s to instance %s: %s "
% (ip, server.id, e.message))
+
+
+def _add_auto_floating_ip(module, nova, server):
+
+ try:
+ new_ip = nova.floating_ips.create()
+ except Exception as e:
+ module.fail_json(msg = "Unable to create floating ip: %s" %
(e.message))
+
+ try:
+ server.add_floating_ip(new_ip)
+ except Exception as e:
+ # Clean up - we auto-created this ip, and it's not attached
+ # to the server, so the cloud will not know what to do with it
+ server.floating_ips.delete(new_ip)
+ module.fail_json(msg = "Error attaching IP %s to instance %s: %s " %
(ip, server.id, e.message))
+
+
+def _add_floating_ip(module, nova, server):
+
+ if module.params['floating_ip_pools']:
+ _add_floating_ip_from_pool(module, nova, server)
+ elif module.params['floating_ips']:
+ _add_floating_ip_list(module, server, module.params['floating_ips'])
+ elif module.params['auto_floating_ip']:
+ _add_auto_floating_ip(module, nova, server)
+ else:
+ return server
+
+ # this may look redundant, but if there is now a
+ # floating IP, then it needs to be obtained from
+ # a recent server object if the above code path exec'd
+ try:
+ server = nova.servers.get(server.id)
+ except Exception, e:
+ module.fail_json(msg = "Error in getting info from instance: %s " %
e.message)
+ return server
+
+
+def _get_image_id(module, nova):
+ if module.params['image_name']:
+ for image in nova.images.list():
+ if (module.params['image_name'] in image.name and (
+ not module.params['image_exclude']
+ or module.params['image_exclude'] not in image.name)):
+ return image.id
+ module.fail_json(msg = "Error finding image id from name(%s)" %
module.params['image_name'])
+ return module.params['image_id']
+
+
+def _get_flavor_id(module, nova):
+ if module.params['flavor_ram']:
+ for flavor in sorted(nova.flavors.list(),
key=operator.attrgetter('ram')):
+ if (flavor.ram >= module.params['flavor_ram'] and
+ (not module.params['flavor_include'] or
module.params['flavor_include'] in flavor.name)):
+ return flavor.id
+ module.fail_json(msg = "Error finding flavor with %sMB of RAM" %
module.params['flavor_ram'])
+ return module.params['flavor_id']
+
+
+def _create_server(module, nova):
+ image_id = _get_image_id(module, nova)
+ flavor_id = _get_flavor_id(module, nova)
+ bootargs = [module.params['name'], image_id, flavor_id]
+ bootkwargs = {
+ 'nics' : module.params['nics'],
+ 'meta' : module.params['meta'],
+ 'security_groups':
module.params['security_groups'].split(','),
+ #userdata is unhyphenated in novaclient, but hyphenated here for
consistency with the ec2 module:
+ 'userdata': module.params['user_data'],
+ 'config_drive': module.params['config_drive'],
+ }
+
+ for optional_param in ('region_name', 'key_name',
'availability_zone'):
+ if module.params[optional_param]:
+ bootkwargs[optional_param] = module.params[optional_param]
+ try:
+ server = nova.servers.create(*bootargs, **bootkwargs)
+ server = nova.servers.get(server.id)
+ except Exception, e:
+ module.fail_json( msg = "Error in creating instance: %s " %
e.message)
+ if module.params['wait'] == 'yes':
+ expire = time.time() + int(module.params['wait_for'])
+ while time.time() < expire:
+ try:
+ server = nova.servers.get(server.id)
+ except Exception, e:
+ module.fail_json( msg = "Error in getting info from instance:
%s" % e.message)
+ if server.status == 'ACTIVE':
+ server = _add_floating_ip(module, nova, server)
+
+ private = openstack_find_nova_addresses(getattr(server,
'addresses'), 'fixed', 'private')
+ public = openstack_find_nova_addresses(getattr(server,
'addresses'), 'floating', 'public')
+
+ # now exit with info
+ module.exit_json(changed = True, id = server.id,
private_ip=''.join(private), public_ip=''.join(public), status =
server.status, info = server._info)
+
+ if server.status == 'ERROR':
+ module.fail_json(msg = "Error in creating the server, please check
logs")
+ time.sleep(2)
+
+ module.fail_json(msg = "Timeout waiting for the server to come up.. Please
check manually")
+ if server.status == 'ERROR':
+ module.fail_json(msg = "Error in creating the server.. Please check
manually")
+ private = openstack_find_nova_addresses(getattr(server, 'addresses'),
'fixed', 'private')
+ public = openstack_find_nova_addresses(getattr(server, 'addresses'),
'floating', 'public')
+
+ module.exit_json(changed = True, id = info['id'],
private_ip=''.join(private), public_ip=''.join(public), status =
server.status, info = server._info)
+
+
+def _delete_floating_ip_list(module, nova, server, extra_ips):
+ for ip in extra_ips:
+ nova.servers.remove_floating_ip(server=server.id, address=ip)
+
+
+def _check_floating_ips(module, nova, server):
+ changed = False
+ if module.params['floating_ip_pools'] or
module.params['floating_ips'] or module.params['auto_floating_ip']:
+ ips = openstack_find_nova_addresses(server.addresses, 'floating')
+ if not ips:
+ # If we're configured to have a floating but we don't have one,
+ # let's add one
+ server = _add_floating_ip(module, nova, server)
+ changed = True
+ elif module.params['floating_ips']:
+ # we were configured to have specific ips, let's make sure we have
+ # those
+ missing_ips = []
+ for ip in module.params['floating_ips']:
+ if ip not in ips:
+ missing_ips.append(ip)
+ if missing_ips:
+ server = _add_floating_ip_list(module, server, missing_ips)
+ changed = True
+ extra_ips = []
+ for ip in ips:
+ if ip not in module.params['floating_ips']:
+ extra_ips.append(ip)
+ if extra_ips:
+ _delete_floating_ip_list(module, server, extra_ips)
+ changed = True
+ return (changed, server)
+
+
+def _get_server_state(module, nova):
+ server = None
+ try:
+ servers = nova.servers.list(True, {'name':
module.params['name']})
+ if servers:
+ # the {'name': module.params['name']} will also return
servers
+ # with names that partially match the server name, so we have to
+ # strictly filter here
+ servers = [x for x in servers if x.name == module.params['name']]
+ if servers:
+ server = servers[0]
+ except Exception, e:
+ module.fail_json(msg = "Error in getting the server list: %s" %
e.message)
+ if server and module.params['state'] == 'present':
+ if server.status != 'ACTIVE':
+ module.fail_json( msg="The VM is available but not Active. state:"
+ server.status)
+ (ip_changed, server) = _check_floating_ips(module, nova, server)
+ private = openstack_find_nova_addresses(getattr(server, 'addresses'),
'fixed', 'private')
+ public = openstack_find_nova_addresses(getattr(server, 'addresses'),
'floating', 'public')
+ module.exit_json(changed = ip_changed, id = server.id, public_ip =
''.join(public), private_ip = ''.join(private), info = server._info)
+ if server and module.params['state'] == 'absent':
+ return True
+ if module.params['state'] == 'absent':
+ module.exit_json(changed = False, result = "not present")
+ return True
+
+
+
+def main():
+ argument_spec = openstack_argument_spec()
+ argument_spec.update(dict(
+ name = dict(required=True),
+ image_id = dict(default=None),
+ image_name = dict(default=None),
+ image_exclude = dict(default='(deprecated)'),
+ flavor_id = dict(default=1),
+ flavor_ram = dict(default=None, type='int'),
+ flavor_include = dict(default=None),
+ key_name = dict(default=None),
+ security_groups = dict(default='default'),
+ nics = dict(default=None),
+ meta = dict(default=None),
+ wait = dict(default='yes',
choices=['yes', 'no']),
+ wait_for = dict(default=180),
+ state = dict(default='present',
choices=['absent', 'present']),
+ user_data = dict(default=None),
+ config_drive = dict(default=False, type='bool'),
+ auto_floating_ip = dict(default=False, type='bool'),
+ floating_ips = dict(default=None),
+ floating_ip_pools = dict(default=None),
+ insecure = dict(default=False, type='bool'),
+ ))
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ mutually_exclusive=[
+ ['auto_floating_ip','floating_ips'],
+ ['auto_floating_ip','floating_ip_pools'],
+ ['floating_ips','floating_ip_pools'],
+ ['image_id','image_name'],
+ ['flavor_id','flavor_ram'],
+ ],
+ )
+
+ nova = nova_client.Client(module.params['login_username'],
+ module.params['login_password'],
+ module.params['login_tenant_name'],
+ module.params['auth_url'],
+ region_name=module.params['region_name'],
+ insecure=module.params['insecure'],
+ service_type='compute')
+ try:
+ nova.authenticate()
+ except exceptions.Unauthorized, e:
+ module.fail_json(msg = "Invalid OpenStack Nova credentials.: %s" %
e.message)
+ except exceptions.AuthorizationFailure, e:
+ module.fail_json(msg = "Unable to authorize user: %s" % e.message)
+
+ if module.params['state'] == 'present':
+ if not module.params['image_id'] and not
module.params['image_name']:
+ module.fail_json( msg = "Parameter 'image_id' or `image_name` is
required if state == 'present'")
+ else:
+ _get_server_state(module, nova)
+ _create_server(module, nova)
+ if module.params['state'] == 'absent':
+ _get_server_state(module, nova)
+ _delete_server(module, nova)
+
+# this is magic, see lib/ansible/module_common.py
+from ansible.module_utils.basic import *
+from ansible.module_utils.openstack import *
+main()
+
diff --git a/backend/conf/playbooks/provision_builder_tasks.yml
b/backend/conf/playbooks/WIP/provision/provision_builder_tasks.yml
similarity index 56%
copy from backend/conf/playbooks/provision_builder_tasks.yml
copy to backend/conf/playbooks/WIP/provision/provision_builder_tasks.yml
index 7183692..02db4c5 100644
--- a/backend/conf/playbooks/provision_builder_tasks.yml
+++ b/backend/conf/playbooks/WIP/provision/provision_builder_tasks.yml
@@ -14,6 +14,7 @@
- libsemanage-python
- name: make sure newest rpm
+ # todo: replace with dnf after ansible 1.9 is available
yum: name={{ item }} state=latest
with_items:
- rpm
@@ -21,27 +22,36 @@
- ca-certificates
- name: put updated mock configs into /etc/mock
- copy: src=files/{{ item }} dest=/etc/mock
+ copy: src=files/mock/{{ item }} dest=/etc/mock
with_items:
- site-defaults.cfg
-- name: prepare caches
+# ansible doesn't support simultaneously usage of async and with_* options
+# it's not even planned for implementation, see
https://github.com/ansible/ansible/issues/5841
+#- name: prepare caches
+# when: prepare_base_image is defined
+# async: 3600
+# command: mock -r {{ item }} --init
+# with_items:
+# - epel-5-i386
+# - epel-5-x86_64
+# - epel-6-i386
+# - epel-6-x86_64
+# - epel-7-x86_64
+# - fedora-20-i386
+# - fedora-20-x86_64
+# - fedora-21-i386
+# - fedora-21-x86_64
+# - fedora-22-i386
+# - fedora-22-x86_64
+# - fedora-rawhide-i386
+# - fedora-rawhide-x86_64
+
+
+- name: prepare cache
+ when: prepare_base_image is defined
async: 3600
- command: mock -r {{ item }} --init
- with_items:
- - epel-5-i386
- - epel-5-x86_64
- - epel-6-i386
- - epel-6-x86_64
- - epel-7-x86_64
- - fedora-20-i386
- - fedora-20-x86_64
- - fedora-21-i386
- - fedora-21-x86_64
- - fedora-22-i386
- - fedora-22-x86_64
- - fedora-rawhide-i386
- - fedora-rawhide-x86_64
+ shell: "for i in epel-5-i386 epel-5-x86_64 epel-6-i386 epel-6-x86_64 epel-7-x86_64
fedora-20-i386 fedora-20-x86_64 fedora-21-i386 fedora-21-x86_64 fedora-22-i386
fedora-22-x86_64 fedora-rawhide-i386 fedora-rawhide-x86_64; do mock --init -r $i;
done"
- name: mockbuilder user
user: name=mockbuilder groups=mock
diff --git a/backend/conf/playbooks/WIP/provision/spinup_nova_pb.yml
b/backend/conf/playbooks/WIP/provision/spinup_nova_pb.yml
new file mode 100644
index 0000000..b1bdde6
--- /dev/null
+++ b/backend/conf/playbooks/WIP/provision/spinup_nova_pb.yml
@@ -0,0 +1,86 @@
+- name: check/create instance
+ hosts: 127.0.0.1
+ #hosts: copr-back-stg
+ gather_facts: False
+
+ vars:
+ OS_AUTH_URL: "https://fed-cloud09.cloud.fedoraproject.org:5000/v2.0"
+ image_id: "e71dd9f6-ec73-44dd-946c-25b09fce332d"
+ # With the addition of Keystone we have standardized on the term **tenant**
+ # # as the entity that owns the resources.
+ OS_TENANT_ID: "566a072fb1694950998ad191fee3833b"
+ OS_TENANT_NAME: "coprdev"
+ #
+ # # In addition to the owning entity (tenant), openstack stores the entity
+ # # performing the action as the **user**.
+ OS_USERNAME: "FILLME"
+ #
+ # # With Keystone you pass the keystone password.
+ # echo "Please enter your OpenStack Password: "
+ # read -sr OS_PASSWORD_INPUT
+ OS_PASSWORD: "FILLME"
+ #
+ # _OS_AUTH_OPTS: "--os-auth-url {{OS_AUTH_URL}} --os-username {{OS_USERNAME}}
--os-password {{OS_PASSWORD}} --os-tenant-name {{OS_TENANT_NAME}} --os-tenant-id
{{OS_TENANT_ID}} "
+ # VM_NAME_OR_ID: "vm_from_nova_cli_001"
+
+ network_name: "copr-net"
+ cloud_networks:
+ #- net-id: "53fb02fd-6e97-4cfc-b298-a2ff867daa52"
+ - net-id: "6797b4e3-28a0-4a14-9689-e506d0cca90d"
+ #- net-id: "dcb11bd5-47df-43ed-bb2f-5d9c39bfedcd"
+ keypair: buildsys
+ max_spawn_time: 600
+
+ #prepare_base_image: True
+
+ #vars_prompt:
+ # - name: "OS_PASSWORD"
+ # prompt: "Enter OS password"
+ # private: yes
+ tasks:
+ - name: generate builder name
+ # local_action: command echo "Copr_builder_{{ 999999999 | random }}"
+ #ocal_action: command echo "Copr_builder_138954194"
+ local_action: set_fact vm_name="Copr_builder_{{ 999999999 | random }}"
+ #register: vm_name
+ - debug: msg="VM_NAME={{ vm_name }}"
+
+ - include: "spinup_nova_task.yml"
+
+
+ # - set_fact: builder_ip="{{ nova.info|nova_result_to_builder_ip }}"
+
+ - debug: msg="VM_IP={{ builder_ip }}"
+
+ - name: wait for he host to be hot
+ local_action: wait_for host={{ builder_ip }} port=22 delay=1 timeout=600
+
+ #- name: sleep
+ # local_action: command sleep 20
+
+
+
+ - name: wait until ssh is available
+ local_action: shell false; until [ "$?" -eq "0" ]; do sleep 2;
ssh -o PasswordAuthentication=no fedora@{{ builder_ip }} 'echo foobar'
2>/dev/null; done
+ async: 600
+ poll: 2
+
+
+ #egister: echo_result
+ #ommand: echo foobar
+ #ntil: echo_result.stdout == "foobar"
+ #etries: 15
+ #elay: 5
+ #gnore_errors: True
+
+
+- name: provision builder
+ hosts: builder_temp_group
+ gather_facts: False
+ sudo: True
+ user: fedora
+
+ tasks:
+ #- debug: msg="hello"
+ # # include: "provision_task.yml"
+ - include: "provision_builder_tasks.yml"
diff --git a/backend/conf/playbooks/WIP/provision/spinup_nova_task.yml
b/backend/conf/playbooks/WIP/provision/spinup_nova_task.yml
new file mode 100644
index 0000000..ca7c661
--- /dev/null
+++ b/backend/conf/playbooks/WIP/provision/spinup_nova_task.yml
@@ -0,0 +1,28 @@
+- name: spin/ensure vm with nova_compute
+ local_action:
+ module: nova_compute
+ insecure: True
+ auth_url: "{{OS_AUTH_URL}}"
+ login_username: "{{OS_USERNAME}}"
+ login_password: "{{OS_PASSWORD}}"
+ login_tenant_name: "{{OS_TENANT_NAME}}"
+ name: "{{ vm_name }}"
+ # image_id: 86422ca2-6eeb-435c-87e8-402b3c7c3b7b
+ image_id: "{{ image_id }}"
+ wait_for: "{{ max_spawn_time }}"
+ flavor_id: 2
+ security_groups: ssh-anywhere-coprdev,default,ssh-from-persistent-coprdev
#,ssh-internal-persistent
+ key_name: "{{ keypair }}"
+ nics:
+ - net-id: "{{ network_name|network_name_to_id(OS_USERNAME, OS_PASSWORD,
OS_TENANT_NAME, OS_AUTH_URL) }}"
+ register: nova
+
+- debug: msg="{{ nova.info }}"
+
+
+- set_fact: builder_ip="{{ nova.info|nova_result_to_builder_ip(network_name)
}}"
+
+- name: add it to the special group
+ local_action: add_host hostname={{ builder_ip }} groupname=builder_temp_group
+
+