Moving and reorganizing codebase

Change-Id: Ib1ce0dff824bb57033f4115f2721e765b2fcd293
This commit is contained in:
Julia Kreger 2014-08-14 20:17:56 -04:00
parent 6dd1ccfd67
commit d6bc04296c
27 changed files with 1245 additions and 0 deletions

View File

@ -0,0 +1,20 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
--
os_username: admin
os_password: admin
os_tenant_name: admin
os_region_name: region.x
os_auth_url: http://127.0.0.1:35357/v2.0/

View File

@ -0,0 +1,38 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
- name: rebuild using heat facts
hosts: localhost
tasks:
- name: gather facts from heat
local_action:
module: heat_facts
region_name: regionOne
login_username: admin
login_password: setpassword
login_tenant_name: admin
auth_url: http://192.0.2.1:5000/v3
stacks: all
- name: rebuild all instances
nova_rebuild:
region_name: regionOne
login_username: admin
login_password: setpassword
login_tenant_name: admin
auth_url: http://192.0.2.1:5000/v2.0
name: "{{ item.key }}"
image_id: "{{ item.value.heat_image.id }}"
preserve_ephemeral: yes
wait_for: 200
with_dict: heat_instances

View File

@ -0,0 +1,33 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
- name: examine heat facts
hosts: localhost
tasks:
- name: display facts from heat
local_action:
module: heat_facts
region_name: regionOne
login_username: '{{ lookup("env", "OS_USERNAME") }}'
login_password: '{{ lookup("env", "OS_PASSWORD") }}'
login_tenant_name: '{{ lookup("env", "OS_TENANT_NAME") }}'
auth_url: '{{ lookup("env", "OS_AUTH_URL") }}'
stacks: all
- name: Stacks debug info
debug: msg="Stack Name {{ item.key }}, stack status {{ item.value.heat_stack_status }}"
with_dict: heat_stacks
- name: Instances debug info
debug: msg="Instance Name {{ item.key }}, instance resource type {{ item.value.heat_resource_type }}"
with_dict: heat_instances

View File

@ -0,0 +1,28 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
- name: rebuild a nova instance
hosts: localhost
tasks:
- name: rebuild an instance
nova_rebuild:
region_name: regionOne
login_username: admin
login_password: setpassword
login_tenant_name: admin
auth_url: http://192.0.2.3:5000/v2.0
name: overcloud-NovaCompute-setvmname
image_id: 6663f30c-fff8-4c67-b0a9-fc72193b9eea
preserve_ephemeral: yes
wait_for: 200

View File

@ -0,0 +1,53 @@
A simple iterator for running a playbook.
=========================================
Getting Started
---------------
You will need:
* Stack environment variables loaded.
Example: source $TRIPLEO_ROOT/tripleo-incubator/undercloudrc
* An Ansible Inventory file defining localhost which makes use of a local connection. This file is passed in as the -i option to the included script. You can view such a file at ../hosts_local.
Example Content: "localhost ansible_connection=local"
More information can be found at http://docs.ansible.com/intro_inventory.html
* A file containing a list of instances you wish to run the playbook against.
Example: instances.txt
* A configuration file named update_config.cfg in the folder where your executing the script from. This file has sections that are based upon a portion of the instance name, such as "controller" and "NovaCompute". With-in each section is a "image_id" option which is where you would place the new image ID to rebuild the instance with. Image IDs can be obtained via `glance image-list` once you have the appropriate environment variables loaded.
Example: update_config.cfg
* A playbook, expecting expecting the following
* image_id - glance image id.
* name - instance name
* A slightly modified copy of the simeple_rebuild.yml example playbook exists as main.yml
Putting it all together
-----------------------
source $TRIPLEO_ROOT/tripleo-incubator/undercloudrc
python ./simple_update.py -p ./main.yml -l instances.txt -i ../hosts_local
A Few notes
-----------
1) The variables defined in main.yml before the tasks level are presently
redundant, as the underlying nova_rebuild module supports retrieval of the
configuration from environment variables, although they could be useful for
modules that do not presently support such functionality, or modules that
need to execute remotely.
2) If an inventory is populated of each machine into ansible, then it would
be easy to modify the playbook to connect out and perform actions on each
instance, such as backup a database, fetch files, replace files, etc.

View File

@ -0,0 +1,4 @@
overcloud-NovaCompute0-sbepht5ngm5v
overcloud-NovaCompute1-7d2o5lpz32yt
overcloud-NovaCompute2-wssjjvfecxwk
overcloud-controller0-blhq6zj26lhh

View File

@ -0,0 +1,33 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
- name: rebuild an instance
hosts: localhost
vars:
os_username: "{{ lookup('env','OS_USERNAME') }}"
os_tenant_name: "{{ lookup('env','OS_TENANT_NAME') }}"
os_password: "{{ lookup('env','OS_PASSWORD') }}"
os_auth_url: "{{ lookup('env','OS_AUTH_URL') }}"
tasks:
- name: rebuild an instance
nova_rebuild:
region_name: regionOne
login_username: "{{ os_username }}"
login_password: "{{ os_password }}"
login_tenant_name: "{{ os_tenant_name}}"
auth_url: "{{ os_auth_url }}"
name: "{{ name }}"
image_id: "{{ image_id }}"
preserve_ephemeral: yes
wait_for: 300

View File

@ -0,0 +1,64 @@
#!/usr/bin/env python
#
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
import ConfigParser
import argparse
import subprocess
parser = argparse.ArgumentParser(description='A foo that bars')
parser.add_argument('-p', dest='playbook', help='main.yml', required=True)
parser.add_argument(
'-l',
dest='instances',
help='instances.txt',
required=True
)
parser.add_argument(
'-i',
dest='inventory',
help='inventory.ini',
required=True
)
parser.add_argument(
'-c',
dest='configfile',
help='update_config.cfg',
required=False,
default='update_config.cfg'
)
results = parser.parse_args()
config = ConfigParser.RawConfigParser()
config.read(results.configfile)
with open(results.instances) as list:
for host in list:
for section in config.sections():
if section in host:
hostname = host.strip('\n')
image_id = config.get(section, 'image_id')
args = (
'ansible-playbook',
results.playbook,
'-e',
"name=%s image_id=%s" % (hostname, image_id),
'-i',
results.inventory
)
print "Executing:"
print args
subprocess.call(args)

View File

@ -0,0 +1,26 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
# Each server name "class" should be a section with an underlying
# image_id property that contains the Glance Image ID to be utilized.
# You can obtain a list of loaded image ids utilizing the
# `glance image-list` command.
[controller]
image_id=7732e7ca-52fa-4acf-beeb-9cfd82e0e3df
[NovaCompute]
image_id=0e09dcac-b4de-42c4-b7ad-d86a33c49ae0

346
library/cloud/heat_facts Normal file
View File

@ -0,0 +1,346 @@
#!/usr/bin/python
# (c) 2014 Patrick "CaptTofu" Galbraith <patg@patg.net>
# (c) 2014 Clint Byrum <clint@fewbar.com>
# (c) 2014 Allison Randal <allison@lohutok.net>
# Code also from rax_facts, docker_facts, nova_facts and the primary heat module
#
#
# This file is part of Ansible
#
# Ansible 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.
#
# Ansible 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 Ansible. If not, see <http://www.gnu.org/licenses/>.
# This is a DOCUMENTATION stub specific to this module, it extends
# a documentation fragment located in ansible.utils.module_docs_fragments
DOCUMENTATION = '''
---
module: heat_facts
short_description: Gather facts for Heat instances and images
description:
- Gather facts for Heat instances and images
version_added: "0.1"
options:
id:
description:
- instance ID to retrieve facts for
default: null (all instances if neither name nor id specified)
name:
description:
- instance name to retrieve facts for
default: null (all instances if neither name nor id specified)
address:
description
- instance address, internal or external (floating) to retrieve
facts for
default: null
group:
description
- server group to retrieve facts for (filter instances)
default: null
author: Allison Randal
'''
EXAMPLES = '''
- name: Gather info about instances
hosts: localhost
gather_facts: False
tasks:
- name: Get facts about instance with server id 123
local_action:
login_username: galt
login_password: starnesville
login_tenant_name: galt-project1
auth_url: https://region-b.geo-1.identity.hpcloudsvc.com:35357/v3/
region_name: region-b.geo-1
module: heat_facts
id: f062f85b-5586-479a-b6a2-647385b04715
key_name: test
wait_for: 200
security_groups: default
- name: Get facts about instance with ip address of 10.0.0.102
local_action:
module: heat_facts
address: 10.0.0.102
- name: Gather info about all instances and images
hosts: heat
gather_facts: True
tasks:
- name: Get facts about instances
local_action:
module: heat_facts
stacks: all
- name: stacks debug info
debug: msg="Stack Name {{ item.key }}"
with_dict: heat_stacks
- name: instances debug info
debug: msg="Instance Name {{ item.key }}"
with_dict: heat_instances
'''
from types import NoneType
HAS_KEYSTONE_CLIENT = True
HAS_HEAT_CLIENT = True
HAS_NOVA_CLIENT = True
NON_CALLABLES = (basestring, bool, dict, int, list, NoneType)
try:
from heatclient.v1 import client as heat_client
# from heatclient import exceptions
except ImportError:
HAS_HEAT_CLIENT = False
print("failed=True msg='heatclient is required for this module'")
try:
from novaclient.v1_1 import client as nova_client
except ImportError:
HAS_NOVA_CLIENT = False
print("failed=True msg='novaclient is required for this module'")
try:
from keystoneclient.v3 import client as keystone_client
except ImportError:
HAS_KEYSTONE_CLIENT = False
print("failed=True msg='keystoneclient is required for this module'")
class HeatFacts:
def __init__(self, module):
self._ksclient = None
self._hclient = None
self._nclient = None
self.module = module
self.name = module.params.get('name')
self.id = module.params.get('id')
self.address = module.params.get('address')
self.stacks = module.params.get('stacks')
self.group = module.params.get('group')
self.stack_list = None
if self.stacks and self.stacks != 'all':
self.stack_list = [ module.params.get('stacks') ]
def key_cleanup(self, value):
return 'heat_%s' % (re.sub('[^\w-]', '_', value).lower().lstrip('_'))
def object_to_dict(self, obj):
instance = {}
for key in dir(obj):
value = getattr(obj, key)
if key == 'manager':
next
if (isinstance(value, NON_CALLABLES) and not key.startswith('_')):
key = self.key_cleanup(key)
instance[key] = value
return instance
def object_list_to_dict(self, object_list, name):
dicts = {}
for obj in object_list:
dictn = self.object_to_dict(obj)
if name is not None and \
name != dictn['heat_stack_name']:
next
else:
dicts[dictn['heat_stack_name']] = dictn
return dicts
def get_instances(self):
instance_obj_list = []
instances_dict = {}
for stack_name in self.stack_list:
stack_obj = self.heat.stacks.get(stack_name)
stack_id = stack_obj.id
for res in self.heat.resources.list(stack_id):
if res.resource_type == 'OS::Nova::Server':
if self.id and self.id != res.physical_resource_id:
break
instance = self.object_to_dict(res)
server = self.nova.servers.get(res.physical_resource_id)
if self.name and self.name != server.name:
break
group_match = re.search("compute|controller|undercloud", server.name, flags=re.IGNORECASE)
if group_match:
instance['heat_group'] = group_match.group(0)
if self.group and self.group != instance['heat_group']:
break
instance.update(self.object_to_dict(server))
if self.address and self.address != instance['heat_networks']['ctlplane'][0]:
break
image = self.nova.images.get(instance['heat_image']['id'])
instance['heat_image'].update(image.metadata)
instance['heat_stack_name'] = stack_name
instances_dict[server.name] = instance
# this is specific to instances, hence not in object_list_to_dict()
if self.address is not None:
for iname, instance_dict in instances_dict.iteritems():
for netname, networks in \
instance_dict['heat_networks'].iteritems():
for address in networks:
if self.address == address:
instances_dict = {iname: instances_dict[iname]}
return instances_dict
def get_stacks(self):
stacks_dict = {}
stack_obj_list = []
stack_id = None
if self.stacks != 'all':
stack_id = self.stacks
try:
stack_obj_list.append(self.heat.stacks.get(stack_id))
except Exception, e:
self.module.fail_json(msg='%s' % e. message)
else:
try:
stack_obj_list = self.heat.stacks.list()
except Exception, e:
self.module.fail_json(msg='%s' % e. message)
stacks_dict = self.object_list_to_dict(stack_obj_list, stack_id)
for sname, sdict in stacks_dict.iteritems():
if 'heat_parameters' in sdict:
del sdict['heat_parameters']
return stacks_dict
def heat_facts(self, module):
changed = False
facts = {}
# get all stacks
facts['heat_stacks'] = self.get_stacks()
if self.stacks == 'all':
self.stack_list = facts['heat_stacks'].keys()
# get all instances
facts['heat_instances'] = self.get_instances()
module.exit_json(changed=changed, ansible_facts=facts)
@property
def keystone(self):
if self._ksclient is None:
self._ksclient = keystone_client.Client(
auth_url=self.module.params['auth_url'],
username=self.module.params['login_username'],
password=self.module.params['login_password'])
try:
self._ksclient.authenticate()
except exceptions.Unauthorized, e:
module.fail_json(msg="Invalid OpenStack Keystone credentials.: %s" %
e.message)
except exceptions.AuthorizationFailure, e:
module.fail_json(msg="Unable to authorize user: %s" % e.message)
return self._ksclient
@property
def heat(self):
if self._hclient is None:
ksclient = self.keystone
endpoint = ksclient.service_catalog.url_for(
service_type='orchestration', endpoint_type='publicURL')
self._hclient = heat_client.Client(
endpoint=endpoint,
token=ksclient.auth_token)
if self._hclient is None:
module.fail_json(msg="Failed to instantiate heat client. This "
"could mean that your credentials are wrong.")
return self._hclient
@property
def nova(self):
if self._nclient is None:
ksclient = self.keystone
endpoint = ksclient.service_catalog.url_for(
service_type='compute', endpoint_type='publicURL')
self._nclient = nova_client.Client(
bypass_url=endpoint,
username=None,
api_key=None,
auth_url=self.module.params['auth_url'],
auth_token=ksclient.auth_token)
if self._nclient is None:
module.fail_json(msg="Failed to instantiate nova client. This "
"could mean that your credentials are wrong.")
return self._nclient
def main():
if not HAS_HEAT_CLIENT:
module.fail_json(msg=
'The heat python client is required \
for this module')
if not HAS_KEYSTONE_CLIENT:
module.fail_json(msg=
'The keystone python client is required \
for this module')
if not HAS_NOVA_CLIENT:
module.fail_json(msg=
'The nova python client is required \
for this module')
argument_spec = dict(
id=dict(default=None),
name=dict(default=None),
address=dict(default=None),
stacks=dict(default=None),
group=dict(default=None),
login_username=dict(default='admin'),
login_password=dict(required=True),
login_tenant_name=dict(required='True'),
auth_url=dict(default='http://127.0.0.1:35357/v3/'),
region_name=dict(default=None),
image_id=dict(default=None),
flavor_id=dict(default=1),
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)
)
module = AnsibleModule(
argument_spec=argument_spec,
mutually_exclusive=[['id', 'name']]
)
manager = HeatFacts(module)
manager.heat_facts(module)
# import module snippets
from ansible.module_utils.basic import *
### invoke the module
main()

229
library/cloud/nova_rebuild Normal file
View File

@ -0,0 +1,229 @@
#!/usr/bin/python
#coding: utf-8 -*-
# (c) 2013, Benno Joy <benno@ansible.com>
# (c) 2013, John Dewey <john@dewey.ws>
# (c) 2014, Allison Randal <allison@lohutok.net>
#
# 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 os
try:
from novaclient.v1_1 import client as nova_client
from novaclient import exceptions
import time
except ImportError:
print("failed=True msg='novaclient is required for this module'")
DOCUMENTATION = '''
---
module: nova_rebuild
short_description: Rebuild VMs from OpenStack
description:
- Rebuild (re-image) 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
name:
description:
- Name of the instance to be rebuilt
default: None
instance_id:
description:
- Instance ID of the instance to be rebuilt
default: None
image_id:
description:
- The id of the image that has to be cloned
required: true
default: None
preserve_ephemeral:
description:
- Whether to preserve ephemeral storage on the instance
required: false
default: false
wait:
description:
- If the module should wait for the VM to be created.
required: false
default: 'yes'
wait_for:
description:
- Number of seconds the module should wait for the VM to get into active state
required: false
default: 600
requirements: ["novaclient"]
'''
EXAMPLES = '''
# Rebuilds an existing VM with a new image
- nova_rebuild:
login_username: admin
login_password: admin
login_tenant_name: admin
name: vm1
image_id: 4f905f38-e52a-43d2-b6ec-754a13ffb529
wait_for: 200
'''
# The following two openstack_ are copy paste from an upcoming
# core module "lib/ansible/module_utils/openstack.py" Once that's landed,
# these should be replaced with a line at the bottom of the file:
# from ansible.module_utils.openstack import *
def openstack_argument_spec():
# Consume standard OpenStack environment variables.
# This is mainly only useful for ad-hoc command line operation as
# in playbooks one would assume variables would be used appropriately
OS_AUTH_URL=os.environ.get('OS_AUTH_URL', 'http://127.0.0.1:35357/v2.0/')
OS_PASSWORD=os.environ.get('OS_PASSWORD', None)
OS_REGION_NAME=os.environ.get('OS_REGION_NAME', None)
OS_USERNAME=os.environ.get('OS_USERNAME', 'admin')
OS_TENANT_NAME=os.environ.get('OS_TENANT_NAME', OS_USERNAME)
spec = dict(
login_username = dict(default=OS_USERNAME),
auth_url = dict(default=OS_AUTH_URL),
region_name = dict(default=OS_REGION_NAME),
availability_zone = dict(default=None),
)
if OS_PASSWORD:
spec['login_password'] = dict(default=OS_PASSWORD)
else:
spec['login_password'] = dict(required=True)
if OS_TENANT_NAME:
spec['login_tenant_name'] = dict(default=OS_TENANT_NAME)
else:
spec['login_tenant_name'] = dict(required=True)
return spec
def openstack_find_nova_addresses(addresses, ext_tag, key_name=None):
ret = []
for (k, v) in addresses.iteritems():
if key_name and k == key_name:
ret.extend([addrs['addr'] for addrs in v])
else:
for interface_spec in v:
if 'OS-EXT-IPS:type' in interface_spec and interface_spec['OS-EXT-IPS:type'] == ext_tag:
ret.append(interface_spec['addr'])
return ret
def _rebuild_server(module, nova):
server = None
try:
if module.params.get('instance_id') is None:
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]
else:
server = nova.servers.get(module.params['instance_id'])
except Exception, e:
module.fail_json(msg = "Error in getting the server list: %s" % e.message)
if not server:
module.exit_json(changed = False, result = "not present")
bootargs = [server, module.params['image_id']]
bootkwargs = {
'preserve_ephemeral' : module.params['preserve_ephemeral'],
}
try:
server = nova.servers.rebuild(*bootargs, **bootkwargs)
server = nova.servers.get(server.id)
except Exception, e:
module.fail_json( msg = "Error in rebuilding 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':
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 = 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 rebuilding 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 rebuilding 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 main():
argument_spec = openstack_argument_spec()
argument_spec.update(dict(
name = dict(),
instance_id = dict(),
image_id = dict(required=True),
preserve_ephemeral = dict(default=False, choices=[True, False]),
wait = dict(default='yes', choices=['yes', 'no']),
wait_for = dict(default=600),
))
module = AnsibleModule(argument_spec=argument_spec)
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'],
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)
_rebuild_server(module, nova)
# this is magic, see lib/ansible/module_common.py
from ansible.module_utils.basic import *
main()

View File

@ -0,0 +1,17 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
- hosts: all
tasks:
- include: disable_os_collect_config.yml

View File

@ -0,0 +1,17 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
- hosts: all
tasks:
- include: refresh_config.yml

View File

@ -0,0 +1,27 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
---
# Stop and disable os-collect-config
#
# Run from the tripleo-ansible directory:
#
- name: "Disable os-collect-config service"
sudo: yes
service: name=os-collect-config enabled=no state=stopped
- name: "Reconfigure os-collect-config for local collector"
sudo: yes
copy:
src: files/os-collect-config.conf
dest: /etc/os-collect-config.conf

View File

@ -0,0 +1,4 @@
[DEFAULT]
collectors = ec2
collectors = local
command = os-refresh-config

View File

@ -0,0 +1,20 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
- include_vars: auth_vars.yml
- name: launch a nova instance
hosts: localhost
roles:
- { role: launch_compute, name: vm1, image_id: 4f905f38-e52a-43d2-b6ec-754a13ffb529, net_id: 34605f38-e52a-25d2-b6ec-754a13ffb723, flavor_id: 100, hostname: test1, group: uge_master }

View File

@ -0,0 +1,27 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
---
- name: "Create ssh host key backup directory"
sudo: yes
file:
path=/mnt/state/_ssh_host_keys
state=directory
owner=root
group=root
mode=0700
- name: "Preserve ssh host keys"
sudo: yes
action: shell cp -a /etc/ssh/ssh_host_* /mnt/state/_ssh_host_keys/

21
playbooks/rebuild.yml Normal file
View File

@ -0,0 +1,21 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
---
- name: "Call nova_rebuild"
nova_rebuild:
instance_id: "{{ instance_id }}"
image_id: "{{ rebuild_image_id }}"
preserve_ephemeral: true
delegate_to: localhost

View File

@ -0,0 +1,21 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
- include_vars: auth_vars.yml
- name: rebuild a nova instance
hosts: localhost
tasks:
roles:
- { role: rebuild_compute, name: vm1, image_id: 4f905f38-e52a-43d2-b6ec-754a13ffb529 }

View File

@ -0,0 +1,25 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
---
# Update the collect files to contain metadata obtained from Heat
#
- name: "Ensure heat local-data directory exists"
sudo: yes
file: path=/var/lib/os-collect-config/local-data state=directory
- name: "Write out metadata"
sudo: yes
template:
src: templates/host_metadata.json.j2
dest: /var/lib/os-collect-config/local-data/host_metadata.json

View File

@ -0,0 +1,24 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
---
- name: "Restore ssh host keys"
sudo: yes
action: shell mv /mnt/state/_ssh_host_keys/ssh_host_* /etc/ssh/
- name: "Remove ssh host key backup directory"
sudo: yes
file:
path=/mnt/state/_ssh_host_keys
state=absent

36
playbooks/start_cloud.yml Normal file
View File

@ -0,0 +1,36 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
---
- hosts: controller
name: Enable Overcloud Controller
sudo: yes
tasks:
- service: name={{ item }} enabled=yes state=started
with_items: overcloud_controller_services
- hosts: nova-compute
name: Enable Overcloud Compute
sudo: yes
tasks:
- name: "Run os-collect-config"
sudo: yes
command: os-collect-config --force --one
- service: name={{ item }} enabled=yes state=started
with_items: overcloud_compute_services
- hosts: undercloud
name: Enable Undercloud
sudo: yes
tasks:
- service: name={{ item }} enabled=yes state=started
with_items: undercloud_services

30
playbooks/stop_cloud.yml Normal file
View File

@ -0,0 +1,30 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
---
- hosts: controller
name: "Disable OpenStack Controller Services"
tasks:
- service: name={{ item }} enabled=no state=stopped
with_items: control-services
- hosts: nova-compute
name: "Disable OpenStack Compute"
tasks:
- service: name={{ item }} enabled=no state=stopped
with_items: compute-services
- hosts: undercloud
name: "Disable OpenStack Undercloud Services"
tasks:
- service: name={{ item }} enabled=no state=stopped
with_items: undercloud-services

View File

@ -0,0 +1,12 @@
{
"deployments": [],
"os-collect-config": {
"cfn": {
"stack_name": "{% stack_name %},
"metadata_url": "{% metadata_url %},
"access_key_id": "{% access_key_id %},
"secret_access_key": "{% sercret_access_key %}",
"path": "{% path %}"
}
}
}

View File

@ -0,0 +1 @@
{{ hostvars[inventory_hostname]['heat_metadata'] | to_nice_json }}

View File

@ -0,0 +1 @@
["/var/lib/os-collect-config/heat_local.json"]

View File

@ -0,0 +1,88 @@
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
#
# 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.
---
- hosts: all
tasks:
- include: disable_os_collect_config.yml
- hosts: undercloud
name: Disable Undercloud
tasks:
- service: name={{ item }} enabled=no state=stopped
with_items: undercloud_services
- hosts: nova-compute
name: Disable Overcloud Compute
sudo: yes
tasks:
- service: name={{ item }} enabled=no state=stopped
with_items: overcloud_compute_services
- hosts: controller
name: Disable Overcloud Controller
sudo: yes
tasks:
- service: name={{ item }} enabled=no state=stopped
with_items: overcloud_controller_services
- hosts: undercloud
name: Rebuild and Refresh Undercloud
tasks:
- include: preserve_ssh_host_keys.yml
- { include: rebuild.yml, instance_id: "{{ instance_id }}", rebuild_image_id: "{{ undercloud_rebuild_image_id }}" }
- local_action: wait_for port=22 timeout=600 host="{{ inventory_hostname }}" search_regex=OpenSSH delay=10
- include: refresh_config.yml
- hosts: nova-compute
name: Rebuild and Refresh Nova Compute
tasks:
- include: preserve_ssh_host_keys.yml
- { include: rebuild.yml, instance_id: "{{ instance_id }}", rebuild_image_id: "{{ nova_compute_rebuild_image_id }}" }
- local_action: wait_for port=22 timeout=600 host="{{ inventory_hostname }}" search_regex=OpenSSH delay=10
- include: refresh_config.yml
- hosts: controller
name: Rebuild and Refresh Controller
tasks:
- include: preserve_ssh_host_keys.yml
- { include: rebuild.yml, instance_id: "{{ instance_id }}", rebuild_image_id: "{{ controller_rebuild_image_id }}" }
- local_action: wait_for port=22 timeout=600 host="{{ inventory_hostname }}" search_regex=OpenSSH delay=10
- include: refresh_config.yml
- hosts: all
tasks:
- include: disable_os_collect_config.yml
- hosts: controller
tasks:
- name: "Work around apache2 starting up at boot w/o config..."
sudo: yes
service: name=apache2 enabled=no state=stopped
- name: "Run os-collect-config"
sudo: yes
command: os-collect-config --force --one
- hosts: controller
name: Enable Overcloud Controller
sudo: yes
tasks:
- service: name={{ item }} enabled=yes state=started
with_items: overcloud_controller_services
- hosts: nova-compute
name: Enable Overcloud Compute
sudo: yes
tasks:
- name: "Run os-collect-config"
sudo: yes
command: os-collect-config --force --one
- service: name={{ item }} enabled=yes state=started
with_items: overcloud_compute_services
- hosts: undercloud
name: Enable Undercloud
sudo: yes
tasks:
- service: name={{ item }} enabled=yes state=started
with_items: undercloud_services