commit 6f6e75f5496910724209929e32730f5927373585 Author: d34dh0r53 Date: Tue Aug 26 18:08:15 2014 -0500 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..2a79832bea --- /dev/null +++ b/.gitignore @@ -0,0 +1,49 @@ +# Override Files # +rpc_deployment/playbooks/lab_plays +rpc_deployment/vars/overrides/*.yml + +# Compiled source # +################### +*.com +*.class +*.dll +*.exe +*.o +*.so +*.pyc +build/ +dist/ + +# Packages # +############ +# it's better to unpack these files and commit the raw source +# git has its own built in compression methods +*.7z +*.dmg +*.gz +*.iso +*.jar +*.rar +*.tar +*.zip + +# Logs and databases # +###################### +*.log +*.sql +*.sqlite + +# OS generated files # +###################### +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +.idea +.tox +*.sublime* +*.egg-info +Icon? +ehthumbs.db +Thumbs.db diff --git a/Changelog.md b/Changelog.md new file mode 100644 index 0000000000..de1e79f65a --- /dev/null +++ b/Changelog.md @@ -0,0 +1,5 @@ +# Changelog + +## 9.0.0rc3 - 2014-08-xx + +- Added Changelog diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..e06d208186 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. + diff --git a/README.rst b/README.rst new file mode 100644 index 0000000000..340a4577bb --- /dev/null +++ b/README.rst @@ -0,0 +1,159 @@ +Ansible Openstack LXC Playbook +############################## +:date: 2013-09-05 09:51 +:tags: rackspace, lxc, openstack, cloud, ansible +:category: \*nix + +Deploy Openstack in Containers +============================== + +First Pass at Ansible playbook for LXC (openstack) Containers. +Make sure that you have the custom Ansible module installed on +your local system prior to running the playbook. + +Expect bugs and general unexplainable issues and the ever so popular +API change due to general messing about with bits. + + +Playbook Support +---------------- + +OpenStack: + * keystone + * glance-api + * glance-registry + * cinder-api + * cinder-scheduler + * cinder-volume + * nova-api + * nova-api-ec2 + * nova-api-metadata + * nova-api-os-compute + * nova-compute + * nova-conductor + * nova-scheduler + * heat-api + * heat-api-cfn + * heat-api-cloudwatch + * heat-engine + * horizon + * neutron-server + * neutron-dhcp-agent + * neutron-metadata-agent + * neutron-linuxbridge-agent + + +Infra: + * haproxy + * galara + * rabbitmq + * Deploy-Containers + * Destroy-Containers + * Clone-Container + * Archive-Container + * Archive-all-containers + * Deploy-archived-container + + +Assumptions +----------- + +This repo assumes that you have setup the host server that will be running the Openstack Infrastructure with three +bridged network devices named: ``br-mgmt``, ``br-vmnet``, ``br-ext``. Through these bridges will be used throughout +the Openstack infrastructure. + +The repo also relies on configuration files found in the `/etc` directory of this repo. +If you are running ansible from an "Un-privileged" host, you can place the contents of the /etc/ directory in your +home folder; this would be in a directory similar to `/home/kevin/rpc_deploy/`. Once you have the file in place, you +will have to input the details of your environment in the `rpc_user_config.yml` file; please see the file for how +this should look. After you have a bridged network and the files/directory in place, continue on to _`Base Usage`. + + +Base Usage +---------- + +All commands must be executed from the `rpc_deployment` directory. From this directory you will have access to all +of the playbooks, roles, and variables. It is recommended that you create an override file to contain any and all +variables that you wish to override for the deployment. While the override file is is not required it will make life +a bit easier. + +All of the variables that you may wish to update are in the `vars/` directory, however you should also be aware that +services will pull in base group variables as found in `inventory/group_vars`. + +All playbooks exist in the ``playbooks/`` directory and are grouped in different sub-directories. + +All of the keys, tokens, and passwords are in the `user_variables.yml` file. This file contains no +preset passwords. To setup your keys, passwords, and tokens you will need to either edit this file +manually or use the script ``pw-token-gen.py``. Example: + +.. code-block:: + + # Generate the tokens + scripts/pw-token-gen.py --file /etc/rpc_deploy/user_variables.yml + + +Example usage from the `rpc_deployment` directory in the `ansible-rpc-lxc` repository + +.. code-block:: bash + + # Run setup on all hosts: + ansible-playbook -e @vars/user_variables.yml playbooks/setup/host-setup.yml + + # Run infrastructure on all hosts + ansible-playbook -e @vars/user_variables.yml playbooks/infrastructure/infrastructure-setup.yml + + # Setup and configure openstack within your spec'd containers + ansible-playbook -e @vars/user_variables.yml playbooks/openstack/openstack-setup.yml + + +About Inventory +--------------- + +In ansible all things that ansible cares about are located in inventory. In the Rackspace Private Cloud all +inventory is dynamically generated using the previously mentioned configuration files. While this is a dynamically +generated inventory it is not 100% generated on every run. The inventory is saved in a file named, +`rpc_inventory.json` and is located in the directory where you've located your user configuration files. On every +run a backup of the inventory json file is created in both the current working directory as well as the location where +the user configuration files exist. The inventory json file is a living document and is intended to grow as the environment +scales in infrastructure. This means that the inventory file will be appended to as you add more nodes and or change the +container affinity from within the `rpc_user_config.yml` file. It is recommended that the base inventory file be backed +up to a safe location upon the completion of a deployment operation. While the dynamic inventory processor has guards in it +to ensure that the built inventory is not adversely effected by programatic operations this does not guard against user error +and or catastrophic failure. + + +Scaling +------- + +If you are scaling the environment using the dynamically generated inventory you should know that the inventory was designed to +generate new entries in inventory and not remove entries from inventory. These playbooks will build an environment to spec so if +container affinity is changed and or a node is added or removed from an environment the user configuration file will need to be +modified as well as the inventory json. For this reason it is recommended that should a physical node need replacing it should be +renamed the same as the previous one. This will make things easier when rebuilding the environment. Additionally if a container +is needing to be replaced it is better to simply remove the misbehaving container and rebuild it using the existing inventory. +The reasons that bursting up and down in openstack is less than idea when talking about the infrastructure nodes is outside the +scope of this document though its safe to say that the sheer volume of moving parts within openstack make this a precarious process. + + +Notes +----- + +* Library has an experimental `Keystone` module which adds ``keystone:`` support to ansible. +* Library has an experimental `Swift` module which adds ``swift:`` support to ansible. +* Library has an experimental `LXC` module which adds ``lxc:`` support to ansible. + +License +------- +Copyright 2014, Rackspace US, Inc. + +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. diff --git a/etc/README.rst b/etc/README.rst new file mode 100644 index 0000000000..0df3392488 --- /dev/null +++ b/etc/README.rst @@ -0,0 +1,149 @@ +Ansible Openstack LXC Configuration +=================================== +:date: 2013-09-05 09:51 +:tags: rackspace, lxc, rpc, openstack, cloud, ansible +:category: \*nix + +This directory contains the files needed to make the rpc_deployment process work. +The inventory is generated from a user configuration file named ``rpc_user_config.yml``. +To load inventory you MUST copy the directory ``rpc_deploy`` to either ``$HOME/`` or ``/etc/``. +With this folder in place, you will need to enter the folder and edit the file ``rpc_user_config.yml``. +The file will contain all of the IP addresses/hostnames that your infrastructure will exist on +as well as a CIDR that your containers will have IP addresses assigned from. This allows for easy +scaling as new nodes and or affinity for containers is all set within this file. + +Please see the ``rpc_user_config.yml`` file in the provided ``/etc`` directory for more details on how +that file is setup. + +If you need some assistance defining the CIDR for a given ip address range check out http://www.ipaddressguide.com/cidr + + + +Words on rpc_user_config.yml +############################ + +While the ``rpc_user_config.yml`` file is noted fairly heavily with examples and information regarding the options, here's some more information on what the file consists of and how to use it. + + +Global options +-------------- + +The user configuration file has three globally available options. These options allow you to set the CIDR for all of your containers IP addresses, and a list of used IP addresses that you may not want the inventory system to collide with, global overrides which are added to inventory outside of "group_vars" and "var_files" files. + + +---- + +Global Options: + * cidr: + * used_ips: + * global_overrides: + +Here's the syntax for ``cidr``. + +.. code-block:: yaml + + cidr: / + + +---- + +To tell inventory not to attempt to consume IP addresses which may or may not exist within the defined cidr write all known IP addresses that are already consumed as a list in yaml format. + + +Heres the ``used_ips`` syntax + +.. code-block:: yaml + + used_ips: + - 10.0.0.250 + - 10.0.0.251 + - 10.0.0.252 + - 10.0.0.253 + + +---- + +If you want to specify specific globally available options and do not want to place them in ``var_files`` or within the ``group_vars/all.yml`` file you can set them in a key = value par within the ``global_overrides`` hash. + +Here's the ``global_overrides`` syntax + + +.. code-block:: yaml + + global_overrides: + debug: True + git_install_branch: master + + + +Predefined host groups +---------------------- + +The user configuration file has 4 defined groups which have mapping found within the ``rpc_environment.yml`` file. + +The predefined groups are: + * infra_hosts: + * compute_hosts: + * storage_hosts: + * log_hosts: + + +Any host specified within these groups will have containers built within them automatically. The containers that will be build are all mapped out within the rpc_environment.json file. + +When specifying hosts inside of any of the known groups the syntax is as follows: + +.. code-block:: yaml + + infra_hosts: + infra_host1: + ip: 10.0.0.1 + + +With this the top key is the host name and ip is used to set the known IP address of the host name. Even if you have the host names set within your environment using either the ``hosts`` file or a resolver you must specify the "ip". + +If you want to use a host that is not in a predefined group and is used is some custom out of band Ansible play you can add a top level key for the host type with the host name and "ip" key. The syntax is the exact same as the predefined host groups. + + +Adding options to containers within targeted hosts +-------------------------------------------------- + +Within the host variables options can be added that will append to the ``host_vars`` of a given set of containers. This allows you to add "special" configuration to containers on a targeted host which may come in handy when scaling out or planning a deployment of services. To add these options to all containers within the host simply add ``container_vars`` under the host name and use ``key: value`` pairs for all of the desired options. All ``key: value`` pairs will be set as ``host_vars`` on all containers found under host name. + +Here is an example of turning debug mode on all containers on infra1 + + +.. code-block:: yaml + + infra_hosts: + infra1: + ip: 10.0.0.10 + container_vars: + debug: True + infra2: + ... + + +In this example you can see that we are setting ``container_vars`` under the host name ``infra1`` and that debug was set to True. + + +Limiting the container types: + When developing the inventory it may be useful to further limit the containers that will have access to the provided options. In this case you use the option ``limit_container_types`` followed by the type of container you with to limit the options to. When using the ``limit_container_types`` option the inventory script will perform a string match on the container name and if a match is found, even if it's a partial match, the options will be appended to the container. + + +Here is an example of adding cinder_backends to containers on a host named cinder1 under the ``storage_hosts`` group. The options will be limited to containers matching the type "cinder_volume". + + +.. code-block:: yaml + + storage_hosts: + cinder1: + ip: 10.0.0.10 + container_vars: + cinder_backends: + limit_container_types: cinder_volume + lvm: + volume_group: cinder-volumes + driver: cinder.volume.drivers.lvm.LVMISCSIDriver + backend_name: LVM_iSCSI + cinder2: + ... diff --git a/etc/network/README.rst b/etc/network/README.rst new file mode 100644 index 0000000000..439509859d --- /dev/null +++ b/etc/network/README.rst @@ -0,0 +1,22 @@ +Ansible Openstack Networking +============================ +:date: 2013-09-05 09:51 +:tags: rackspace, rpc, openstack, cloud, ansible, networking, bond, interfaces +:category: \*nix + +This directory contains some base interface files that will allow you to see what +the networking setup might be like in your environment. Three **basic** example +configurations have been provided in the in ``interfaces.d`` directory. These +files should cover most cases in terms of host setup though should **NEVER** be +taken literally. These files should only serve as an example and **WILL** need to +be edited to fit your unique network needs. All provided files have different configurations +within them to suit very different use cases. It should also be noted that UDEV rules may +change your network setup between boxes and may require tweaking. If you have questions on +how debian networking is built out please review the following documentation. + + +On-line Resources: + * Ubuntu Bonding: https://help.ubuntu.com/community/UbuntuBonding + * Ubuntu Networking: https://help.ubuntu.com/14.04/serverguide/network-configuration.html + * Debian Bonding: https://wiki.debian.org/Bonding + * Debian Networking: https://wiki.debian.org/NetworkConfiguration diff --git a/etc/network/interfaces b/etc/network/interfaces new file mode 100644 index 0000000000..41d0d2b485 --- /dev/null +++ b/etc/network/interfaces @@ -0,0 +1,7 @@ +# Used by ifup(8) and ifdown(8). See the interfaces(5) manpage or +# /usr/share/doc/ifupdown/examples for more information. +# The loopback network interface +auto lo +iface lo inet loopback + +source /etc/network/interfaces.d/*.cfg diff --git a/etc/network/interfaces.d/rpc_interface.cfg.example b/etc/network/interfaces.d/rpc_interface.cfg.example new file mode 100644 index 0000000000..8639121d10 --- /dev/null +++ b/etc/network/interfaces.d/rpc_interface.cfg.example @@ -0,0 +1,132 @@ +#EXAMPLE INTERFACE FILE +# +#1293 - HOST_NET (Ignore This. It's the native VLAN.) +#2176 - CONTAINER_NET +#1998 - OVERLAY_NET +#2144 - STORAGE_NET +#2146 - GATEWAY_NET (VM Provider Network. Ignore this. Openstack will tag for us.) + +## Physical interface, could be bond. This only needs to be set once for the physical device +auto eth0 +iface eth0 inet manual + bond-master bond0 + bond-primary eth0 + +auto eth1 +iface eth1 inet manual + bond-master bond1 + bond-primary eth1 + +auto eth2 +iface eth2 inet manual + bond-master bond0 + +auto eth3 +iface eth3 inet manual + bond-master bond1 + +auto eth4 +iface eth4 inet manual + + +## Create a bonded interface. Note that the "bond-slaves" is set to none. This is because the +# bond-master has already been set in the raw interfaces for the new bond0. +auto bond0 +iface bond0 inet static + bond-slaves none + bond-mode active-backup + bond-miimon 100 + bond-downdelay 200 + bond-updelay 200 + address 10.240.0.100 + netmask 255.255.252.0 + gateway 10.240.0.1 + dns-nameservers 69.20.0.164 69.20.0.196 + +auto bond1 +iface bond1 inet manual + bond-slaves none + bond-mode active-backup + bond-miimon 100 + bond-downdelay 250 + bond-updelay 250 + + +## Vlan tagged interface, this should be physical interface along with the vlan tag +# The vlan tag number should reflect your already setup vlans. + +#STORAGE_NET +iface bond0.2144 inet manual + vlan-raw-device bond0 + +#CONTAINER_NET +iface bond0.2176 inet manual + vlan-raw-device bond0 + +#OVERLAY_NET +iface bond1.1998 inet manual + vlan-raw-device bond1 + + +## Required network bridges; br-vlan, br-vxlan, br-mgmt. +# Bridge for management network +auto br-mgmt +iface br-mgmt inet static + bridge_stp off + bridge_waitport 0 + bridge_fd 0 + # Notice the bridge port is the vlan tagged interface + bridge_ports bond0.2176 + address 172.29.236.100 + netmask 255.255.252.0 + dns-nameservers 69.20.0.164 69.20.0.196 + + +# Bridge for vxlan network +# Only the COMPUTE nodes will have an IP on this bridge! +# When used by infra nodes, IPs exist in the containers and inet should be set to manual. +auto br-vxlan +iface br-vxlan inet static + bridge_stp off + bridge_waitport 0 + bridge_fd 0 + bridge_ports bond1.1998 + address 172.29.240.100 + netmask 255.255.252.0 + + +# Bridge for vlan network +auto br-vlan +iface br-vlan inet static + bridge_stp off + bridge_waitport 0 + bridge_fd 0 + # Notice this bridge port is an Untagged host interface + bridge_ports bond1 + + +# Bridge for storage network +# Only the COMPUTE nodes will have an IP on this bridge! +# When used by infra nodes, IPs exist in the containers and inet should be set to manual. +auto br-storage +iface br-storage inet static + bridge_stp off + bridge_waitport 0 + bridge_fd 0 + bridge_ports bond0.2144 + address 172.29.244.100 + netmask 255.255.252.0 + + +# Bridge for servicenet network +# ALL nodes will have an IP on this bridge. If fact, it's the same IP. +# !! DO NOT PUT A PHYSICAL INTERFACE IN THIS BRIDGE ON THE HOST !! +# Will ue an iptables MASQUERADE rule to NAT traffic +auto br-snet +iface br-snet inet static + bridge_stp off + bridge_waitport 0 + bridge_fd 0 + # Notice there is NO physical interface in this bridge! + address 172.29.248.1 + netmask 255.255.252.0 diff --git a/etc/rpc_deploy/rpc_environment.yml b/etc/rpc_deploy/rpc_environment.yml new file mode 100644 index 0000000000..87e1c73b6c --- /dev/null +++ b/etc/rpc_deploy/rpc_environment.yml @@ -0,0 +1,282 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +component_skel: + cinder_api: + belongs_to: + - cinder_all + cinder_scheduler: + belongs_to: + - cinder_all + cinder_volume: + belongs_to: + - cinder_all + elasticsearch: + belongs_to: + - elasticsearch_all + galera: + belongs_to: + - galera_all + glance_api: + belongs_to: + - glance_all + glance_registry: + belongs_to: + - glance_all + heat_api: + belongs_to: + - heat_all + heat_api_cfn: + belongs_to: + - heat_all + heat_api_cloudwatch: + belongs_to: + - heat_all + heat_engine: + belongs_to: + - heat_all + horizon: + belongs_to: + - horizon_all + keystone: + belongs_to: + - keystone_all + kibana: + belongs_to: + - kibana_all + logstash: + belongs_to: + - logstash_all + memcached: + belongs_to: + - memcached_all + neutron_agent: + belongs_to: + - neutron_all + neutron_dhcp_agent: + belongs_to: + - neutron_all + neutron_linuxbridge_agent: + belongs_to: + - neutron_all + neutron_metering_agent: + belongs_to: + - neutron_all + neutron_l3_agent: + belongs_to: + - neutron_all + neutron_metadata_agent: + belongs_to: + - neutron_all + neutron_server: + belongs_to: + - neutron_all + nova_api_ec2: + belongs_to: + - nova_all + nova_api_metadata: + belongs_to: + - nova_all + nova_api_os_compute: + belongs_to: + - nova_all + nova_compute: + belongs_to: + - nova_all + nova_conductor: + belongs_to: + - nova_all + nova_scheduler: + belongs_to: + - nova_all + nova_spice_console: + belongs_to: + - nova_all + rabbit: + belongs_to: + - rabbit_all + rsyslog: + belongs_to: + - rsyslog_all + utility: + belongs_to: + - utility_all +container_skel: + cinder_api_container: + belongs_to: + - infra_containers + contains: + - cinder_api + cinder_volumes_container: + belongs_to: + - storage_containers + contains: + - cinder_scheduler + - cinder_volume + elasticsearch_container: + belongs_to: + - log_containers + contains: + - elasticsearch + galera_container: + belongs_to: + - infra_containers + contains: + - galera + glance_container: + belongs_to: + - infra_containers + contains: + - glance_api + - glance_registry + heat_apis_container: + belongs_to: + - infra_containers + contains: + - heat_api_cloudwatch + - heat_api_cfn + - heat_api + heat_engine_container: + belongs_to: + - infra_containers + contains: + - heat_engine + horizon_container: + belongs_to: + - infra_containers + contains: + - horizon + keystone_container: + belongs_to: + - infra_containers + contains: + - keystone + kibana_container: + belongs_to: + - log_containers + contains: + - kibana + logstash_container: + belongs_to: + - log_containers + contains: + - logstash + memcached_container: + belongs_to: + - infra_containers + contains: + - memcached + neutron_agents_container: + belongs_to: + - network_containers + contains: + - neutron_agent + - neutron_metadata_agent + - neutron_metering_agent + - neutron_linuxbridge_agent + - neutron_l3_agent + - neutron_dhcp_agent + neutron_server_container: + belongs_to: + - network_containers + contains: + - neutron_server + nova_api_ec2_container: + belongs_to: + - infra_containers + contains: + - nova_api_ec2 + nova_api_metadata_container: + belongs_to: + - infra_containers + contains: + - nova_api_metadata + nova_api_os_compute_container: + belongs_to: + - infra_containers + contains: + - nova_api_os_compute + nova_compute_container: + is_metal: true + belongs_to: + - compute_containers + contains: + - neutron_linuxbridge_agent + - nova_compute + nova_conductor_container: + belongs_to: + - infra_containers + contains: + - nova_conductor + nova_scheduler_container: + belongs_to: + - infra_containers + contains: + - nova_scheduler + nova_spice_console_container: + belongs_to: + - infra_containers + contains: + - nova_spice_console + rabbit_mq_container: + belongs_to: + - infra_containers + contains: + - rabbit + rsyslog_container: + belongs_to: + - infra_containers + - compute_containers + - storage_containers + - log_containers + - network_containers + contains: + - rsyslog + utility_container: + belongs_to: + - infra_containers + contains: + - utility +physical_skel: + network_containers: + belongs_to: + - all_containers + network_hosts: + belongs_to: + - hosts + compute_containers: + belongs_to: + - all_containers + compute_hosts: + belongs_to: + - hosts + infra_containers: + belongs_to: + - all_containers + infra_hosts: + belongs_to: + - hosts + log_containers: + belongs_to: + - all_containers + log_hosts: + belongs_to: + - hosts + storage_containers: + belongs_to: + - all_containers + storage_hosts: + belongs_to: + - hosts diff --git a/etc/rpc_deploy/rpc_user_config.yml b/etc/rpc_deploy/rpc_user_config.yml new file mode 100644 index 0000000000..c66b30c6e8 --- /dev/null +++ b/etc/rpc_deploy/rpc_user_config.yml @@ -0,0 +1,159 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# This is the md5 of the environment file +# this will ensure consistency when deploying. +environment_version: 5e7155d022462c5a82384c1b2ed8b946 + +# User defined CIDR used for containers +# Global cidr/s used for everything. +cidr_networks: + # Cidr used in the Management network + container: 172.29.236.0/22 + # Cidr used in the Service network + snet: 172.29.248.0/22 + # Cidr used in the VM network + tunnel: 172.29.240.0/22 + # Cidr used in the Storage network + storage: 172.29.244.0/22 + +# User defined list of consumed IP addresses that may intersect +# with the provided CIDR. +used_ips: + - 172.29.236.1,172.29.236.50 + - 172.29.244.1,172.29.244.50 + +# As a user you can define anything that you may wish to "globally" +# override from within the rpc_deploy configuration file. Anything +# specified here will take precedence over anything else any where. +global_overrides: + # Internal Management vip address + internal_lb_vip_address: 172.29.236.1 + # External DMZ VIP address + external_lb_vip_address: 192.168.1.1 + # Bridged interface to use with tunnel type networks + tunnel_bridge: "br-vxlan" + # Bridged interface to build containers with + management_bridge: "br-mgmt" + # Define your Add on container networks. + # group_binds: bind a provided network to a particular group + # container_bridge: instructs inventory where a bridge is plugged + # into on the host side of a veth pair + # container_interface: interface name within a container + # ip_from_q: name of a cidr to pull an IP address from + # type: Networks must have a type. types are: ["raw", "vxlan", "flat", "vlan"] + # range: Optional value used in "vxlan" and "vlan" type networks + # net_name: Optional value used in mapping network names used in neutron ml2 + # You must have a management network. + provider_networks: + - network: + group_binds: + - all_containers + - hosts + type: "raw" + container_bridge: "br-mgmt" + container_interface: "eth1" + ip_from_q: "container" + - network: + group_binds: + - glance_api + - cinder_api + - cinder_volume + - nova_compute + type: "raw" + container_bridge: "br-storage" + container_interface: "eth2" + ip_from_q: "storage" + - network: + group_binds: + - glance_api + - nova_compute + - neutron_linuxbridge_agent + type: "raw" + container_bridge: "br-snet" + container_interface: "eth3" + ip_from_q: "snet" + - network: + group_binds: + - neutron_linuxbridge_agent + container_bridge: "br-vxlan" + container_interface: "eth10" + ip_from_q: "tunnel" + type: "vxlan" + range: "1:1000" + net_name: "vxlan" + - network: + group_binds: + - neutron_linuxbridge_agent + container_bridge: "br-vlan" + container_interface: "eth11" + type: "flat" + net_name: "vlan" + - network: + group_binds: + - neutron_linuxbridge_agent + container_bridge: "br-vlan" + container_interface: "eth11" + type: "vlan" + range: "1:1" + net_name: "vlan" + # Name of load balancer + lb_name: lb_name_in_core + +# User defined Infrastructure Hosts, this should be a required group +infra_hosts: + infra1: + ip: 172.29.236.100 + infra2: + ip: 172.29.236.101 + infra3: + ip: 172.29.236.102 + +# User defined Compute Hosts, this should be a required group +compute_hosts: + compute1: + ip: 172.29.236.103 + +# User defined Storage Hosts, this should be a required group +storage_hosts: + cinder1: + ip: 172.29.236.104 + # "container_vars" can be set outside of all other options as + # host specific optional variables. + container_vars: + # In this example we are defining what cinder volumes are + # on a given host. + cinder_backends: + # if the "limit_container_types" argument is set, within + # the top level key of the provided option the inventory + # process will perform a string match on the container name with + # the value found within the "limit_container_types" argument. + # If any part of the string found within the container + # name the options are appended as host_vars inside of inventory. + limit_container_types: cinder_volume + lvm: + volume_group: cinder-volumes + driver: cinder.volume.drivers.lvm.LVMISCSIDriver + backend_name: LVM_iSCSI + +# User defined Logging Hosts, this should be a required group +log_hosts: + logger1: + ip: 172.29.236.107 + +# User defined Networking Hosts, this should be a required group +network_hosts: + network1: + ip: 172.29.236.108 diff --git a/etc/rpc_deploy/rpc_user_config.yml.example b/etc/rpc_deploy/rpc_user_config.yml.example new file mode 100644 index 0000000000..c0e3c54a5f --- /dev/null +++ b/etc/rpc_deploy/rpc_user_config.yml.example @@ -0,0 +1,220 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# This is the md5 of the environment file +# this will ensure consistency when deploying. +environment_version: 5e7155d022462c5a82384c1b2ed8b946 + +# User defined CIDR used for containers +# Global cidr/s used for everything. +cidr_networks: + # Cidr used in the Management network + container: 172.29.236.0/22 + # Cidr used in the Service network + snet: 172.29.248.0/22 + # Cidr used in the VM network + tunnel: 172.29.240.0/22 + # Cidr used in the Storage network + storage: 172.29.244.0/22 + +# User defined list of consumed IP addresses that may intersect +# with the provided CIDR. +used_ips: + - 172.29.236.1,172.29.236.50 + - 172.29.244.1,172.29.244.50 + +# As a user you can define anything that you may wish to "globally" +# override from within the rpc_deploy configuration file. Anything +# specified here will take precedence over anything else any where. +global_overrides: + # Internal Management vip address + internal_lb_vip_address: 172.29.236.1 + # External DMZ VIP address + external_lb_vip_address: 192.168.1.1 + # Bridged interface to use with tunnel type networks + tunnel_bridge: "br-vxlan" + # Bridged interface to build containers with + management_bridge: "br-mgmt" + # Define your Add on container networks. + # group_binds: bind a provided network to a particular group + # container_bridge: instructs inventory where a bridge is plugged + # into on the host side of a veth pair + # container_interface: interface name within a container + # ip_from_q: name of a cidr to pull an IP address from + # type: Networks must have a type. types are: ["raw", "vxlan", "flat", "vlan"] + # range: Optional value used in "vxlan" and "vlan" type networks + # net_name: Optional value used in mapping network names used in neutron ml2 + # You must have a management network. + provider_networks: + - network: + group_binds: + - all_containers + - hosts + type: "raw" + container_bridge: "br-mgmt" + container_interface: "eth1" + ip_from_q: "container" + - network: + group_binds: + - glance_api + - cinder_api + - cinder_volume + - nova_compute + type: "raw" + container_bridge: "br-storage" + container_interface: "eth2" + ip_from_q: "storage" + - network: + group_binds: + - glance_api + - nova_compute + - neutron_linuxbridge_agent + type: "raw" + container_bridge: "br-snet" + container_interface: "eth3" + ip_from_q: "snet" + - network: + group_binds: + - neutron_linuxbridge_agent + container_bridge: "br-vxlan" + container_interface: "eth10" + ip_from_q: "tunnel" + type: "vxlan" + range: "1:1000" + net_name: "vxlan" + - network: + group_binds: + - neutron_linuxbridge_agent + container_bridge: "br-vlan" + container_interface: "eth11" + type: "flat" + net_name: "vlan" + - network: + group_binds: + - neutron_linuxbridge_agent + container_bridge: "br-vlan" + container_interface: "eth11" + type: "vlan" + range: "1:1" + net_name: "vlan" + # Name of load balancer + lb_name: lb_name_in_core + # Other options you may want + debug: True + ### Cinder default volume type option + # # This can be set to use a specific volume type. This is + # # an optional variable because you may have different volume + # # types on different hosts named different things. For this + # # Reason if you choose to set this variable please set it + # # to the name of one of your setup volume types + # cinder_default_volume_type: lvm + ### Cinder default volume type option + +# User defined Infrastructure Hosts, this should be a required group +infra_hosts: + infra1: + ip: 172.29.236.100 + infra2: + ip: 172.29.236.101 + infra3: + ip: 172.29.236.102 + +# User defined Compute Hosts, this should be a required group +compute_hosts: + compute1: + ip: 172.29.236.103 + host_vars: + host_networks: + - { type: raw, device_name: eth0, bond_master: bond0, bond_primary: true } + - { type: raw, device_name: eth4, bond_master: bond0, bond_primary: false } + - { type: vlan_tagged, device_name: bond0, tagged_device_name: bond0.2176 } + - { type: vlan_tagged, device_name: bond0, tagged_device_name: bond1.1998 } + - { type: bonded, device_name: bond0 } + - { type: bridged, device_name: br-mgmt, bridge_ports: ["bond0.2176"], address: "172.29.236.103", netmask: "255.255.255.0", gateway: "172.29.236.1", dns_nameservers: ["69.20.0.164", "69.20.0.196"] } + - { type: bridged, device_name: br-vxlan, bridge_ports: ["bond1.1998"], address: "172.29.240.103", netmask: "255.255.255.0" } + - { type: bridged, device_name: br-vlan, bridge_ports: ["bond1"] } + +# User defined Storage Hosts, this should be a required group +storage_hosts: + cinder1: + ip: 172.29.236.104 + # "container_vars" can be set outside of all other options as + # host specific optional variables. + container_vars: + # In this example we are defining what cinder volumes are + # on a given host. + cinder_backends: + # if the "limit_container_types" argument is set, within + # the top level key of the provided option the inventory + # process will perform a string match on the container name with + # the value found within the "limit_container_types" argument. + # If any part of the string found within the container + # name the options are appended as host_vars inside of inventory. + limit_container_types: cinder_volume + lvm: + volume_group: cinder-volumes + driver: cinder.volume.drivers.lvm.LVMISCSIDriver + backend_name: LVM_iSCSI + cinder2: + ip: 172.29.236.105 + container_vars: + cinder_backends: + limit_container_types: cinder_volume + lvm_ssd: + volume_group: cinder-volumes + driver: cinder.volume.drivers.lvm.LVMISCSIDriver + backend_name: LVM_SSD_iSCSI + cinder3: + ip: 172.29.236.106 + container_vars: + cinder_backends: + limit_container_type: cinder_volume + netapp: + netapp_storage_family: ontap_7mode + netapp_storage_protocol: iscsi + netapp_server_hostname: "{{ cinder_netapp_hostname }}" + netapp_server_port: 80 + netapp_login: "{{ cinder_netapp_username }}" + netapp_password: "{{ cinder_netapp_password }}" + driver: cinder.volume.drivers.netapp.common.NetAppDriver + backend_name: NETAPP_iSCSI + +# User defined Logging Hosts, this should be a required group +log_hosts: + logger1: + ip: 172.29.236.107 + +# User defined Networking Hosts, this should be a required group +network_hosts: + network1: + ip: 172.29.236.108 + host_vars: + host_networks: + - { type: raw, device_name: eth0, bond_master: bond0, bond_primary: true } + - { type: raw, device_name: eth4, bond_master: bond0, bond_primary: false } + - { type: vlan_tagged, device_name: bond0, tagged_device_name: bond0.2176 } + - { type: vlan_tagged, device_name: bond0, tagged_device_name: bond1.1998 } + - { type: bonded, device_name: bond0 } + - { type: bridged, device_name: br-mgmt, bridge_ports: ["bond0.2176"], address: "172.29.236.108", netmask: "255.255.255.0", gateway: "172.29.236.1", dns_nameservers: ["69.20.0.164", "69.20.0.196"] } + - { type: bridged, device_name: br-vxlan, bridge_ports: ["bond1.1998"], address: "172.29.240.108", netmask: "255.255.255.0" } + - { type: bridged, device_name: br-vlan, bridge_ports: ["bond1"] } + +# Other hosts can be added whenever needed. Note that containers will not be +# assigned to "other" hosts by default. If you would like to have containers +# assigned to hosts that are outside of the predefined groups, you will need to +# make an edit to the rpc_environment.yml file. +# haproxy_hosts: +# haproxy1: +# ip: 10.0.0.12 diff --git a/etc/rpc_deploy/user_variables.yml b/etc/rpc_deploy/user_variables.yml new file mode 100644 index 0000000000..28e76659f3 --- /dev/null +++ b/etc/rpc_deploy/user_variables.yml @@ -0,0 +1,136 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +## Rackspace Cloud Details +# UK accounts: https://lon.identity.api.rackspacecloud.com/v2.0 +rackspace_cloud_auth_url: https://identity.api.rackspacecloud.com/v2.0 +rackspace_cloud_tenant_id: SomeTenantID +rackspace_cloud_username: SomeUserName +rackspace_cloud_password: SomeUsersPassword +rackspace_cloud_api_key: SomeAPIKey + + +## Rabbit Options +rabbitmq_password: +rabbitmq_cookie_token: + + +## Tokens +memcached_encryption_key: + + +## Container default user +container_openstack_password: + + +## Galera Options +mysql_root_password: +mysql_debian_sys_maint_password: + + +## Keystone Options +keystone_container_mysql_password: +keystone_auth_admin_token: +keystone_auth_admin_password: +keystone_service_password: + + +## Cinder Options +cinder_container_mysql_password: +cinder_service_password: +cinder_v2_service_password: + + +## Glance Options +glance_default_store: file +glance_container_mysql_password: +glance_service_password: +glance_swift_store_auth_address: "{{ rackspace_cloud_auth_url }}" +glance_swift_store_user: "{{ rackspace_cloud_tenant_id }}:{{ rackspace_cloud_username }}" +glance_swift_store_key: "{{ rackspace_cloud_password }}" +glance_swift_store_container: SomeContainerName +glance_swift_store_region: SomeRegion +glance_swift_enable_snet: True + + +## Heat Options +heat_stack_domain_admin_password: +heat_container_mysql_password: +### THE HEAT AUTH KEY NEEDS TO BE 32 CHARACTERS LONG ## +heat_auth_encryption_key: +### THE HEAT AUTH KEY NEEDS TO BE 32 CHARACTERS LONG ## +heat_service_password: +heat_cfn_service_password: + + +## Horizon Options +horizon_container_mysql_password: + + +## MaaS Options +# Set maas_auth_method to 'token' to use maas_auth_token/maas_api_url +# instead of maas_username/maas_api_key +maas_auth_method: password +maas_auth_url: "{{ rackspace_cloud_auth_url }}" +maas_username: "{{ rackspace_cloud_username }}" +maas_api_key: "{{ rackspace_cloud_api_key }}" +maas_auth_token: some_token +maas_api_url: https://monitoring.api.rackspacecloud.com/v1.0/{{ rackspace_cloud_tenant_id }} +maas_notification_plan: npTechnicalContactsEmail +maas_agent_token: some_token +maas_target_alias: public0_v4 +maas_scheme: https +# Override scheme for specific service remote monitor by specifying here: E.g. +# maas_nova_scheme: http +maas_keystone_user: maas +maas_keystone_password: +# Check this number of times before registering state change +maas_alarm_local_consecutive_count: 3 +maas_alarm_remote_consecutive_count: 1 +# Period and timeout times (seconds) for a check +# Timeout must be less than period +maas_check_period: 60 +maas_check_timeout: 30 +maas_monitoring_zones: + - mzdfw + - mziad + - mzord + - mzlon + - mzhkg +maas_repo_version: v9.0.0 + + +## Neutron Options +neutron_container_mysql_password: +neutron_service_password: + + +## Nova Options +nova_virt_type: qemu +nova_container_mysql_password: +nova_metadata_proxy_secret: +nova_ec2_service_password: +nova_service_password: +nova_v3_service_password: +nova_s3_service_password: + + +## RPC Support +rpc_support_holland_password: +# rpc_support_holland_branch: defaults to release tag: v1.0.10 + +## Kibana Options +kibana_password: + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000..c26242813e --- /dev/null +++ b/requirements.txt @@ -0,0 +1,13 @@ +Jinja2==2.7.3 +MarkupSafe==0.23 +PyYAML==3.11 +ansible==1.6.6 +click==2.5 +colorize==1.0.2 +ecdsa==0.11 +netaddr==0.7.12 +paramiko==1.14.0 +prettytable==0.7.2 +pycrypto==2.6.1 +wsgiref==0.1.2 +pexpect==3.3 diff --git a/rpc_deployment/ansible.cfg b/rpc_deployment/ansible.cfg new file mode 100644 index 0000000000..383edbfa2a --- /dev/null +++ b/rpc_deployment/ansible.cfg @@ -0,0 +1,8 @@ +[defaults] +gathering = smart +hostfile = inventory +host_key_checking = False + + +[ssh_connection] +pipelining = True diff --git a/rpc_deployment/handlers/services.yml b/rpc_deployment/handlers/services.yml new file mode 100644 index 0000000000..ad37f8679f --- /dev/null +++ b/rpc_deployment/handlers/services.yml @@ -0,0 +1,24 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Restart os service + service: name={{ item }} state=restarted pattern={{ item }} + register: service_restart + failed_when: "'msg' in service_restart and 'FAIL' in service_restart.msg|upper" + with_items: service_names + notify: Ensure os service running + +- name: Ensure os service running + service: name={{ program_name }} state=started pattern={{ program_name }} diff --git a/rpc_deployment/inventory/dynamic_inventory.py b/rpc_deployment/inventory/dynamic_inventory.py new file mode 100755 index 0000000000..58cbdd7442 --- /dev/null +++ b/rpc_deployment/inventory/dynamic_inventory.py @@ -0,0 +1,797 @@ +#!/usr/bin/env python +# Copyright 2014, Rackspace US, Inc. +# +# 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. +# +# (c) 2014, Kevin Carter + +import argparse +import datetime +import hashlib +import json +import os +import Queue +import random +import tarfile +import uuid + +try: + import yaml +except ImportError: + print('Missing Dependency, "PyYAML"') + +try: + import netaddr +except ImportError: + print('Missing Dependency, "netaddr"') + +USED_IPS = [] +INVENTORY_SKEL = { + '_meta': { + 'hostvars': {} + } +} + +# This is a list of items that all hosts should have at all times. +# Any new item added to inventory that will used as a default argument in the +# inventory setup should be added to this list. +REQUIRED_HOSTVARS = [ + 'is_metal', + 'ansible_ssh_host', + 'container_address', + 'container_name', + 'physical_host', + 'component' +] + + +def args(): + """Setup argument Parsing.""" + parser = argparse.ArgumentParser( + usage='%(prog)s', + description='Rackspace Openstack, Inventory Generator', + epilog='Inventory Generator Licensed "Apache 2.0"') + + parser.add_argument( + '--file', + help='User defined configuration file', + required=False, + default=None + ) + parser.add_argument( + '--list', + help='List all entries', + action='store_true' + ) + + return vars(parser.parse_args()) + + +def get_ip_address(name, ip_q): + """Return an IP address from our IP Address queue.""" + try: + ip_addr = ip_q.get(timeout=1) + while ip_addr in USED_IPS: + ip_addr = ip_q.get(timeout=1) + else: + append_if(array=USED_IPS, item=ip_addr) + return str(ip_addr) + except Queue.Empty: + raise SystemExit( + 'Cannot retrieve requested amount of IP addresses. Increase the %s' + ' range in your rpc_user_config.yml.' % name + ) + + +def _load_ip_q(cidr, ip_q): + """Load the IP queue with all IP address from a given cidr. + + :param cidr: ``str`` IP address with cidr notation + """ + _all_ips = [str(i) for i in list(netaddr.IPNetwork(cidr))] + base_exclude = [ + str(netaddr.IPNetwork(cidr).network), + str(netaddr.IPNetwork(cidr).broadcast) + ] + USED_IPS.extend(base_exclude) + for ip in random.sample(_all_ips, len(_all_ips)): + if ip not in USED_IPS: + ip_q.put(ip) + + +def _parse_belongs_to(key, belongs_to, inventory): + """Parse all items in a `belongs_to` list. + + :param key: ``str`` Name of key to append to a given entry + :param belongs_to: ``list`` List of items to iterate over + :param inventory: ``dict`` Living dictionary of inventory + """ + for item in belongs_to: + if key not in inventory[item]['children']: + append_if(array=inventory[item]['children'], item=key) + + +def _build_container_hosts(container_affinity, container_hosts, type_and_name, + inventory, host_type, container_type, + container_host_type, physical_host_type, config, + is_metal, assignment): + """Add in all of hte host associations into inventory. + + This will add in all of the hosts into the inventory based on the given + affinity for a container component and its subsequent type groups. + + :param container_affinity: ``int`` Set the number of a given container + :param container_hosts: ``list`` List of containers on an host + :param type_and_name: ``str`` Combined name of host and container name + :param inventory: ``dict`` Living dictionary of inventory + :param host_type: ``str`` Name of the host type + :param container_type: ``str`` Type of container + :param container_host_type: ``str`` Type of host + :param physical_host_type: ``str`` Name of physical host group + :param config: ``dict`` User defined information + :param is_metal: ``bol`` If true, a container entry will not be built + :param assignment: ``str`` Name of container component target + """ + container_list = [] + for make_container in range(container_affinity): + for i in container_hosts: + if '%s-' % type_and_name in i: + append_if(array=container_list, item=i) + + existing_count = len(list(set(container_list))) + if existing_count < container_affinity: + hostvars = inventory['_meta']['hostvars'] + container_mapping = inventory[container_type]['children'] + address = None + + if is_metal is False: + cuuid = '%s' % uuid.uuid4() + cuuid = cuuid.split('-')[0] + container_host_name = '%s-%s' % (type_and_name, cuuid) + hostvars_options = hostvars[container_host_name] = {} + + if container_host_type not in inventory: + inventory[container_host_type] = { + "hosts": [], + } + + append_if( + array=inventory[container_host_type]["hosts"], + item=container_host_name + ) + append_if(array=container_hosts, item=container_host_name) + else: + if host_type not in hostvars: + hostvars[host_type] = {} + + hostvars_options = hostvars[host_type] + container_host_name = host_type + host_type_config = config[physical_host_type][host_type] + address = host_type_config.get('ip') + + # Create a host types containers group and append it to inventory + host_type_containers = '%s_containers' % host_type + append_if(array=container_mapping, item=host_type_containers) + + hostvars_options.update({ + 'is_metal': is_metal, + 'ansible_ssh_host': address, + 'container_address': address, + 'container_name': container_host_name, + 'physical_host': host_type, + 'component': assignment + }) + + +def _append_container_types(inventory, host_type): + """Append the "physical_host" type to all containers. + + :param inventory: ``dict`` Living dictionary of inventory + :param host_type: ``str`` Name of the host type + """ + for _host in inventory['_meta']['hostvars'].keys(): + hdata = inventory['_meta']['hostvars'][_host] + if 'container_name' in hdata: + if hdata['container_name'].startswith(host_type): + if 'physical_host' not in hdata: + hdata['physical_host'] = host_type + + +def _append_to_host_groups(inventory, container_type, assignment, host_type, + type_and_name, host_options): + """Append all containers to physical (logical) groups based on host types. + + :param inventory: ``dict`` Living dictionary of inventory + + :param container_type: ``str`` Type of container + :param assignment: ``str`` Name of container component target + :param host_type: ``str`` Name of the host type + :param type_and_name: ``str`` Combined name of host and container name + """ + physical_group_type = '%s_all' % container_type.split('_')[0] + if physical_group_type not in inventory: + inventory[physical_group_type] = {'hosts': []} + + iph = inventory[physical_group_type]['hosts'] + iah = inventory[assignment]['hosts'] + for hname, hdata in inventory['_meta']['hostvars'].iteritems(): + if 'container_types' in hdata or 'container_name' in hdata: + if 'container_name' not in hdata: + container = hdata['container_name'] = hname + else: + container = hdata['container_name'] + + component = hdata.get('component') + if container.startswith(host_type): + if 'physical_host' not in hdata: + hdata['physical_host'] = host_type + + if container.startswith('%s-' % type_and_name): + append_if(array=iah, item=container) + elif hdata.get('is_metal') is True: + if component == assignment: + append_if(array=iah, item=container) + + if container.startswith('%s-' % type_and_name): + append_if(array=iph, item=container) + elif hdata.get('is_metal') is True: + if container.startswith(host_type): + append_if(array=iph, item=container) + + # Append any options in config to the host_vars of a container + container_vars = host_options.get('container_vars') + if isinstance(container_vars, dict): + for _keys, _vars in container_vars.items(): + # Copy the options dictionary for manipulation + options = _vars.copy() + + for _k, _v in options.items(): + limit = None + # If a limit is set use the limit string as a filter + # for the container name and see if it matches. + if 'limit_container_types' in _v: + limit = _v.pop( + 'limit_container_types', None + ) + + if limit is None or limit in container: + hdata[_keys] = {_k: _v} + + +def _add_container_hosts(assignment, config, container_name, container_type, + inventory, is_metal): + """Add a given container name and type to the hosts. + + :param assignment: ``str`` Name of container component target + :param config: ``dict`` User defined information + :param container_name: ``str`` Name fo container + :param container_type: ``str`` Type of container + :param inventory: ``dict`` Living dictionary of inventory + :param is_metal: ``bol`` If true, a container entry will not be built + """ + physical_host_type = '%s_hosts' % container_type.split('_')[0] + # If the physical host type is not in config return + if physical_host_type not in config: + return + + for host_type in inventory[physical_host_type]['hosts']: + container_hosts = inventory[container_name]['hosts'] + + # If host_type is not in config do not append containers to it + if host_type not in config[physical_host_type]: + continue + + # Get any set host options + host_options = config[physical_host_type][host_type] + affinity = host_options.get('affinity', {}) + + container_affinity = affinity.get(container_name, 1) + # Ensures that container names are not longer than 64 + name_length = len(host_type) + if name_length > 25: + name_diff = name_length - 25 + host_name = host_type[:-name_diff] + else: + host_name = host_type + type_and_name = '%s_%s' % (host_name, container_name) + + physical_host = inventory['_meta']['hostvars'][host_type] + container_host_type = '%s_containers' % host_type + if 'container_types' not in physical_host: + physical_host['container_types'] = container_host_type + elif physical_host['container_types'] != container_host_type: + physical_host['container_types'] = container_host_type + + # Add all of the containers into the inventory + _build_container_hosts( + container_affinity, + container_hosts, + type_and_name, + inventory, + host_type, + container_type, + container_host_type, + physical_host_type, + config, + is_metal, + assignment + ) + + # Add the physical host type to all containers from the built inventory + _append_container_types(inventory, host_type) + _append_to_host_groups( + inventory, + container_type, + assignment, + host_type, + type_and_name, + host_options + ) + + +def user_defined_setup(config, inventory, is_metal): + """Apply user defined entries from config into inventory. + + :param config: ``dict`` User defined information + :param inventory: ``dict`` Living dictionary of inventory + :param is_metal: ``bol`` If true, a container entry will not be built + """ + for key, value in config.iteritems(): + if key.endswith('hosts'): + if key not in inventory: + inventory[key] = {'hosts': []} + + if value is None: + return + + for _key, _value in value.iteritems(): + if _key not in inventory['_meta']['hostvars']: + inventory['_meta']['hostvars'][_key] = {} + + inventory['_meta']['hostvars'][_key].update({ + 'ansible_ssh_host': _value['ip'], + 'container_address': _value['ip'], + 'is_metal': is_metal, + }) + + if 'host_vars' in _value: + for _k, _v in _value['host_vars'].items(): + inventory['_meta']['hostvars'][_key][_k] = _v + + append_if(array=USED_IPS, item=_value['ip']) + append_if(array=inventory[key]['hosts'], item=_key) + + +def skel_setup(environment_file, inventory): + """Build out the main inventory skeleton as needed. + + :param environment_file: ``dict`` Known environment information + :param inventory: ``dict`` Living dictionary of inventory + """ + for key, value in environment_file.iteritems(): + if key == 'version': + continue + for _key, _value in value.iteritems(): + if _key not in inventory: + inventory[_key] = {} + if _key.endswith('container'): + if 'hosts' not in inventory[_key]: + inventory[_key]['hosts'] = [] + else: + if 'children' not in inventory[_key]: + inventory[_key]['children'] = [] + if 'hosts' not in inventory[_key]: + inventory[_key]['hosts'] = [] + + if 'belongs_to' in _value: + for assignment in _value['belongs_to']: + if assignment not in inventory: + inventory[assignment] = {} + if 'children' not in inventory[assignment]: + inventory[assignment]['children'] = [] + if 'hosts' not in inventory[assignment]: + inventory[assignment]['hosts'] = [] + + +def skel_load(skeleton, inventory): + """Build out data as provided from the defined `skel` dictionary. + + :param skeleton: + :param inventory: ``dict`` Living dictionary of inventory + """ + for key, value in skeleton.iteritems(): + _parse_belongs_to( + key, + belongs_to=value['belongs_to'], + inventory=inventory + ) + + +def _add_additional_networks(key, inventory, ip_q, k_name, netmask): + """Process additional ip adds and append then to hosts as needed. + + If the host is found to be "is_metal" it will be marked as "on_metal" + and will not have an additionally assigned IP address. + + :param key: ``str`` Component key name + :param inventory: ``dict`` Living dictionary of inventory + :param ip_q: ``object`` build queue of IP addresses + :param k_name: ``str`` key to use in host vars for storage + """ + base_hosts = inventory['_meta']['hostvars'] + addr_name = '%s_address' % k_name + lookup = inventory[key] + + if 'children' in lookup and lookup['children']: + for group in lookup['children']: + _add_additional_networks(group, inventory, ip_q, k_name, netmask) + + if 'hosts' in lookup and lookup['hosts']: + for chost in lookup['hosts']: + container = base_hosts[chost] + if not container.get(addr_name): + if ip_q is None: + container[addr_name] = None + else: + container[addr_name] = get_ip_address( + name=k_name, ip_q=ip_q + ) + + netmask_name = '%s_netmask' % k_name + if netmask_name not in container: + container[netmask_name] = netmask + + +def _load_optional_q(config, cidr_name): + """Load optional queue with ip addresses. + + :param config: ``dict`` User defined information + :param cidr_name: ``str`` Name of the cidr name + """ + cidr = config.get(cidr_name) + ip_q = None + if cidr is not None: + ip_q = Queue.Queue() + _load_ip_q(cidr=cidr, ip_q=ip_q) + return ip_q + + +def container_skel_load(container_skel, inventory, config): + """Build out all containers as defined in the environment file. + + :param container_skel: ``dict`` container skeleton for all known containers + :param inventory: ``dict`` Living dictionary of inventory + :param config: ``dict`` User defined information + """ + for key, value in container_skel.iteritems(): + for assignment in value['contains']: + for container_type in value['belongs_to']: + _add_container_hosts( + assignment, + config, + key, + container_type, + inventory, + value.get('is_metal', False) + ) + else: + cidr_networks = config.get('cidr_networks') + provider_queues = {} + for net_name in cidr_networks: + ip_q = _load_optional_q( + cidr_networks, cidr_name=net_name + ) + provider_queues[net_name] = ip_q + if ip_q is not None: + net = netaddr.IPNetwork(cidr_networks.get(net_name)) + provider_queues['%s_netmask' % net_name] = str(net.netmask) + + overrides = config['global_overrides'] + mgmt_bridge = overrides['management_bridge'] + mgmt_dict = {} + if cidr_networks: + for pn in overrides['provider_networks']: + network = pn['network'] + if 'ip_from_q' in network and 'group_binds' in network: + q_name = network['ip_from_q'] + for group in network['group_binds']: + _add_additional_networks( + key=group, + inventory=inventory, + ip_q=provider_queues[q_name], + k_name=q_name, + netmask=provider_queues['%s_netmask' % q_name] + ) + + if mgmt_bridge == network['container_bridge']: + nci = network['container_interface'] + ncb = network['container_bridge'] + ncn = network.get('ip_from_q') + mgmt_dict['container_interface'] = nci + mgmt_dict['container_bridge'] = ncb + if ncn: + cidr_net = netaddr.IPNetwork(cidr_networks.get(ncn)) + mgmt_dict['container_netmask'] = str(cidr_net.netmask) + + for host, hostvars in inventory['_meta']['hostvars'].iteritems(): + base_hosts = inventory['_meta']['hostvars'][host] + if 'container_network' not in base_hosts: + base_hosts['container_network'] = mgmt_dict + + for _key, _value in hostvars.iteritems(): + if _key == 'ansible_ssh_host' and _value is None: + ca = base_hosts['container_address'] + base_hosts['ansible_ssh_host'] = ca + + +def file_find(filename, user_file=None, pass_exception=False): + """Return the path to a file. + + If no file is found the system will exit. + The file lookup will be done in the following directories: + /etc/rpc_deploy/ + $HOME/rpc_deploy/ + $(pwd)/rpc_deploy/ + + :param filename: ``str`` Name of the file to find + :param user_file: ``str`` Additional localtion to look in FIRST for a file + """ + file_check = [ + os.path.join( + '/etc', 'rpc_deploy', filename + ), + os.path.join( + os.environ.get('HOME'), 'rpc_deploy', filename + ), + os.path.join( + os.getcwd(), filename + ) + ] + + if user_file is not None: + file_check.insert(0, os.path.expanduser(user_file)) + + for f in file_check: + if os.path.isfile(f): + return f + else: + if pass_exception is False: + raise SystemExit('No file found at: %s' % file_check) + else: + return False + + +def _set_used_ips(user_defined_config, inventory): + """Set all of the used ips into a global list. + + :param user_defined_config: ``dict`` User defined configuration + :param inventory: ``dict`` Living inventory of containers and hosts + """ + used_ips = user_defined_config.get('used_ips') + if isinstance(used_ips, list): + for ip in used_ips: + split_ip = ip.split(',') + if len(split_ip) >= 2: + ip_range = list( + netaddr.iter_iprange( + split_ip[0], + split_ip[-1] + ) + ) + USED_IPS.extend([str(i) for i in ip_range]) + else: + append_if(array=USED_IPS, item=split_ip[0]) + + # Find all used IP addresses and ensure that they are not used again + for host_entry in inventory['_meta']['hostvars'].values(): + if 'ansible_ssh_host' in host_entry: + append_if(array=USED_IPS, item=host_entry['ansible_ssh_host']) + + for key, value in host_entry.iteritems(): + if key.endswith('address'): + append_if(array=USED_IPS, item=value) + + +def _ensure_inventory_uptodate(inventory): + """Update inventory if needed. + + Inspect the current inventory and ensure that all host items have all of + the required entries. + + :param inventory: ``dict`` Living inventory of containers and hosts + """ + for key, value in inventory['_meta']['hostvars'].iteritems(): + if 'container_name' not in value: + value['container_name'] = key + + for rh in REQUIRED_HOSTVARS: + if rh not in value: + value[rh] = None + + +def _parse_global_variables(user_cidr, inventory, user_defined_config): + """Add any extra variables that may have been set in config. + + :param user_cidr: ``str`` IP address range in CIDR notation + :param inventory: ``dict`` Living inventory of containers and hosts + :param user_defined_config: ``dict`` User defined variables + """ + if 'all' not in inventory: + inventory['all'] = {} + + if 'vars' not in inventory['all']: + inventory['all']['vars'] = {} + + # Write the users defined cidr into global variables. + inventory['all']['vars']['container_cidr'] = user_cidr + + if 'global_overrides' in user_defined_config: + if isinstance(user_defined_config['global_overrides'], dict): + inventory['all']['vars'].update( + user_defined_config['global_overrides'] + ) + + +def append_if(array, item): + """Append an ``item`` to an ``array`` if its not already in it. + + :param array: ``list`` List object to append to + :param item: ``object`` Object to append to the list + :returns array: returns the amended list. + """ + if item not in array: + array.append(item) + return array + + +def md5_checker(localfile): + """Check for different Md5 in CloudFiles vs Local File. + + If the md5 sum is different, return True else False + + :param localfile: + :return True|False: + """ + + def calc_hash(): + """Read the hash. + + :return data_hash.read(): + """ + + return data_hash.read(128 * md5.block_size) + + if os.path.isfile(localfile) is True: + md5 = hashlib.md5() + with open(localfile, 'rb') as data_hash: + for chk in iter(calc_hash, ''): + md5.update(chk) + + return md5.hexdigest() + else: + raise SystemExit('This [ %s ] is not a file.' % localfile) + + +def main(): + """Run the main application.""" + all_args = args() + + # Get the contents of the user config json and load it as an object + user_config_file = file_find( + filename='rpc_user_config.yml', user_file=all_args.get('file') + ) + local_path = os.path.dirname(user_config_file) + + # Load the user defined configuration file + with open(user_config_file, 'rb') as f: + user_defined_config = yaml.load(f.read()) + + # Get the contents of the system environment json + environment_file = file_find(filename='rpc_environment.yml') + + # Load existing rpc environment json + with open(environment_file, 'rb') as f: + environment = yaml.safe_load(f.read()) + + # Check the version of the environment file + env_version = md5_checker(localfile=environment_file) + version = user_defined_config.get('environment_version') + if env_version != version: + raise SystemExit( + 'The MD5 sum of the environment file does not match the expected' + ' value. To ensure that you are using the proper environment' + ' please repull the correct environment file from the upstream' + ' repository. Found MD5: [ %s ] expected MD5 [ %s ]' + % (env_version, version) + ) + + + # Load existing inventory file if found + dynamic_inventory_file = os.path.join(local_path, 'rpc_inventory.json') + if os.path.isfile(dynamic_inventory_file): + with open(dynamic_inventory_file, 'rb') as f: + dynamic_inventory = json.loads(f.read()) + + # Create a backup of all previous inventory files as a tar archive + inventory_backup_file = os.path.join( + local_path, + 'backup_rpc_inventory.tar' + ) + with tarfile.open(inventory_backup_file, 'a') as tar: + basename = os.path.basename(dynamic_inventory_file) + # Time stamp the inventory file in UTC + utctime = datetime.datetime.utcnow() + utctime = utctime.strftime("%Y%m%d_%H%M%S") + backup_name = '%s-%s.json' % (basename, utctime) + tar.add(dynamic_inventory_file, arcname=backup_name) + else: + dynamic_inventory = INVENTORY_SKEL + + # Save the users container cidr as a group variable + if 'container' in user_defined_config['cidr_networks']: + user_cidr = user_defined_config['cidr_networks']['container'] + else: + raise SystemExit('No CIDR specified in user config') + + # Add the container_cidr into the all global ansible group_vars + _parse_global_variables(user_cidr, dynamic_inventory, user_defined_config) + + # Load all of the IP addresses that we know are used and set the queue + _set_used_ips(user_defined_config, dynamic_inventory) + user_defined_setup(user_defined_config, dynamic_inventory, is_metal=True) + skel_setup(environment, dynamic_inventory) + skel_load( + environment.get('physical_skel'), + dynamic_inventory + ) + skel_load( + environment.get('component_skel'), dynamic_inventory + ) + container_skel_load( + environment.get('container_skel'), + dynamic_inventory, + user_defined_config + ) + + # Look at inventory and ensure all entries have all required values. + _ensure_inventory_uptodate(inventory=dynamic_inventory) + + # Load the inventory json + dynamic_inventory_json = json.dumps(dynamic_inventory, indent=4) + + # Generate a list of all hosts and their used IP addresses + hostnames_ips = {} + for _host, _vars in dynamic_inventory['_meta']['hostvars'].iteritems(): + host_hash = hostnames_ips[_host] = {} + for _key, _value in _vars.iteritems(): + if _key.endswith('address') or _key == 'ansible_ssh_host': + host_hash[_key] = _value + + # Save a list of all hosts and their given IP addresses + with open(os.path.join(local_path, 'rpc_hostnames_ips.yml'), 'wb') as f: + f.write( + json.dumps( + hostnames_ips, + indent=4 + ) + ) + + # Save new dynamic inventory + with open(dynamic_inventory_file, 'wb') as f: + f.write(dynamic_inventory_json) + + # Print out our inventory + print(dynamic_inventory_json) + +if __name__ == '__main__': + main() diff --git a/rpc_deployment/inventory/group_vars/all.yml b/rpc_deployment/inventory/group_vars/all.yml new file mode 100644 index 0000000000..5a74a8edab --- /dev/null +++ b/rpc_deployment/inventory/group_vars/all.yml @@ -0,0 +1,179 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the dbservers group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +# Defined required kernel. presently 3.13.0-32-generic +required_kernel: 3.13.0-34-generic + +## Container Template Config +container_template: rpc +container_release: trusty + +# Parameters on what the conatiner will be built with +container_config: /etc/lxc/lxc-rpc.conf + + +## Base Ansible config for all plays +ansible_ssh_port: 22 + + +## Virtual IP address +# Internal Management vip address +internal_vip_address: "{{ internal_lb_vip_address }}" + +# External DMZ VIP address +external_vip_address: "{{ external_lb_vip_address }}" + + +## URL for the frozen rpc repo +rpc_repo_url: "http://dc0e2a2ef0676c3453b1-31bb9324d3aeab0d08fa434012c1e64d.r5.cf1.rackcdn.com" + + +## GPG Keys +gpg_keys: + - { key_name: 'mariadb', keyserver: 'hkp://keyserver.ubuntu.com:80', hash_id: '0xcbcb082a1bb943db' } + + +## Repositories +apt_common_repos: + - { repo: "deb http://mirror.jmu.edu/pub/mariadb/repo/5.5/ubuntu {{ ansible_distribution_release }} main", state: "present" } + +apt_lxc_common_repos: + - { repo: "ppa:ubuntu-lxc/stable", state: "present" } + +get_pip_url: "https://bootstrap.pypa.io/get-pip.py" + + +## Users that will not be created via container_common +excluded_user_create: + - mysql + - rabbitmq + + +## Base Packages +apt_common_packages: + - vlan + - python-software-properties + - python-dev + - build-essential + - git-core + - rsyslog + - lvm2 + - libssl-dev + - bridge-utils + - cgroup-lite + - sqlite3 + - iptables + - sshpass + - libffi-dev + - libxml2-dev + - libxslt1-dev + - mariadb-client + - libmariadbclient-dev + + +# Util packages that are installed when repos are put in place +common_util_packages: + - curl + - wget + - time + - rsync + + +## MySQL Information +mysql_port: 3306 +mysql_user: root +mysql_password: "{{ mysql_root_password }}" +mysql_address: "{{ internal_vip_address }}" + + +## RPC Backend +rpc_thread_pool_size: 64 +rpc_conn_pool_size: 30 +rpc_response_timeout: 60 +rpc_cast_timeout: 30 +rpc_backend: rabbit + + +## RabbitMQ +rabbit_port: 5672 +rabbit_hosts: "{% for host in groups['rabbit'] %}{{ hostvars[host]['container_address'] }}:{{ rabbit_port }}{% if not loop.last %},{% endif %}{% endfor %}" +rabbit_use_ssl: false +rabbit_virtual_host: / +rabbit_retry_interval: 1 +rabbit_retry_backoff: 2 +rabbit_max_retries: 0 +rabbit_ha_queues: false +rabbit_userid: openstack +rabbit_password: "{{ rabbitmq_password }}" + + +## Auth +auth_admin_username: admin +auth_admin_password: "{{ keystone_auth_admin_password }}" +auth_admin_token: "{{ keystone_auth_admin_password }}" +auth_admin_tenant: admin +auth_identity_uri: "http://{{ internal_vip_address }}:5000/v2.0" +auth_admin_uri: "http://{{ internal_vip_address }}:35357/v2.0" +auth_host: "{{ internal_vip_address }}" +auth_port: 35357 +auth_public_port: 5000 +auth_protocol: http + + +## Openstack Region +service_region: RegionOne + + +## Container User +container_username: openstack +container_password: "{{ container_openstack_password }}" + + +## Memcached +memcached_memory: 8192 +memcached_port: 11211 +memcached_user: memcache +memcached_secret_key: "{{ memcached_encryption_key }}" + + +## Haproxy Configuration +hap_rise: 3 +hap_fall: 3 +hap_interval: 12000 + +# Default haproxy backup nodes to empty list so this doesn't have to be +# defined for each service. +hap_backup_nodes: [] + + +## Swift credentials for Swift Container image store +swift_archive_store: + creds_file: /root/swiftcreds + section: default + container: poc_lxc_containers + +## Remote logging common configuration +elasticsearch_http_port: 9200 +elasticsearch_tcp_port: 9300 +elasticsearch_mode: transport +elasticsearch_cluster: openstack +elasticsearch_vip: "{{ external_vip_address }}" +logstash_port: 5544 + +# Directory where serverspec is installed to on utility container +serverspec_install_dir: /opt/serverspec diff --git a/rpc_deployment/inventory/group_vars/cinder_all.yml b/rpc_deployment/inventory/group_vars/cinder_all.yml new file mode 100644 index 0000000000..6acc2b94ad --- /dev/null +++ b/rpc_deployment/inventory/group_vars/cinder_all.yml @@ -0,0 +1,92 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the Cinder-api group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +## Service Name +service_name: cinder + +# Verbosity Options +debug: False +verbose: True + +# only used when the lxc vg is present on the target +container_lvm_fstype: ext4 +container_lvm_fssize: 5GB + +## General configuration +## Set this in rpc_user_config.yml UNLESS you want all hosts to use the same +## Cinder backends. See the rpc_user_config example for more on how this is done. +# cinder_backends: +# lvm: +# volume_group: cinder-volumes +# driver: cinder.volume.drivers.lvm.LVMISCSIDriver +# backend_name: LVM_iSCSI + +cinder_service_port: "{{ cinder_port|default('8776') }}" + +## DB +container_mysql_user: cinder +container_mysql_password: "{{ cinder_container_mysql_password }}" +container_database: cinder + +## Cinder Auth +service_admin_tenant_name: "service" +service_admin_username: "cinder" +service_admin_password: "{{ cinder_service_password }}" + +## Cinder User / Group +system_user: cinder +system_group: cinder + +## Service Names +service_names: + - cinder-api + - cinder-scheduler + - cinder-volume + +## Git Source +git_repo: https://git.openstack.org/openstack/cinder +git_fallback_repo: https://github.com/openstack/cinder +git_etc_example: etc/cinder/ +git_install_branch: stable/icehouse + +service_pip_dependencies: + - pywbem + - ecdsa + - MySQL-python + - python-memcached + - pycrypto + - python-cinderclient + - python-keystoneclient + - keystonemiddleware + +container_directories: + - /var/log/cinder + - /var/lib/cinder + - /var/lib/cinder/volumes + - /etc/cinder + - /etc/cinder/rootwrap.d + - /var/cache/cinder + - /var/lock/cinder + - /var/run/cinder + +container_packages: + - libpq-dev + - libkmod-dev + - libkmod2 + - dmeventd + diff --git a/rpc_deployment/inventory/group_vars/elasticsearch.yml b/rpc_deployment/inventory/group_vars/elasticsearch.yml new file mode 100644 index 0000000000..88e733a146 --- /dev/null +++ b/rpc_deployment/inventory/group_vars/elasticsearch.yml @@ -0,0 +1,36 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Variables for the logstash containers +service_name: elasticsearch + +debug: False +verbose: True + +container_lvm_fstype: ext4 +container_lvm_fssize: 5GB + +apt_container_keys: + - { url: "http://packages.elasticsearch.org/GPG-KEY-elasticsearch", state: "present" } + +apt_container_repos: + - { repo: "deb http://packages.elasticsearch.org/elasticsearch/1.2/debian stable main", state: "present"} + +container_packages: + - elasticsearch + +service_pip_dependencies: + - requests + diff --git a/rpc_deployment/inventory/group_vars/galera.yml b/rpc_deployment/inventory/group_vars/galera.yml new file mode 100644 index 0000000000..ed3bfcaae2 --- /dev/null +++ b/rpc_deployment/inventory/group_vars/galera.yml @@ -0,0 +1,39 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +service_name: mysql + +container_lvm_fstype: ext4 +container_lvm_fssize: 5GB + +debian_sys_maint_password: "{{ mysql_debian_sys_maint_password }}" + +mariadb_server_package: mariadb-galera-server-5.5 + +galera_packages: + - mariadb-client + - "{{ mariadb_server_package }}" + - galera + - python-software-properties + - software-properties-common + - debconf-utils + - rsync + - xtrabackup + +# Size of the galera cache +galera_gcache_size: 1G + +service_pip_dependencies: + - MySQL-python diff --git a/rpc_deployment/inventory/group_vars/glance_all.yml b/rpc_deployment/inventory/group_vars/glance_all.yml new file mode 100644 index 0000000000..6769256811 --- /dev/null +++ b/rpc_deployment/inventory/group_vars/glance_all.yml @@ -0,0 +1,117 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the Glance-api group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +## Service Name +service_name: glance + +service_publicurl: "http://{{ external_vip_address }}:9292" +service_adminurl: "http://{{ internal_vip_address }}:9292" +service_internalurl: "http://{{ internal_vip_address }}:9292" + +# Verbosity Options +debug: False +verbose: True + +# only used when the lxc vg is present on the target +container_lvm_fstype: ext4 +container_lvm_fssize: 5GB + +# General configuration +registry_host: "{{ internal_vip_address }}" + +## DB +container_mysql_user: glance +container_mysql_password: "{{ glance_container_mysql_password }}" +container_database: glance + +## RPC +rpc_backend: glance.openstack.common.rpc.impl_kombu + +## Backend +default_store: "{{ glance_default_store|default('file') }}" + +## Swift Options +swift_store_auth_address: "{{ glance_swift_store_auth_address | default('NoAuthAddress') }}" +swift_store_user: "{{ glance_swift_store_user | default('NoUser') }}" +swift_store_key: "{{ glance_swift_store_key | default('NoKey') }}" +swift_store_region: "{{ glance_swift_store_region | default('NoRegion') }}" +swift_store_container: "{{ glance_swift_store_container | default('NoContainer')}}" + +## Auth +service_admin_tenant_name: "service" +service_admin_username: "glance" +service_admin_password: "{{ glance_service_password }}" + +## Glance User / Group +system_user: glance +system_group: glance + +## Service Names +service_names: + - glance-api + - glance-registry + +flavor: "keystone+cachemanagement" + +## Git Source +git_repo: https://git.openstack.org/openstack/glance +git_fallback_repo: https://github.com/openstack/glance +git_etc_example: etc/ +git_install_branch: stable/icehouse + +service_pip_dependencies: + - warlock + - MySQL-python + - python-memcached + - pycrypto + - python-glanceclient + - python-keystoneclient + - keystonemiddleware + +container_directories: + - /var/log/glance + - /var/lib/glance + - /var/lib/glance/cache + - /var/lib/glance/cache/api + - /var/lib/glance/cache/registry + - /var/lib/glance/scrubber + - /etc/glance + - /var/cache/glance + +container_packages: + - rsync + +cf_snet_endpoints: + DFW: + hostname: storage101.dfw1.clouddrive.com + ip: 10.191.208.30 + HKG: + hostname: storage101.hkg1.clouddrive.com + ip: 10.191.208.34 + IAD: + hostname: storage101.iad3.clouddrive.com + ip: 10.191.208.34 + LON: + hostname: storage101.lon3.clouddrive.com + ip: 10.191.209.30 + ORD: + hostname: storage101.ord1.clouddrive.com + ip: 10.191.208.30 + SYD: + hostname: storage101.syd2.clouddrive.com + ip: 10.191.208.34 diff --git a/rpc_deployment/inventory/group_vars/heat_all.yml b/rpc_deployment/inventory/group_vars/heat_all.yml new file mode 100644 index 0000000000..9c489e2407 --- /dev/null +++ b/rpc_deployment/inventory/group_vars/heat_all.yml @@ -0,0 +1,92 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the Heat-api group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +## Service Name +service_name: heat + +# Verbosity Options +debug: False +verbose: True + +# only used when the lxc vg is present on the target +container_lvm_fstype: ext4 +container_lvm_fssize: 5GB + + +## DB +container_mysql_user: heat +container_mysql_password: "{{ heat_container_mysql_password }}" +container_database: heat + +## RPC +rpc_backend: heat.openstack.common.rpc.impl_kombu + +## Auth +service_admin_tenant_name: "service" +service_admin_username: "heat" +service_admin_password: "{{ heat_service_password }}" + +## Heat User / Group +system_user: heat +system_group: heat + +## Service Names +service_names: + - heat-api + - heat-api-cfn + - heat-api-cloudwatch + - heat-engine + +## Stack +stack_domain_admin_password: "{{ heat_stack_domain_admin_password }}" +stack_domain_admin: heat_domain_admin +deferred_auth_method: trusts + +auth_encryption_key: "{{ heat_auth_encryption_key }}" + +heat_watch_server_url: "http://{{ external_vip_address }}:8003" +heat_waitcondition_server_url: "http://{{ internal_vip_address }}:8000/v1/waitcondition" +heat_metadata_server_url: "http://{{ internal_vip_address }}:8000" + +## Git Source +git_repo: https://git.openstack.org/openstack/heat +git_fallback_repo: https://github.com/openstack/heat +git_etc_example: etc/heat +git_install_branch: stable/icehouse + +service_pip_dependencies: + - MySQL-python + - python-memcached + - pycrypto + - python-heatclient + - python-keystoneclient + - python-troveclient + - python-ceilometerclient + - keystonemiddleware + +container_directories: + - /etc/heat + - /etc/heat/environment.d + - /etc/heat/templates + - /var/cache/heat + - /var/lib/heat + - /var/log/heat + +container_packages: + - rsync + - libxslt1.1 diff --git a/rpc_deployment/inventory/group_vars/horizon.yml b/rpc_deployment/inventory/group_vars/horizon.yml new file mode 100644 index 0000000000..84326b3b8a --- /dev/null +++ b/rpc_deployment/inventory/group_vars/horizon.yml @@ -0,0 +1,84 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the Horizon group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +# Enable containerization of services +containerize: true + +## Service Name +service_name: apache2 + +# Verbosity Options +debug: False + +# only used when the lxc vg is present on the target +container_lvm_fstype: ext4 +container_lvm_fssize: 5GB + + +## DB +container_mysql_user: dash +container_mysql_password: "{{ horizon_container_mysql_password }}" +container_database: dash + + +## Horizon User / Group +system_user: www-data +system_group: www-data + +## Git Source +git_repo: https://git.openstack.org/openstack/horizon +git_fallback_repo: https://github.com/openstack/horizon +git_install_branch: stable/icehouse + +# Installation directories +install_root_dir: /opt/horizon +install_lib_dir: /opt/horizon/lib/python2.7/site-packages + +service_pip_dependencies: + - oslo.config + - MySQL-python + - python-memcached + - django-appconf + - pycrypto + - ply + - greenlet + +container_directories: + - "{{ install_root_dir }}" + - "{{ install_lib_dir }}" + +container_packages: + - apache2 + - apache2-utils + - libapache2-mod-wsgi + - libssl-dev + - libxslt1.1 + - openssl + +horizon_fqdn: "{{ external_vip_address }}" +horizon_server_name: "{{ container_name }}" +horizon_self_signed: true + +pip_install_options: "--install-option='--prefix={{ install_root_dir }}'" +service_name: horizon + +## Optional certification options +# horizon_cacert_pem: /path/to/cacert.pem +# horizon_ssl_cert: /etc/ssl/certs/apache.cert +# horizon_ssl_key: /etc/ssl/private/apache.key +# horizon_ssl_cert_path: /etc/ssl/certs diff --git a/rpc_deployment/inventory/group_vars/hosts.yml b/rpc_deployment/inventory/group_vars/hosts.yml new file mode 100644 index 0000000000..4fdfe6cf8e --- /dev/null +++ b/rpc_deployment/inventory/group_vars/hosts.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +raxmon_agent_key: + - "https://monitoring.api.rackspacecloud.com/pki/agent/linux.asc" + +raxmon_agent_repos: + - { repo: "deb http://stable.packages.cloudmonitoring.rackspace.com/ubuntu-14.04-x86_64 cloudmonitoring main", state: "present" } diff --git a/rpc_deployment/inventory/group_vars/keystone_all.yml b/rpc_deployment/inventory/group_vars/keystone_all.yml new file mode 100644 index 0000000000..7c44c426ce --- /dev/null +++ b/rpc_deployment/inventory/group_vars/keystone_all.yml @@ -0,0 +1,99 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the Keystone-api group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +## Service Name +service_name: keystone + + +## Service ports +service_port: 5000 +admin_port: 35357 + + +## Verbosity Options +debug: False +verbose: True + +# only used when the lxc vg is present on the target +container_lvm_fstype: ext4 +container_lvm_fssize: 5GB + + +## DB +container_mysql_user: keystone +container_mysql_password: "{{ keystone_container_mysql_password }}" +container_database: keystone + + +## AUTH +auth_methods: "password,token" +token_provider: "keystone.token.providers.uuid.Provider" + +# If the "token_provider" is set to PKI set this to True +keystone_use_pki: False + + +## Keystone User / Group +system_user: keystone +system_group: keystone + + +## Git Source +git_repo: https://git.openstack.org/openstack/keystone +git_fallback_repo: https://github.com/openstack/keystone +git_etc_example: etc/ +git_install_branch: stable/icehouse + +# Common PIP Packages +service_pip_dependencies: + - repoze.lru + - pbr + - MySQL-python + - pycrypto + - python-memcached + - python-keystoneclient + + +## Enable SSL +keystone_ssl: false + +## Optional SSL vars +# keystone_ssl_cert: /etc/ssl/certs/apache.cert +# keystone_ssl_key: /etc/ssl/certs/apache.key +# keystone_ssl_cert_path: /etc/ssl/certs + + +container_directories: + - /etc/keystone + - /etc/keystone/ssl + - /var/lib/keystone + - /var/log/keystone + - /var/www/cgi-bin/keystone + +container_packages: + - libsasl2-dev + - debhelper + - dh-apparmor + - docutils-common + - libjs-sphinxdoc + - libjs-underscore + - libxslt1.1 + - libldap2-dev + - apache2 + - apache2-utils + - libapache2-mod-wsgi diff --git a/rpc_deployment/inventory/group_vars/kibana.yml b/rpc_deployment/inventory/group_vars/kibana.yml new file mode 100644 index 0000000000..222f0be950 --- /dev/null +++ b/rpc_deployment/inventory/group_vars/kibana.yml @@ -0,0 +1,39 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Variables for the logstash containers +service_name: kibana + +debug: False +verbose: True + +container_lvm_fstype: ext4 +container_lvm_fssize: 5GB + +kibana_url: https://download.elasticsearch.org/kibana/kibana/kibana-3.1.0.tar.gz + +kibana_root: /opt/kibana + +container_packages: + - apache2 + - python-passlib + +system_user: www-user +system_group: www-data + +kibana_fqdn: "{{ external_vip_address }}" +kibana_server_name: "{{ container_name }}" +kibana_self_signed: true +kibana_ssl_port: 8443 diff --git a/rpc_deployment/inventory/group_vars/logstash.yml b/rpc_deployment/inventory/group_vars/logstash.yml new file mode 100644 index 0000000000..5acddbd64e --- /dev/null +++ b/rpc_deployment/inventory/group_vars/logstash.yml @@ -0,0 +1,35 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Variables for the logstash containers +service_name: logstash + +debug: False +verbose: True + +container_lvm_fstype: ext4 +container_lvm_fssize: 5GB + +# Apt repos for ELK +apt_container_keys: + - { url: "http://packages.elasticsearch.org/GPG-KEY-elasticsearch", state: "present" } + +apt_container_repos: + - { repo: "deb http://packages.elasticsearch.org/logstash/1.4/debian stable main", state: "present"} + +container_packages: + - logstash + - logstash-contrib + diff --git a/rpc_deployment/inventory/group_vars/memcached.yml b/rpc_deployment/inventory/group_vars/memcached.yml new file mode 100644 index 0000000000..7b165df92f --- /dev/null +++ b/rpc_deployment/inventory/group_vars/memcached.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +service_name: memcached + +# only used when the lxc vg is present on the target +container_lvm_fstype: ext4 +container_lvm_fssize: 5GB diff --git a/rpc_deployment/inventory/group_vars/neutron_all.yml b/rpc_deployment/inventory/group_vars/neutron_all.yml new file mode 100644 index 0000000000..420deb29de --- /dev/null +++ b/rpc_deployment/inventory/group_vars/neutron_all.yml @@ -0,0 +1,111 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +## Service Name +service_name: neutron + +# Verbosity Options +debug: False +verbose: True + +## only used when the lxc vg is present on the target +container_lvm_fstype: ext4 +container_lvm_fssize: 5GB + +## General configuration +core_plugin: neutron.plugins.ml2.plugin.Ml2Plugin +interface_driver: neutron.agent.linux.interface.BridgeInterfaceDriver +metering_driver: neutron.services.metering.drivers.iptables.iptables_driver.IptablesMeteringDriver + +service_plugins: + - neutron.services.l3_router.l3_router_plugin.L3RouterPlugin + - neutron.services.loadbalancer.plugin.LoadBalancerPlugin + - neutron.services.firewall.fwaas_plugin.FirewallPlugin + - neutron.services.vpn.plugin.VPNDriverPlugin + - neutron.services.metering.metering_plugin.MeteringPlugin + +dhcp_driver: neutron.agent.linux.dhcp.Dnsmasq +neutron_config: /etc/neutron/neutron.conf +neutron_plugin: /etc/neutron/plugins/ml2/ml2_conf.ini +neutron_revision: icehouse + +## Neutron downtime +neutron_agent_down_time: 120 +neutron_report_interval: "{{ neutron_agent_down_time|int / 2 }}" +neutron_agent_polling_interval: 5 + +## DB +container_mysql_user: neutron +container_mysql_password: "{{ neutron_container_mysql_password }}" +container_database: neutron + +## RPC +rpc_backend: rabbit + +## Nova Auth +service_admin_tenant_name: "service" +service_admin_username: "neutron" +service_admin_password: "{{ neutron_service_password }}" + +## Nova User / Group +system_user: neutron +system_group: neutron + +## Service Names +service_names: + - neutron-agent + - neutron-dhcp-agent + - neutron-linuxbridge-agent + - neutron-metadata-agent + - neutron-metering-agent + - neutron-l3-agent + - neutron-server + +## Git Source +git_repo: https://git.openstack.org/openstack/neutron +git_fallback_repo: https://github.com/openstack/neutron +git_etc_example: etc/ +git_install_branch: stable/icehouse + +service_pip_dependencies: + - MySQL-python + - python-memcached + - pycrypto + - repoze.lru + - configobj + - cliff + - python-novaclient + - python-neutronclient + - python-keystoneclient + - keystonemiddleware + +container_directories: + - /etc/neutron + - /etc/neutron/plugins + - /etc/neutron/plugins/ml2 + - /etc/neutron/rootwrap.d + - /var/cache/neutron + - /var/lib/neutron + - /var/lock/neutron + - /var/log/neutron + - /var/run/neutron + +container_packages: + - libpq-dev + - dnsmasq-base + - dnsmasq-utils diff --git a/rpc_deployment/inventory/group_vars/nova_all.yml b/rpc_deployment/inventory/group_vars/nova_all.yml new file mode 100644 index 0000000000..87e368bc3d --- /dev/null +++ b/rpc_deployment/inventory/group_vars/nova_all.yml @@ -0,0 +1,103 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +## Service Name +service_name: nova + +# Verbosity Options +debug: False +verbose: True + +# only used when the lxc vg is present on the target +container_lvm_fstype: ext4 +container_lvm_fssize: 5GB + +# General configuration +volume_driver: cinder.volume.drivers.lvm.LVMISCSIDriver + +## DB +container_mysql_user: nova +container_mysql_password: "{{ nova_container_mysql_password }}" +container_database: nova + +## RPC +rpc_backend: nova.openstack.common.rpc.impl_kombu + +## Nova virtualization Type, set to KVM if supported +virt_type: "{{ nova_virt_type|default('qemu') }}" + +## Nova Auth +service_admin_tenant_name: "service" +service_admin_username: "nova" +service_admin_password: "{{ nova_service_password }}" + +## Nova User / Group +system_user: nova +system_group: nova + +## Service Names +service_names: + - nova-api-metadata + - nova-api-os-compute + - nova-api-ec2 + - nova-compute + - nova-conductor + - nova-scheduler + +# Endpoint used throughout various services, including nova +nova_metadata_ip: "{{ internal_vip_address }}" +nova_metadata_proxy_shared_secret: "{{ nova_metadata_proxy_secret }}" + + +## Nova global config +nova_cpu_mode: host-model +nova_linuxnet_interface_driver: nova.network.linux_net.NeutronLinuxBridgeInterfaceDriver +nova_libvirt_vif_driver: nova.virt.libvirt.vif.NeutronLinuxBridgeVIFDriver +nova_firewall_driver: nova.virt.firewall.NoopFirewallDriver +nova_compute_driver: libvirt.LibvirtDriver +nova_max_age: 0 + +## Git Source +git_repo: https://git.openstack.org/openstack/nova +git_fallback_repo: https://github.com/openstack/nova +git_etc_example: etc/nova/ +git_install_branch: stable/icehouse + +service_pip_dependencies: + - MySQL-python + - python-memcached + - pycrypto + - python-keystoneclient + - python-novaclient + - keystonemiddleware + +container_directories: + - /var/log/nova + - /var/lib/nova + - /var/lib/nova/cache/api + - /etc/nova + - /etc/nova/rootwrap.d + - /var/cache/nova + - /var/lock/nova + - /var/run/nova + +container_packages: + - libpq-dev + - open-iscsi + - vlan + - kpartx diff --git a/rpc_deployment/inventory/group_vars/rabbit.yml b/rpc_deployment/inventory/group_vars/rabbit.yml new file mode 100644 index 0000000000..10ed0f3ea2 --- /dev/null +++ b/rpc_deployment/inventory/group_vars/rabbit.yml @@ -0,0 +1,33 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +service_name: rabbitmq + +rabbitmq_key: + - "http://www.rabbitmq.com/rabbitmq-signing-key-public.asc" + +rabbit_repos: + - { repo: "deb http://www.rabbitmq.com/debian/ testing main", state: "present" } + +container_lvm_fstype: ext4 +container_lvm_fssize: 5GB +container_config_options: + - "lxc.aa_profile=lxc-openstack" + +rabbit_cookie: "{{ rabbitmq_cookie_token }}" + +enable_management_plugin: true + +rabbit_cluster_name: rpc diff --git a/rpc_deployment/inventory/group_vars/rsyslog.yml b/rpc_deployment/inventory/group_vars/rsyslog.yml new file mode 100644 index 0000000000..737156c483 --- /dev/null +++ b/rpc_deployment/inventory/group_vars/rsyslog.yml @@ -0,0 +1,27 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Variables for the rsyslog containers +# +service_name: rsyslog + +debug: False +verbose: True + +container_lvm_fstype: ext4 +container_lvm_fssize: 5GB + +apt_container_repos: + - { repo: "ppa:adiscon/v8-stable", state: "present" } diff --git a/rpc_deployment/inventory/group_vars/utility_all.yml b/rpc_deployment/inventory/group_vars/utility_all.yml new file mode 100644 index 0000000000..9319566d1f --- /dev/null +++ b/rpc_deployment/inventory/group_vars/utility_all.yml @@ -0,0 +1,37 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the utility group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +## Service Name +service_name: utility + +# Only used when the lxc vg is present on the target +container_lvm_fstype: ext4 +container_lvm_fssize: 5GB + +service_pip_dependencies: + - python-openstackclient + - python-cinderclient + - python-glanceclient + - python-heatclient + - python-keystoneclient + - python-neutronclient + - python-novaclient + - python-swiftclient + +container_packages: + - ruby1.9.1 diff --git a/rpc_deployment/inventory/hosts b/rpc_deployment/inventory/hosts new file mode 100644 index 0000000000..8bb7ba6b33 --- /dev/null +++ b/rpc_deployment/inventory/hosts @@ -0,0 +1,2 @@ +[local] +localhost diff --git a/rpc_deployment/library/keystone b/rpc_deployment/library/keystone new file mode 100644 index 0000000000..6c38c2ae54 --- /dev/null +++ b/rpc_deployment/library/keystone @@ -0,0 +1,832 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# (c) 2014, Kevin Carter +# +# 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 . + +# Based on Jimmy Tang's implementation + +DOCUMENTATION = """ +--- +module: keystone +version_added: "1.6.2" +short_description: + - Manage OpenStack Identity (keystone) users, tenants, roles, and endpoints. +description: + - Manage OpenStack Identity (keystone) users, tenants, roles, and endpoints. +options: + return_code: + description: + - Allow for return Codes other than 0 when executing commands. + - This is a comma separated list of acceptable return codes. + default: 0 + login_user: + description: + - login username to authenticate to keystone + required: false + default: admin + login_password: + description: + - Password of login user + required: false + default: 'yes' + login_tenant_name: + description: + - The tenant login_user belongs to + required: false + default: None + token: + description: + - The token to be uses in case the password is not specified + required: false + default: None + endpoint: + description: + - The keystone url for authentication + required: false + password: + description: + - The password to be assigned to the user + required: false + default: None + user_name: + description: + - The name of the user that has to added/removed from OpenStack + required: false + default: None + tenant_name: + description: + - The tenant name that has be added/removed + required: false + default: None + role_name: + description: + - The name of the role to be assigned or created + required: false + service_name: + description: + - Name of the service. + required: false + default: None + region_name: + description: + - Name of the region. + required: false + default: None + description: + description: + - A description for the tenant + required: false + default: None + email: + description: + - Email address for the user, this is only used in "ensure_user" + required: false + default: None + service_type: + description: + - Type of service. + required: false + default: None + publicurl: + description: + - Public URL. + required: false + default: None + adminurl: + description: + - Admin URL. + required: false + default: None + internalurl: + description: + - Internal URL. + required: false + default: None + command: + description: + - Indicate desired state of the resource + choices: ['get_tenant', 'get_user', 'get_role', 'ensure_service', + 'ensure_endpoint', 'ensure_role', 'ensure_user', + 'ensure_user_role', 'ensure_tenant'] + required: true +requirements: [ python-keystoneclient ] +author: Kevin Carter +""" + +EXAMPLES = """ +# Create an admin tenant +- keystone: > + command=ensure_tenant + tenant_name=admin + description="Admin Tenant" + +# Create a service tenant +- keystone: > + command=ensure_tenant + tenant_name=service + description="Service Tenant" + +# Create an admin user +- keystone: > + command=ensure_user + user_name=admin + tenant_name=admin + password=secrete + email="admin@some-domain.com" + +# Create an admin role +- keystone: > + command=ensure_role + role_name=admin + +# Create a user +- keystone: > + command=ensure_user + user_name=glance + tenant_name=service + password=secrete + email="glance@some-domain.com" + +# Add a role to a user +- keystone: > + command=ensure_user_role + user_name=glance + tenant_name=service + role_name=admin + +# Create a service +- keystone: > + command=ensure_service + service_name=glance + service_type=image + description="Glance Image Service" + +# Create an endpoint +- keystone: > + command=ensure_endpoint + region_name=RegionOne + service_name=glance + service_type=image + publicurl=http://127.0.0.1:9292 + adminurl=http://127.0.0.1:9292 + internalurl=http://127.0.0.1:9292 + +# Get tenant id +- keystone: > + command=get_tenant + tenant_name=admin + +# Get user id +- keystone: > + command=get_user + user_name=admin + +# Get role id +- keystone: > + command=get_role + user_name=admin + +""" + +COMMAND_MAP = { + 'get_tenant': { + 'variables': [ + 'tenant_name' + ] + }, + 'get_user': { + 'variables': [ + 'user_name' + ] + }, + 'get_role': { + 'variables': [ + 'role_name', + 'tenant_name', + 'user_name' + ] + }, + 'ensure_service': { + 'variables': [ + 'service_name', + 'service_type', + 'description' + ] + }, + 'ensure_endpoint': { + 'variables': [ + 'region_name', + 'service_name', + 'service_type', + 'publicurl', + 'adminurl', + 'internalurl' + ] + }, + 'ensure_role': { + 'variables': [ + 'role_name' + ] + }, + 'ensure_user': { + 'variables': [ + 'tenant_name', + 'user_name', + 'password', + 'email' + ] + }, + 'ensure_user_role': { + 'variables': [ + 'user_name', + 'tenant_name', + 'role_name' + ] + }, + 'ensure_tenant': { + 'variables': [ + 'tenant_name', + 'description' + ] + } +} + +try: + from keystoneclient.v2_0 import client +except ImportError: + keystoneclient_found = False +else: + keystoneclient_found = True + + +class ManageKeystone(object): + def __init__(self, module): + """Manage Keystone via Ansible.""" + self.state_change = False + self.keystone = None + + # Load AnsibleModule + self.module = module + + def command_router(self): + """Run the command as its provided to the module.""" + command_name = self.module.params['command'] + if command_name not in COMMAND_MAP: + self.failure( + error='No Command Found', + rc=2, + msg='Command [ %s ] was not found.' % command_name + ) + + action_command = COMMAND_MAP[command_name] + if hasattr(self, '%s' % command_name): + action = getattr(self, '%s' % command_name) + facts = action(variables=action_command['variables']) + if facts is None: + self.module.exit_json(changed=self.state_change) + else: + self.module.exit_json( + changed=self.state_change, + ansible_facts=facts + ) + else: + self.failure( + error='Command not in ManageKeystone class', + rc=2, + msg='Method [ %s ] was not found.' % command_name + ) + + @staticmethod + def _facts(facts): + """Return a dict for our Ansible facts. + + :param facts: ``dict`` Dict with data to return + """ + return {'keystone_facts': facts} + + def _get_vars(self, variables, required=None): + """Return a dict of all variables as found within the module. + + :param variables: ``list`` List of all variables that are available to + use within the Keystone Command. + :param required: ``list`` Name of variables that are required. + """ + return_dict = {} + for variable in variables: + return_dict[variable] = self.module.params.get(variable) + else: + if isinstance(required, list): + for var_name in required: + check = return_dict.get(var_name) + if check is None: + self.failure( + error='Missing [ %s ] from Task or found a None' + ' value' % var_name, + rc=000, + msg='variables %s - available params [ %s ]' + % (variables, self.module.params) + ) + return return_dict + + def failure(self, error, rc, msg): + """Return a Failure when running an Ansible command. + + :param error: ``str`` Error that occurred. + :param rc: ``int`` Return code while executing an Ansible command. + :param msg: ``str`` Message to report. + """ + self.module.fail_json(msg=msg, rc=rc, err=error) + + def _authenticate(self): + """Return a keystone client object.""" + required_vars = ['endpoint'] + variables = [ + 'endpoint', + 'login_user', + 'login_password', + 'login_tenant_name', + 'token' + ] + variables_dict = self._get_vars(variables, required=required_vars) + + endpoint = variables_dict.pop('endpoint') + login_user = variables_dict.pop('login_user') + login_password = variables_dict.pop('login_password') + login_tenant_name = variables_dict.pop('login_tenant_name') + token = variables_dict.pop('token') + + if token is None: + if login_tenant_name is None: + self.failure( + error='Missing Tenant Name', + rc=2, + msg='If you do not specify a token you must use a tenant' + ' name for authentication. Try adding' + ' [ login_tenant_name ] to the task' + ) + if login_password is None: + self.failure( + error='Missing Password', + rc=2, + msg='If you do not specify a token you must use a password' + ' name for authentication. Try adding' + ' [ login_password ] to the task' + ) + + if token: + self.keystone = client.Client(endpoint=endpoint, token=token) + else: + self.keystone = client.Client( + auth_url=endpoint, + username=login_user, + password=login_password, + tenant_name=login_tenant_name + ) + + def _get_tenant(self, name): + """Return tenant information. + + :param name: ``str`` Name of the tenant. + """ + for entry in self.keystone.tenants.list(): + if entry.name == name: + return entry + else: + return None + + def get_tenant(self, variables): + """Return a tenant id. + + This will return `None` if the ``name`` is not found. + + :param variables: ``list`` List of all variables that are available to + use within the Keystone Command. + """ + self._authenticate() + variables_dict = self._get_vars(variables, required=['tenant_name']) + tenant_name = variables_dict.pop('tenant_name') + tenant = self._get_tenant(name=tenant_name) + if tenant is None: + self.failure( + error='tenant [ %s ] was not found.' % tenant_name, + rc=2, + msg='tenant was not found, does it exist?' + ) + + return self._facts(facts={'id': tenant.id}) + + def ensure_tenant(self, variables): + """Create a new tenant within Keystone if it does not exist. + + Returns the tenant ID on a successful run. + + :param variables: ``list`` List of all variables that are available to + use within the Keystone Command. + """ + self._authenticate() + variables_dict = self._get_vars(variables, required=['tenant_name']) + tenant_name = variables_dict.pop('tenant_name') + tenant_description = variables_dict.pop('description') + if tenant_description is None: + tenant_description = 'Tenant %s' % tenant_name + + tenant = self._get_tenant(name=tenant_name) + if tenant is None: + self.state_change = True + tenant = self.keystone.tenants.create( + tenant_name=tenant_name, + description=tenant_description, + enabled=True + ) + + return self._facts(facts={'id': tenant.id}) + + def _get_user(self, name): + """Return a user information. + + This will return `None` if the ``name`` is not found. + + :param name: ``str`` Name of the user. + """ + for entry in self.keystone.users.list(): + if entry.name == name: + return entry + else: + return None + + def get_user(self, variables): + """Return a tenant id. + + This will return `None` if the ``name`` is not found. + + :param variables: ``list`` List of all variables that are available to + use within the Keystone Command. + """ + self._authenticate() + variables_dict = self._get_vars(variables, required=['user_name']) + user_name = variables_dict.pop('user_name') + user = self._get_user(name=user_name) + if user is None: + self.failure( + error='user [ %s ] was not found.' % user_name, + rc=2, + msg='user was not found, does it exist?' + ) + + return self._facts(facts={'id': user.id}) + + def ensure_user(self, variables): + """Create a new user within Keystone if it does not exist. + + Returns the user ID on a successful run. + + :param variables: ``list`` List of all variables that are available to + use within the Keystone Command. + """ + self._authenticate() + required_vars = ['tenant_name', 'user_name', 'password'] + variables_dict = self._get_vars(variables, required=required_vars) + tenant_name = variables_dict.pop('tenant_name') + password = variables_dict.pop('password') + user_name = variables_dict.pop('user_name') + email = variables_dict.pop('email') + + tenant = self._get_tenant(name=tenant_name) + if tenant is None: + self.failure( + error='tenant [ %s ] was not found.' % tenant_name, + rc=2, + msg='tenant was not found, does it exist?' + ) + + user = self._get_user(name=user_name) + if user is None: + self.state_change = True + user = self.keystone.users.create( + name=user_name, + password=password, + email=email, + tenant_id=tenant.id + ) + + return self._facts(facts={'id': user.id}) + + def _get_role(self, name): + """Return a tenant by name. + + This will return `None` if the ``name`` is not found. + + :param name: ``str`` Name of the role. + """ + for entry in self.keystone.roles.list(): + if entry.name == name: + return entry + else: + return None + + def get_role(self, variables): + """Return a tenant by name. + + This will return `None` if the ``name`` is not found. + + :param variables: ``list`` List of all variables that are available to + use within the Keystone Command. + """ + self._authenticate() + variables_dict = self._get_vars(variables, required=['role_name']) + role_name = variables_dict.pop('role_name') + role_data = self._get_role(name=role_name) + if role_data is None: + self.failure( + error='role [ %s ] was not found.' % role_name, + rc=2, + msg='role was not found, does it exist?' + ) + + return self._facts(facts={'id': role_data.id}) + + def _get_role_data(self, user_name, tenant_name, role_name): + user = self._get_user(name=user_name) + if user is None: + self.failure( + error='user [ %s ] was not found.' % user_name, + rc=2, + msg='User was not found, does it exist?' + ) + + tenant = self._get_tenant(name=tenant_name) + if tenant is None: + self.failure( + error='tenant [ %s ] was not found.' % tenant_name, + rc=2, + msg='tenant was not found, does it exist?' + ) + + role = self._get_role(name=role_name) + if role is None: + self.failure( + error='role [ %s ] was not found.' % role_name, + rc=2, + msg='role was not found, does it exist?' + ) + + return user, tenant, role + + def ensure_role(self, variables): + """Create a new role within Keystone if it does not exist. + + Returns the user ID on a successful run. + + :param variables: ``list`` List of all variables that are available to + use within the Keystone Command. + """ + self._authenticate() + variables_dict = self._get_vars(variables, required=['role_name']) + role_name = variables_dict.pop('role_name') + + role = self._get_role(name=role_name) + if role is None: + self.state_change = True + role = self.keystone.roles.create(role_name) + + return self._facts(facts={'id': role.id}) + + def _get_user_roles(self, name, user, tenant): + for entry in self.keystone.users.list_roles(user, tenant.id): + if entry.name == name: + return entry + else: + return None + + def ensure_user_role(self, variables): + self._authenticate() + required_vars = ['user_name', 'tenant_name', 'role_name'] + variables_dict = self._get_vars(variables, required=required_vars) + user_name = variables_dict.pop('user_name') + tenant_name = variables_dict.pop('tenant_name') + role_name = variables_dict.pop('role_name') + + user, tenant, role = self._get_role_data( + user_name=user_name, tenant_name=tenant_name, role_name=role_name + ) + + user_role = self._get_user_roles( + name=role_name, user=user, tenant=tenant + ) + + if user_role is None: + self.keystone.roles.add_user_role( + user=user, role=role, tenant=tenant + ) + user_role = self._get_user_roles( + name=role_name, user=user, tenant=tenant + ) + + return self._facts(facts={'id': user_role.id}) + + def _get_service(self, name, srv_type=None): + for entry in self.keystone.services.list(): + if srv_type is not None: + if entry.type == srv_type and name == entry.name: + return entry + elif entry.name == name: + return entry + else: + return None + + def ensure_service(self, variables): + """Create a new service within Keystone if it does not exist. + + Returns the service ID on a successful run. + + :param variables: ``list`` List of all variables that are available to + use within the Keystone Command. + """ + self._authenticate() + required_vars = ['service_name', 'service_type'] + variables_dict = self._get_vars(variables, required=required_vars) + + service_name = variables_dict.pop('service_name') + description = variables_dict.pop('description') + service_type = variables_dict.pop('service_type') + + service = self._get_service(name=service_name, srv_type=service_type) + if service is None or service.type != service_type: + self.state_change = True + service = self.keystone.services.create( + name=service_name, + service_type=service_type, + description=description + ) + + return self._facts(facts={'id': service.id}) + + def _get_endpoint(self, region, publicurl, adminurl, internalurl): + for entry in self.keystone.endpoints.list(): + check = [ + entry.region == region, + entry.publicurl == publicurl, + entry.adminurl == adminurl, + entry.internalurl == internalurl + ] + if all(check): + return entry + else: + return None + + def ensure_endpoint(self, variables): + """Create a new endpoint within Keystone if it does not exist. + + Returns the endpoint ID on a successful run. + + :param variables: ``list`` List of all variables that are available to + use within the Keystone Command. + """ + self._authenticate() + required_vars = [ + 'region_name', + 'service_name', + 'service_type', + 'publicurl', + 'adminurl', + 'internalurl' + ] + variables_dict = self._get_vars(variables, required=required_vars) + + service_name = variables_dict.pop('service_name') + service_type = variables_dict.pop('service_type') + region = variables_dict.pop('region_name') + publicurl = variables_dict.pop('publicurl') + adminurl = variables_dict.pop('adminurl') + internalurl = variables_dict.pop('internalurl') + + service = self._get_service(name=service_name, srv_type=service_type) + if service is None: + self.failure( + error='service [ %s ] was not found.' % service_name, + rc=2, + msg='Service was not found, does it exist?' + ) + + endpoint = self._get_endpoint( + region=region, + publicurl=publicurl, + adminurl=adminurl, + internalurl=internalurl + ) + if endpoint is None: + self.state_change = True + endpoint = self.keystone.endpoints.create( + region=region, + service_id=service.id, + publicurl=publicurl, + adminurl=adminurl, + internalurl=internalurl + ) + + return self._facts(facts={'id': endpoint.id}) + + +def main(): + module = AnsibleModule( + argument_spec=dict( + login_user=dict( + required=False + ), + login_password=dict( + required=False + ), + login_tenant_name=dict( + required=False + ), + token=dict( + required=False + ), + password=dict( + required=False + ), + endpoint=dict( + required=True, + ), + user_name=dict( + required=False + ), + tenant_name=dict( + required=False + ), + role_name=dict( + required=False + ), + service_name=dict( + required=False + ), + region_name=dict( + required=False + ), + description=dict( + required=False + ), + email=dict( + required=False + ), + service_type=dict( + required=False + ), + publicurl=dict( + required=False + ), + adminurl=dict( + required=False + ), + internalurl=dict( + required=False + ), + command=dict( + required=True, + choices=COMMAND_MAP.keys() + ), + return_code=dict( + type='str', + default='0' + ) + ), + supports_check_mode=False, + mutually_exclusive=[ + ['token', 'login_user'], + ['token', 'login_password'], + ['token', 'login_tenant_name'] + ] + ) + + km = ManageKeystone(module=module) + if not keystoneclient_found: + km.failure( + error='python-keystoneclient is missing', + rc=2, + msg='keystone client was not importable, is it installed?' + ) + + return_code = module.params.get('return_code', '').split(',') + module.params['return_code'] = return_code + km.command_router() + + +# import module snippets +from ansible.module_utils.basic import * +if __name__ == '__main__': + main() diff --git a/rpc_deployment/library/lxc b/rpc_deployment/library/lxc new file mode 100755 index 0000000000..1d5cdbae62 --- /dev/null +++ b/rpc_deployment/library/lxc @@ -0,0 +1,1588 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# (c) 2014, Kevin Carter +# (c) 2014, Hugh Saunders +# +# 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 . + + +import ast +import os +import shutil +import tempfile +import time + + +DOCUMENTATION = """ +--- +module: lxc +version_added: "1.6.2" +short_description: Manage LXC Containers +description: + - Management of LXC containers +options: + name: + description: + - Name of a container. + required: false + return_code: + description: + - Allow for return Codes other than 0 when executing commands. + This is a comma separated list of acceptable return codes. + default: 0 + backingstore: + description: + - Options 'dir', 'lvm', 'loop', 'btrfs', 'best'. The default is + 'none'. + required: false + template: + description: + - Name of the template to use within an LXC create. + required: false + default: ubuntu + template_options: + description: + - Template options when building the container. + required: false + config: + description: + - Path to the LXC configuration file. + required: false + default: /etc/lxc/default.conf + bdev: + description: + - Backend device for use with an LXC container. + required: false + lvname: + description: + - Backend store for lvm. + required: false + vgname: + description: + - If Backend store is lvm, specify the name of the volume group. + required: false + thinpool: + description: + - Use LVM thin pool called TP (Default lxc). + required: false + fstype: + description: + - Create fstype TYPE (Default ext3). + required: false + fssize: + description: + - Filesystem Size (Default 1G, default unit 1M). + required: false + dir: + description: + - Place rootfs directory under DIR. + required: false + zfsroot: + description: + - Create zfs under given zfsroot (Default tank/lxc). + required: false + container_command: + description: + - Run a command in a container. Only used in the "attach" operation. + required: false + return_facts: + description: + - Return stdout after an attach command. Only used in the "attach" + operation. + required: false + default: false + lxcpath: + description: + - Place container under PATH + required: false + snapshot: + description: + - The new container's rootfs should be a LVM or btrfs snapshot of + the original. Only used in "clone" operation. + required: false + keepname: + description: + - Do not change the hostname of the container (in the root + filesystem). Only used in "clone" operation. + required: false + newpath: + description: + - The lxcpath for the new container. Only used in "clone" operation. + required: false + orig: + description: + - The name of the original container to clone. Only used in "clone" + operation. + required: false + new: + description: + - The name of the new container to create. Only used in "clone" + operation. + required: false + state: + choices: + - running + - stopped + description: + - Start a container right after it's created. + required: false + default: 'running' + options: + description: + - Dictionary of options to use in a containers configuration. Only + used in "config" operation. When dropping additional configuration + options the values are strings IE "key=value", see example section + for more details. + required: false + command: + choices: + - list + - create + - destroy + - info + - attach + - start + - stop + - restart + - config + - createtar + - clone + description: + - Type of command to run, see Examples. + required: true +author: Kevin Carter, Hugh Saunders +requirements: ['lxc >= 1.0'] +""" + +EXAMPLES = """ +# Create a new LXC container. +- lxc: name=test-container + template=ubuntu + config=/etc/lxc/lxc-rpc.conf + command=create + state=running + +# Create tar archive from Container this is a bzip2 compressed archive +- lxc: name="{{ container_name }}" + command=createtar + tarpath="/tmp/{{ container_name }}" + +# Run a command within a built and started container. +- lxc: name=test-container + container_command="git clone https://github.com/cloudnull/lxc_defiant" + command=attach + +# List all containers and return a dict of all found information +- lxc: command=list + +# Get information on a given container. +- lxc: name=test-container + command=info + +# Stop a container. +- lxc: name=test-container + command=stop + +# Start a container. +- lxc: name=test-container + command=start + +# Restart a container. +- lxc: name=test-container + command=restart + +# Update the configuration for a container. +# Uses a list of "key=value" pairs. +container_config_options: + - 'cpuset.cpus="0,3"' + - 'lxc.cgroup.devices.allow="a rmw"' + +- lxc: name=test-container + command=config + options="{{ container_config_options }}" + +# Clone a container. +- lxc: orig=test-container + new=test-container-new + command=clone + state=started + +# Destroy a container. +- lxc: name=test-container + command=destroy +""" + + +COMMAND_MAP = { + 'list': { + 'command': 'container_list', + 'variables': [ + 'lxcpath' + ], + }, + 'create': { + 'command': 'container_create', + 'variables': [ + 'name', + 'config', + 'template', + 'bdev', + 'template', + 'lxcpath', + 'lvname', + 'vgname', + 'thinpool', + 'fstype', + 'fssize', + 'dir', + 'zfsroot', + 'template_options', + 'state' + ] + }, + 'destroy': { + 'command': 'container_destroy', + 'variables': [ + 'name', + 'lxcpath' + ], + }, + 'clone': { + 'command': 'container_clone', + 'variables': [ + 'keepname', + 'snapshot', + 'fssize', + 'lxcpath', + 'newpath', + 'backingstore', + 'orig', + 'new', + 'state' + ] + }, + 'info': { + 'command': 'container_info', + 'variables': [ + 'name', + 'lxcpath' + ], + }, + 'attach': { + 'command': 'container_attach', + 'variables': [ + 'name', + 'lxcpath', + 'container_command', + 'return_facts' + ], + }, + 'start': { + 'command': 'container_start', + 'variables': [ + 'name', + 'lxcpath' + ], + }, + 'stop': { + 'command': 'container_stop', + 'variables': [ + 'name', + 'lxcpath' + ], + }, + 'restart': { + 'command': 'container_restart', + 'variables': [ + 'name', + 'lxcpath' + ], + }, + 'config': { + 'command': 'container_config', + 'variables': [ + 'name', + 'lxcpath', + 'options', + 'state' + ], + }, + 'createtar': { + 'command': 'container_create_tar', + 'variables': [ + 'name', + 'lxcpath', + 'tarpath' + ], + } +} + + +# This is used to attach to a running container and execute commands from +# within the container on the host. This will provide local access to a +# container without using SSH. The template will attempt to work within the +# home directory of the user that was attached to the conatiner and source +# that users environment variables by default. +ATTACH_TEMPLATE = """ +%(command)s < greater than [ %s ] on volume group' + ' [ %s ]' % (snapshot_size_gb, free_space, vg) + ) + self.failure( + error='Not enough space to create snapshot', + rc=2, + msg=message + ) + + # Create LVM Snapshot + build_command = [ + self.module.get_bin_path('lvcreate', True), + "-n", + snapshot_name, + "-s", + os.path.join(vg, source_lv), + "-L%sg" % snapshot_size_gb + ] + rc, stdout, err = self._run_command(build_command) + if rc not in self.rc: + msg = ( + 'Failed to Create LVM snapshot %(vg)s/%(source_lv)s' + ' --> %(snapshot_name)s' + % {'vg': vg, + 'source_lv': source_lv, + 'snapshot_name': snapshot_name} + ) + self.failure(err, rc, msg) + + def _lvm_lv_remove(self, name): + vg = self._get_lxc_vg() + # Create LVM Snapshot + build_command = [ + self.module.get_bin_path('lvremove', True), + "-f", + "%(vg)s/%(name)s" % dict(vg=vg, name=name), + ] + rc, stdout, err = self._run_command(build_command) + if rc not in self.rc: + msg = ("Failed to remove LVM LV %(vg)s/%(name)s " + % {'vg': vg, + 'name': name}) + self.failure(err, rc, msg) + + def _lvm_lv_mount(self, lv_name, mount_point): + # mount an lv + vg = self._get_lxc_vg() + build_command = [ + self.module.get_bin_path('mount', True), + "/dev/%(vg)s/%(lv_name)s" % dict(vg=vg, lv_name=lv_name), + mount_point, + ] + rc, stdout, err = self._run_command(build_command) + if rc not in self.rc: + msg = ("failed to mountlvm lv %(vg)s/%(lv_name)s to %(mp)s" + % {'vg': vg, + 'lv_name': lv_name, + 'mp': mount_point}) + self.failure(err, rc, msg) + + def _unmount(self, mount_point): + # Unmount a file system + build_command = [ + self.module.get_bin_path('umount', True), + mount_point, + ] + rc, stdout, err = self._run_command(build_command) + if rc not in self.rc: + msg = ("failed to unmount %(mp)s" % {'mp': mount_point}) + self.failure(err, rc, msg) + + def _create_tar(self, source_dir, archive_name): + """Create an archive of a given ``source_dir`` to ``output_path``. + + :param source_dir: ``str`` Path to the directory to be archived. + :param archive_name: ``str`` Name of the archive file. + """ + # remove trailing / if present. + output_path = archive_name.rstrip(os.sep) + if not output_path.endswith('tar.bz2'): + output_path = '%s.tar.bz2' % output_path + + source_path = os.path.expanduser(source_dir) + build_command = [ + self.module.get_bin_path('tar', True), + '--directory=%s' % source_path, + '-cjf', + output_path, + '.' + ] + + rc, stdout, err = self._run_command( + build_command=build_command, unsafe_shell=True + ) + + if rc not in self.rc: + msg = "failed to create tar archive [ %s ]" % build_command + self.failure(err, rc, msg) + + return output_path + + @staticmethod + def _roundup(num): + """Return a rounded floating point number. + + :param num: ``float`` Number to round up. + """ + num, part = str(num).split('.') + num = int(num) + if int(part) != 0: + num += 1 + return num + + def _container_create_tar(self, variables): + """Create a tar archive from an LXC container. + + The process is as follows: + * Freeze the container (pause processes) + * Create temporary dir + * Copy container config to tmpdir/ + * Unfreeze the container + * If LVM backed: + * Create LVM snapshot of LV backing the container + * Mount the snapshot to tmpdir/rootfs + * Create tar of tmpdir + * Clean up + + :param variables: ``list`` List of all variables that are available to + use within the LXC Command + """ + required_vars = ['name', 'tarpath'] + variables_dict = self._get_vars(variables, required=required_vars) + name = variables_dict.pop('name') + + lxc_config_path = self._load_lxcpath(variables_dict) + + config_file, options = self._load_config(lxc_config_path, name) + lxc_rootfs = [i for i in options if i.startswith('lxc.rootfs')] + if lxc_rootfs: + root_path = [i.strip() for i in lxc_rootfs[0].split('=')][1] + else: + message = ( + 'Check the config file for container [ %s ] @ [ %s ]' + % (name, config_file) + ) + return self.failure( + error='No rootfs entry found in config.', + rc=2, + msg=message + ) + + # Create a temp dir + temp_dir = tempfile.mkdtemp() + + # Set the name of the working dir, temp + container_name + work_dir = os.path.join(temp_dir, name) + + # Set the path to the container data + container_path = os.path.join(lxc_config_path, name) + + # Get current container info + container_data = self._get_container_info( + name=name, variables_dict=variables_dict + ) + + # set current state + state = container_data.get('state') + + # Ensure the original container is stopped or frozen + if state not in ['stopped', 'frozen']: + # Freeze Container + self._ensure_state( + state='frozen', name=name, variables_dict=variables_dict + ) + + # Prepare tmp dir + build_command = [ + self.module.get_bin_path('rsync', True), + '-aHAX', + container_path, + temp_dir + ] + rc, stdout, err = self._run_command(build_command, unsafe_shell=True) + if rc not in self.rc: + self.failure(err, rc, msg='failed to perform backup') + + mount_point = os.path.join(work_dir, 'rootfs') + if not os.path.exists(mount_point): + os.makedirs(mount_point) + + # Restore original state of container + self._ensure_state( + state=state, name=name, variables_dict=variables_dict + ) + + # Test if the containers rootfs is a block device + block_backed = root_path.startswith(os.path.join(os.sep, 'dev')) + snapshot_name = '%s_rpc_ansible_snapshot' % name + + if block_backed: + if snapshot_name not in self._lvm_lv_list(): + # Take snapshot + size, measurement = self._get_lv_size(name=name) + self._lvm_snapshot_create( + source_lv=name, + snapshot_name=snapshot_name, + snapshot_size_gb=self._roundup(num=size) + ) + + # Mount snapshot + self._lvm_lv_mount( + lv_name=snapshot_name, mount_point=mount_point + ) + + try: + # Create Tar + archive_file = self._create_tar( + source_dir=work_dir, archive_name=variables_dict['tarpath'] + ) + except Exception as exp: + self.failure(error=exp, rc=2, msg='Failed to create the archive') + else: + # Set the state as changed and set a new fact + self.state_change = True + archive_fact = { + name: { + 'archive': archive_file + } + } + return self._lxc_facts(facts=archive_fact) + finally: + if block_backed: + # unmount snapshot + self._unmount(mount_point) + + # Remove snapshot + self._lvm_lv_remove(snapshot_name) + + # Remove tmpdir + shutil.rmtree(os.path.dirname(work_dir)) + + +def main(): + """Ansible Main module.""" + module = AnsibleModule( + argument_spec=dict( + name=dict( + type='str' + ), + return_code=dict( + type='str', + default='0' + ), + template=dict( + type='str', + default='ubuntu' + ), + backingstore=dict( + type='str' + ), + template_options=dict( + type='str' + ), + config=dict( + type='str', + default='/etc/lxc/default.conf' + ), + bdev=dict( + type='str' + ), + lvname=dict( + type='str' + ), + vgname=dict( + type='str' + ), + thinpool=dict( + type='str' + ), + fstype=dict( + type='str' + ), + fssize=dict( + type='str' + ), + dir=dict( + type='str' + ), + zfsroot=dict( + type='str' + ), + lxcpath=dict( + type='str' + ), + keepname=dict( + choices=BOOLEANS, + default='false' + ), + snapshot=dict( + choices=BOOLEANS, + default='false' + ), + newpath=dict( + type='str' + ), + orig=dict( + type='str' + ), + new=dict( + type='str' + ), + state=dict( + choices=[ + 'running', + 'stopped' + ], + default='running' + ), + command=dict( + required=True, + choices=COMMAND_MAP.keys() + ), + container_command=dict( + type='str' + ), + options=dict( + type='str' + ), + return_facts=dict( + choices=BOOLEANS, + default=False + ), + tarpath=dict( + type='str' + ) + ), + supports_check_mode=False, + ) + + return_code = module.params.get('return_code', '').split(',') + module.params['return_code'] = return_code + + lm = LxcManagement(module=module) + lm.command_router() + + +# import module bits +from ansible.module_utils.basic import * +main() diff --git a/rpc_deployment/library/name2int b/rpc_deployment/library/name2int new file mode 100644 index 0000000000..845472c77c --- /dev/null +++ b/rpc_deployment/library/name2int @@ -0,0 +1,80 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# (c) 2014, Kevin Carter +# +# 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 . + +DOCUMENTATION = """ +--- +module: name2int +version_added: "1.6.6" +short_description: + - hash a host name and return an integer +description: + - hash a host name and return an integer +options: + name: + description: + - login username + required: true +author: Kevin Carter +""" + +EXAMPLES = """ +# Create a new container +- name2int: + name: "Some-hostname.com" +""" + +import hashlib +import platform + + +class HashHostname(object): + def __init__(self, module): + """Generate an integer from a name.""" + self.module = module + + def return_hashed_host(self, name): + hashed_name = hashlib.md5(name).hexdigest() + hash_int = int(hashed_name, 32) + real_int = int(hash_int % 300) + return real_int + + +def main(): + module = AnsibleModule( + argument_spec=dict( + name=dict( + required=True + ) + ), + supports_check_mode=False + ) + try: + sm = HashHostname(module=module) + int_value = sm.return_hashed_host(platform.node()) + resp = {'int_value': int_value} + module.exit_json(changed=True, **resp) + except Exception as exp: + resp = {'stderr': exp} + module.fail_json(msg='Failed Process', **resp) + +# import module snippets +from ansible.module_utils.basic import * +if __name__ == '__main__': + main() diff --git a/rpc_deployment/library/swift b/rpc_deployment/library/swift new file mode 100644 index 0000000000..11f360b7af --- /dev/null +++ b/rpc_deployment/library/swift @@ -0,0 +1,633 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# (c) 2014, Kevin Carter +# +# 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 . + +DOCUMENTATION = """ +--- +module: swift +version_added: "1.6.2" +short_description: + - Manage objects stored in swift +description: + - Manage objects stored in swift +options: + login_user: + description: + - login username + required: true + login_password: + description: + - Password of login user + required: true + login_tenant_name: + description: + - The tenant login_user belongs to + required: false + default: None + login_url: + description: + - Authentication URL + required: true + region: + description: + - The password to be assigned to the user + required: false + container: + description: + - Name of container + required: true + src: + description: + - path to object. Only used for in 'upload' & 'download' command + required: false + object: + description: + - Name of object + required: false + config_file: + description: + - Path to credential file + required: false + section: + description: + - Section within ``config_file`` to load + required: false + default: default + auth_version: + description: + - Swift authentication version + default: 2.0 + required: false + snet: + description: + - Enable service Net. This may not be supported by all providers + set true or false + default: false + marker: + description: + - Set beginning marker. Only used in 'list' command. + default: false + end_marker: + description: + - Set ending marker. Only used in 'list' command. + default: false + limit: + description: + - Set limit. Only used in 'list' command. + default: false + prefix: + description: + - Set prefix filter. Only used in 'list' command. + default: false + command: + description: + - Indicate desired state of the resource + choices: ['upload', 'download', 'delete', 'create', 'list'] + required: true +notes: + - Environment variables can be set for all auth credentials which allows + for seemless access. The available environment variables are, + OS_USERNAME, OS_PASSWORD, OS_TENANT_ID, OS_AUTH_URL + - A configuration file can be used to load credentials, use ``config_file`` + to source the file. If you have multiple sections within the + configuration file use the ``section`` argument to define the section, + however the default is set to "default". +requirements: [ python-swiftclient ] +author: Kevin Carter +""" + +EXAMPLES = """ +# Create a new container +- swift: > + login_user="SomeUser" + login_password="SomePassword" + login_url="https://identity.somedomain.com/v2.0/" + command=create + container=MyNewContainer + +# Upload a new object +- swift: > + login_user="SomeUser" + login_password="SomePassword" + login_url="https://identity.somedomain.com/v2.0/" + command=upload + container=MyNewContainer + src=/path/to/file + object=MyNewObjectName + +# Download an object +- swift: > + login_user="SomeUser" + login_password="SomePassword" + login_url="https://identity.somedomain.com/v2.0/" + command=download + container=MyNewContainer + src=/path/to/file + object=MyOldObjectName + +# list up-to 10K objects +- swift: > + login_user="SomeUser" + login_password="SomePassword" + login_url="https://identity.somedomain.com/v2.0/" + command=list + container=MyNewContainer + +# Delete an Object +- swift: > + login_user="SomeUser" + login_password="SomePassword" + login_url="https://identity.somedomain.com/v2.0/" + command=delete + container=MyNewContainer + object=MyOldObjectName + +# Delete a container +- swift: > + login_user="SomeUser" + login_password="SomePassword" + login_url="https://identity.somedomain.com/v2.0/" + command=delete + container=MyNewContainer +""" + +COMMAND_MAP = { + 'upload': { + 'variables': [ + 'login_user', + 'login_password', + 'login_tenant_name', + 'login_url', + 'region', + 'container', + 'src', + 'object', + 'auth_version' + ] + }, + 'download': { + 'variables': [ + 'login_user', + 'login_password', + 'login_tenant_name', + 'login_url', + 'region', + 'container', + 'src', + 'object', + 'auth_version' + ] + }, + 'delete': { + 'variables': [ + 'login_user', + 'login_password', + 'login_tenant_name', + 'login_url', + 'region', + 'container', + 'object', + 'auth_version' + ] + }, + 'create': { + 'variables': [ + 'login_user', + 'login_password', + 'login_tenant_name', + 'login_url', + 'region', + 'container', + 'auth_version' + ] + }, + 'list': { + 'variables': [ + 'login_user', + 'login_password', + 'login_tenant_name', + 'login_url', + 'region', + 'container', + 'auth_version', + 'marker', + 'limit', + 'prefix', + 'end_marker' + ] + } +} + + +import ConfigParser + +try: + from swiftclient import client +except ImportError: + swiftclient_found = False +else: + swiftclient_found = True + + +class ManageSwift(object): + def __init__(self, module): + """Manage Swift via Ansible.""" + self.state_change = False + self.swift = None + + # Load AnsibleModule + self.module = module + + def command_router(self): + """Run the command as its provided to the module.""" + command_name = self.module.params['command'] + if command_name not in COMMAND_MAP: + self.failure( + error='No Command Found', + rc=2, + msg='Command [ %s ] was not found.' % command_name + ) + + action_command = COMMAND_MAP[command_name] + if hasattr(self, '_%s' % command_name): + action = getattr(self, '_%s' % command_name) + self._authenticate() + facts = action(variables=action_command['variables']) + if facts is None: + self.module.exit_json(changed=self.state_change) + else: + self.module.exit_json( + changed=self.state_change, + ansible_facts=facts + ) + else: + self.failure( + error='Command not in ManageSwift class', + rc=2, + msg='Method [ %s ] was not found.' % command_name + ) + + @staticmethod + def _facts(facts): + """Return a dict for our Ansible facts. + + :param facts: ``dict`` Dict with data to return + """ + return {'swift_facts': facts} + + def _get_vars(self, variables, required=None): + """Return a dict of all variables as found within the module. + + :param variables: ``list`` List of all variables that are available to + use within the Swift Command. + :param required: ``list`` Name of variables that are required. + """ + return_dict = {} + for variable in variables: + return_dict[variable] = self.module.params.get(variable) + else: + if isinstance(required, list): + for var_name in required: + check = return_dict.get(var_name) + if check is None: + self.failure( + error='Missing [ %s ] from Task or found a None' + ' value' % var_name, + rc=000, + msg='variables %s - available params [ %s ]' + % (variables, self.module.params) + ) + return return_dict + + def failure(self, error, rc, msg): + """Return a Failure when running an Ansible command. + + :param error: ``str`` Error that occurred. + :param rc: ``int`` Return code while executing an Ansible command. + :param msg: ``str`` Message to report. + """ + self.module.fail_json(msg=msg, rc=rc, err=error) + + def _env_vars(self, cred_file=None, section='default'): + """Load environment or sourced credentials. + + If the credentials are specified in either environment variables + or in a credential file the sourced variables will be loaded IF the + not set within the ``module.params``. + + :param cred_file: ``str`` Path to credentials file. + :param section: ``str`` Section within creds file to load. + """ + if cred_file: + parser = ConfigParser.SafeConfigParser() + parser.optionxform = str + parser.read(os.path.expanduser(cred_file)) + for name, value in parser.items(section): + if name == 'OS_AUTH_URL': + if not self.module.params.get('login_url'): + self.module.params['login_url'] = value + if name == 'OS_USERNAME': + if not self.module.params.get('login_user'): + self.module.params['login_user'] = value + if name == 'OS_PASSWORD': + if not self.module.params.get('login_password'): + self.module.params['login_password'] = value + if name == 'OS_TENANT_ID': + if not self.module.params.get('login_tenant_name'): + self.module.params['login_tenant_name'] = value + else: + if not self.module.params.get('login_url'): + authurl = os.getenv('OS_AUTH_URL') + self.module.params['login_url'] = authurl + + if not self.module.params.get('login_user'): + username = os.getenv('OS_USERNAME') + self.module.params['login_user'] = username + + if not self.module.params.get('login_password'): + password = os.getenv('OS_PASSWORD') + self.module.params['login_password'] = password + + if not self.module.params.get('login_tenant_name'): + tenant = os.getenv('OS_TENANT_ID') + self.module.params['login_tenant_name'] = tenant + + def _authenticate(self): + """Return a swift client object.""" + cred_file = self.module.params.pop('config_file', None) + section = self.module.params.pop('section') + self._env_vars(cred_file=cred_file, section=section) + + required_vars = ['login_url', 'login_user', 'login_password'] + variables = [ + 'login_url', + 'login_user', + 'login_password', + 'login_tenant_name', + 'region', + 'auth_version', + 'snet' + ] + variables_dict = self._get_vars(variables, required=required_vars) + + login_url = variables_dict.pop('login_url') + login_user = variables_dict.pop( + 'login_user', os.getenv('OS_AUTH_URL') + ) + login_password = variables_dict.pop( + 'login_password', os.getenv('OS_AUTH_URL') + ) + login_tenant_name = variables_dict.pop( + 'login_tenant_name', os.getenv('OS_TENANT_ID') + ) + region = variables_dict.pop('region', None) + + auth_version = variables_dict.pop('auth_version') + snet = variables_dict.pop('snet', None) + + if snet in BOOLEANS_TRUE: + snet = True + else: + snet = None + + if login_password is None: + self.failure( + error='Missing Password', + rc=2, + msg='A Password is required for authentication. Try adding' + ' [ login_password ] to the task' + ) + + if login_tenant_name is None: + login_tenant_name = ' ' + + creds_dict = { + 'user': login_user, + 'key': login_password, + 'authurl': login_url, + 'tenant_name': login_tenant_name, + 'os_options': { + 'region': region + }, + 'snet': snet, + 'auth_version': auth_version + } + + self.swift = client.Connection(**creds_dict) + + def _upload(self, variables): + """Upload an object to a swift object store. + + :param variables: ``list`` List of all variables that are available to + use within the Keystone Command. + """ + required_vars = ['container', 'src', 'object'] + variables_dict = self._get_vars(variables, required=required_vars) + + container_name = variables_dict.pop('container') + object_name = variables_dict.pop('object') + src_path = variables_dict.pop('src') + + self._create_container(container_name=container_name) + with open(src_path, 'rb') as f: + self.swift.put_object(container_name, object_name, contents=f) + + object_data = self.swift.head_object(container_name, object_name) + self.state_change = True + return self._facts(facts=[object_data]) + + def _download(self, variables): + """Upload an object to a swift object store. + + :param variables: ``list`` List of all variables that are available to + use within the Keystone Command. + """ + required_vars = ['container', 'src', 'object'] + variables_dict = self._get_vars(variables, required=required_vars) + + container_name = variables_dict.pop('container') + object_name = variables_dict.pop('object') + src_path = variables_dict.pop('src') + + with open(src_path, 'wb') as f: + f.write( + self.swift.get_object( + container_name, object_name, resp_chunk_size=204800 + ) + ) + + self.state_change = True + + def _delete(self, variables): + """Upload an object to a swift object store. + + If the ``object`` variable is not used the container will be deleted. + This assumes that the container is empty. + + :param variables: ``list`` List of all variables that are available to + use within the Keystone Command. + """ + required_vars = ['container'] + variables_dict = self._get_vars(variables, required=required_vars) + + container_name = variables_dict.pop('container') + object_name = variables_dict.pop('object', None) + + if object_name: + self.swift.delete_object(container_name, object_name) + else: + self.swift.delete_container(container_name) + + self.state_change = True + + def _create_container(self, container_name): + """Ensure a container exists. If it does not, it will be created. + + :param container_name: ``str`` Name of the container. + """ + try: + container = self.swift.head_container(container_name) + except client.ClientException: + self.swift.put_container(container_name) + else: + return container + + def _create(self, variables): + """Create a new container in swift. + + :param variables: ``list`` List of all variables that are available to + use within the Keystone Command. + """ + required_vars = ['container'] + variables_dict = self._get_vars(variables, required=required_vars) + + container_name = variables_dict.pop('container') + container_data = self._create_container(container_name=container_name) + + if not container_data: + container_data = self.swift.head_container(container_name) + + return self._facts(facts=[container_data]) + + def _list(self, variables): + """Return a list of objects or containers. + + If the ``container`` variable is not used this will return a list of + containers in the region. + + :param variables: ``list`` List of all variables that are available to + use within the Keystone Command. + """ + variables_dict = self._get_vars(variables) + + container_name = variables_dict.pop('container', None) + + filters = { + 'marker': variables_dict.pop('marker', None), + 'limit': variables_dict.pop('limit', None), + 'prefix': variables_dict.pop('prefix', None), + 'end_marker': variables_dict.pop('end_marker', None) + } + + if container_name: + list_data = self.swift.get_container(container_name, **filters)[1] + else: + list_data = self.swift.get_account(**filters)[1] + + return self._facts(facts=list_data) + + +def main(): + module = AnsibleModule( + argument_spec=dict( + login_user=dict( + required=False + ), + login_password=dict( + required=False + ), + login_tenant_name=dict( + required=False + ), + login_url=dict( + required=False + ), + config_file=dict( + required=False + ), + section=dict( + required=False, + default='default' + ), + command=dict( + required=True, + choices=COMMAND_MAP.keys() + ), + region=dict( + required=False + ), + container=dict( + required=False + ), + src=dict( + required=False + ), + object=dict( + required=False + ), + marker=dict( + required=False + ), + limit=dict( + required=False + ), + prefix=dict( + required=False + ), + end_marker=dict( + required=False + ), + auth_version=dict( + required=False, + default='2.0' + ), + snet=dict( + required=False, + default='false', + choices=BOOLEANS + ) + ), + supports_check_mode=False, + ) + + sm = ManageSwift(module=module) + if not swiftclient_found: + sm.failure( + error='python-swiftclient is missing', + rc=2, + msg='Swift client was not importable, is it installed?' + ) + + sm.command_router() + + +# import module snippets +from ansible.module_utils.basic import * +if __name__ == '__main__': + main() diff --git a/rpc_deployment/playbooks/add_host.yml b/rpc_deployment/playbooks/add_host.yml new file mode 100644 index 0000000000..c8821144f0 --- /dev/null +++ b/rpc_deployment/playbooks/add_host.yml @@ -0,0 +1,18 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: setup/host-setup.yml +- include: setup/build-containers.yml + diff --git a/rpc_deployment/playbooks/infrastructure/elasticsearch-install.yml b/rpc_deployment/playbooks/infrastructure/elasticsearch-install.yml new file mode 100644 index 0000000000..13e694391f --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/elasticsearch-install.yml @@ -0,0 +1,30 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Setup supporting services +- hosts: elasticsearch + user: root + roles: + - container_extra_setup + vars_files: + - vars/config_vars/container_config_elasticsearch.yml + +- hosts: elasticsearch + user: root + roles: + - common + - container_common + - logging_common + - elasticsearch diff --git a/rpc_deployment/playbooks/infrastructure/es2unix-install.yml b/rpc_deployment/playbooks/infrastructure/es2unix-install.yml new file mode 100644 index 0000000000..9203437a3f --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/es2unix-install.yml @@ -0,0 +1,21 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Setup supporting services +- hosts: utility_all + user: root + roles: + - logging_common + - utility_logging diff --git a/rpc_deployment/playbooks/infrastructure/galera-add-node.yml b/rpc_deployment/playbooks/infrastructure/galera-add-node.yml new file mode 100644 index 0000000000..e317df8a9b --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/galera-add-node.yml @@ -0,0 +1,21 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Restart each daemon in turn +- hosts: galera:!galera[0] + user: root + serial: 1 + roles: + - galera_restart diff --git a/rpc_deployment/playbooks/infrastructure/galera-bootstrap.yml b/rpc_deployment/playbooks/infrastructure/galera-bootstrap.yml new file mode 100644 index 0000000000..976c7965a2 --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/galera-bootstrap.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: galera[0] + user: root + roles: + - galera_bootstrap diff --git a/rpc_deployment/playbooks/infrastructure/galera-config.yml b/rpc_deployment/playbooks/infrastructure/galera-config.yml new file mode 100644 index 0000000000..89785512f6 --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/galera-config.yml @@ -0,0 +1,27 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: galera + user: root + roles: + - container_extra_setup + - common + - common_sudoers + - container_common + - galera_common + - galera_client_cnf + - galera_config + vars_files: + - vars/config_vars/container_config_galera.yml diff --git a/rpc_deployment/playbooks/infrastructure/galera-install.yml b/rpc_deployment/playbooks/infrastructure/galera-install.yml new file mode 100644 index 0000000000..41a725bee0 --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/galera-install.yml @@ -0,0 +1,18 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: galera-config.yml +- include: galera-startup.yml +- include: galera-post-config.yml diff --git a/rpc_deployment/playbooks/infrastructure/galera-post-config.yml b/rpc_deployment/playbooks/infrastructure/galera-post-config.yml new file mode 100644 index 0000000000..3b59e08839 --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/galera-post-config.yml @@ -0,0 +1,24 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: galera[0] + user: root + roles: + - galera_setup + +- hosts: galera + user: root + roles: + - galera_post_config diff --git a/rpc_deployment/playbooks/infrastructure/galera-remove.yml b/rpc_deployment/playbooks/infrastructure/galera-remove.yml new file mode 100644 index 0000000000..97b3fcd955 --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/galera-remove.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: galera + user: root + roles: + - galera_remove diff --git a/rpc_deployment/playbooks/infrastructure/galera-startup.yml b/rpc_deployment/playbooks/infrastructure/galera-startup.yml new file mode 100644 index 0000000000..a27ee6f6ff --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/galera-startup.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: galera-bootstrap.yml +- include: galera-add-node.yml diff --git a/rpc_deployment/playbooks/infrastructure/galera-stop.yml b/rpc_deployment/playbooks/infrastructure/galera-stop.yml new file mode 100644 index 0000000000..7784d01b1a --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/galera-stop.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: galera + user: root + roles: + - galera_stop diff --git a/rpc_deployment/playbooks/infrastructure/haproxy-install.yml b/rpc_deployment/playbooks/infrastructure/haproxy-install.yml new file mode 100644 index 0000000000..2068b73a91 --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/haproxy-install.yml @@ -0,0 +1,24 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Setup supporting services +- hosts: haproxy_hosts + user: root + roles: + - common + - haproxy_common + - haproxy_service + vars_files: + - vars/config_vars/haproxy_config.yml diff --git a/rpc_deployment/playbooks/infrastructure/infrastructure-setup.yml b/rpc_deployment/playbooks/infrastructure/infrastructure-setup.yml new file mode 100644 index 0000000000..5bfdd4b7ea --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/infrastructure-setup.yml @@ -0,0 +1,24 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: memcached-install.yml +- include: galera-install.yml +- include: rabbit-install.yml +- include: rsyslog-install.yml +- include: elasticsearch-install.yml +- include: logstash-install.yml +- include: kibana-install.yml +- include: es2unix-install.yml +- include: rsyslog-config.yml diff --git a/rpc_deployment/playbooks/infrastructure/inventory b/rpc_deployment/playbooks/infrastructure/inventory new file mode 120000 index 0000000000..f5a95b1299 --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/inventory @@ -0,0 +1 @@ +../../inventory/ \ No newline at end of file diff --git a/rpc_deployment/playbooks/infrastructure/kibana-install.yml b/rpc_deployment/playbooks/infrastructure/kibana-install.yml new file mode 100644 index 0000000000..cebe441f0f --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/kibana-install.yml @@ -0,0 +1,22 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Setup supporting services +- hosts: kibana + user: root + roles: + - common + - container_common + - kibana diff --git a/rpc_deployment/playbooks/infrastructure/library b/rpc_deployment/playbooks/infrastructure/library new file mode 120000 index 0000000000..63acaa1a76 --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/library @@ -0,0 +1 @@ +../../library/ \ No newline at end of file diff --git a/rpc_deployment/playbooks/infrastructure/logstash-config.yml b/rpc_deployment/playbooks/infrastructure/logstash-config.yml new file mode 100644 index 0000000000..283457f170 --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/logstash-config.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Setup supporting services +- hosts: logstash + user: root + roles: + - logstash diff --git a/rpc_deployment/playbooks/infrastructure/logstash-install.yml b/rpc_deployment/playbooks/infrastructure/logstash-install.yml new file mode 100644 index 0000000000..347b7792c8 --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/logstash-install.yml @@ -0,0 +1,31 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Setup supporting services +- hosts: logstash + user: root + roles: + - container_extra_setup + vars_files: + - vars/config_vars/container_config_logstash.yml + + +- hosts: logstash + user: root + roles: + - common + - container_common + - logging_common + - logstash diff --git a/rpc_deployment/playbooks/infrastructure/memcached-install.yml b/rpc_deployment/playbooks/infrastructure/memcached-install.yml new file mode 100644 index 0000000000..d80ece9e8d --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/memcached-install.yml @@ -0,0 +1,24 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: memcached + user: root + roles: + - container_extra_setup + - common + - container_common + - memcached + vars_files: + - vars/config_vars/container_config_memcached.yml diff --git a/rpc_deployment/playbooks/infrastructure/rabbit-add-node.yml b/rpc_deployment/playbooks/infrastructure/rabbit-add-node.yml new file mode 100644 index 0000000000..ad1327c31d --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/rabbit-add-node.yml @@ -0,0 +1,21 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: rabbit:!rabbit[0] + user: root + serial: 1 + roles: + - rabbit_user + - rabbit_join_cluster diff --git a/rpc_deployment/playbooks/infrastructure/rabbit-bootstrap.yml b/rpc_deployment/playbooks/infrastructure/rabbit-bootstrap.yml new file mode 100644 index 0000000000..e5576a3250 --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/rabbit-bootstrap.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: rabbit[0] + user: root + roles: + - rabbit_user + - rabbit_create_cluster diff --git a/rpc_deployment/playbooks/infrastructure/rabbit-config.yml b/rpc_deployment/playbooks/infrastructure/rabbit-config.yml new file mode 100644 index 0000000000..76130ab2f0 --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/rabbit-config.yml @@ -0,0 +1,22 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: rabbit + user: root + roles: + - common + - container_common + - container_extra_setup + - rabbit_common diff --git a/rpc_deployment/playbooks/infrastructure/rabbit-install.yml b/rpc_deployment/playbooks/infrastructure/rabbit-install.yml new file mode 100644 index 0000000000..4ce80c889e --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/rabbit-install.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: rabbit-config.yml +- include: rabbit-startup.yml diff --git a/rpc_deployment/playbooks/infrastructure/rabbit-remove.yml b/rpc_deployment/playbooks/infrastructure/rabbit-remove.yml new file mode 100644 index 0000000000..9e45fdc2df --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/rabbit-remove.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: rabbit + user: root + roles: + - rabbit_remove diff --git a/rpc_deployment/playbooks/infrastructure/rabbit-startup.yml b/rpc_deployment/playbooks/infrastructure/rabbit-startup.yml new file mode 100644 index 0000000000..3323904b9f --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/rabbit-startup.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: rabbit-bootstrap.yml +- include: rabbit-add-node.yml diff --git a/rpc_deployment/playbooks/infrastructure/roles b/rpc_deployment/playbooks/infrastructure/roles new file mode 120000 index 0000000000..148b132062 --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/roles @@ -0,0 +1 @@ +../../roles/ \ No newline at end of file diff --git a/rpc_deployment/playbooks/infrastructure/rsyslog-config.yml b/rpc_deployment/playbooks/infrastructure/rsyslog-config.yml new file mode 100644 index 0000000000..5858daa064 --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/rsyslog-config.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Setup supporting services +- hosts: rsyslog + user: root + roles: + - rsyslog_config diff --git a/rpc_deployment/playbooks/infrastructure/rsyslog-install.yml b/rpc_deployment/playbooks/infrastructure/rsyslog-install.yml new file mode 100644 index 0000000000..72e8e5f8ea --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/rsyslog-install.yml @@ -0,0 +1,25 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: rsyslog + user: root + roles: + - container_extra_setup + - common + - container_common + - safe_upgrade + - rsyslog + vars_files: + - vars/config_vars/container_config_rsyslog.yml diff --git a/rpc_deployment/playbooks/infrastructure/rsyslog-stop.yml b/rpc_deployment/playbooks/infrastructure/rsyslog-stop.yml new file mode 100644 index 0000000000..972b6ef280 --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/rsyslog-stop.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Setup supporting services +- hosts: rsyslog + user: root + roles: + - rsyslog_stop diff --git a/rpc_deployment/playbooks/infrastructure/vars b/rpc_deployment/playbooks/infrastructure/vars new file mode 120000 index 0000000000..efa2775e20 --- /dev/null +++ b/rpc_deployment/playbooks/infrastructure/vars @@ -0,0 +1 @@ +../../vars/ \ No newline at end of file diff --git a/rpc_deployment/playbooks/inventory b/rpc_deployment/playbooks/inventory new file mode 120000 index 0000000000..ea639e0626 --- /dev/null +++ b/rpc_deployment/playbooks/inventory @@ -0,0 +1 @@ +../inventory/ \ No newline at end of file diff --git a/rpc_deployment/playbooks/library b/rpc_deployment/playbooks/library new file mode 120000 index 0000000000..d6bf720fe4 --- /dev/null +++ b/rpc_deployment/playbooks/library @@ -0,0 +1 @@ +../library/ \ No newline at end of file diff --git a/rpc_deployment/playbooks/monitoring/handlers b/rpc_deployment/playbooks/monitoring/handlers new file mode 120000 index 0000000000..d5706936e9 --- /dev/null +++ b/rpc_deployment/playbooks/monitoring/handlers @@ -0,0 +1 @@ +../../handlers \ No newline at end of file diff --git a/rpc_deployment/playbooks/monitoring/inventory b/rpc_deployment/playbooks/monitoring/inventory new file mode 120000 index 0000000000..c743258cef --- /dev/null +++ b/rpc_deployment/playbooks/monitoring/inventory @@ -0,0 +1 @@ +../../inventory \ No newline at end of file diff --git a/rpc_deployment/playbooks/monitoring/library b/rpc_deployment/playbooks/monitoring/library new file mode 120000 index 0000000000..494d3c39e3 --- /dev/null +++ b/rpc_deployment/playbooks/monitoring/library @@ -0,0 +1 @@ +../../library \ No newline at end of file diff --git a/rpc_deployment/playbooks/monitoring/maas_dell_hardware.yml b/rpc_deployment/playbooks/monitoring/maas_dell_hardware.yml new file mode 100644 index 0000000000..b5def3324b --- /dev/null +++ b/rpc_deployment/playbooks/monitoring/maas_dell_hardware.yml @@ -0,0 +1,53 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: hosts + vars: + check_name: openmanage-memory + file_name: openmanage + check_details: file={{ file_name }}.py,args=chassis,args=memory + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + alarms: + - { 'name': 'hardware_memory_status', 'criteria': ':set consecutiveCount={{ maas_alarm_local_consecutive_count }} if (metric["hardware_memory_status"] != 1) { return new AlarmStatus(CRITICAL, "Physical Memory Error"); }' } + user: root + roles: + - maas_dell_hardware + +- hosts: hosts + vars: + check_name: openmanage-processors + file_name: openmanage + check_details: file={{ file_name }}.py,args=chassis,args=processors + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + alarms: + - { 'name': 'hardware_processors_status', 'criteria': ':set consecutiveCount={{ maas_alarm_local_consecutive_count }} if (metric["hardware_processors_status"] != 1) { return new AlarmStatus(CRITICAL, "Physical Processor Error"); }' } + user: root + roles: + - maas_dell_hardware + +- hosts: hosts + vars: + check_name: openmanage-vdisk + file_name: openmanage + check_details: file={{ file_name }}.py,args=storage,args=vdisk + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + alarms: + - { 'name': 'hardware_vdisk_status', 'criteria': ':set consecutiveCount={{ maas_alarm_local_consecutive_count }} if (metric["hardware_vdisk_status"] != 1) { return new AlarmStatus(CRITICAL, "Physical Disk Error"); }' } + user: root + roles: + - maas_dell_hardware diff --git a/rpc_deployment/playbooks/monitoring/maas_local.yml b/rpc_deployment/playbooks/monitoring/maas_local.yml new file mode 100644 index 0000000000..b6d503ddbf --- /dev/null +++ b/rpc_deployment/playbooks/monitoring/maas_local.yml @@ -0,0 +1,169 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: cinder_api_container + vars: + check_name: cinder_api_local_check + check_details: file={{ check_name }}.py,args={{ ansible_ssh_host }} + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + alarms: + - { 'name': 'cinder_api_local_status', 'criteria': ':set consecutiveCount={{ maas_alarm_local_consecutive_count }} if (metric["cinder_api_local_status"] != 1) { return new AlarmStatus(CRITICAL, "API unavailable"); }' } + user: root + roles: + - maas_local + +- hosts: glance_api + vars: + check_name: glance_api_local_check + check_details: file={{ check_name }}.py,args={{ ansible_ssh_host }} + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + alarms: + - { 'name': 'glance_api_local_status', 'criteria': ':set consecutiveCount={{ maas_alarm_local_consecutive_count }} if (metric["glance_api_local_status"] != 1) { return new AlarmStatus(CRITICAL, "API unavailable"); }' } + user: root + roles: + - maas_local + +- hosts: glance_registry + vars: + check_name: glance_registry_local_check + check_details: file={{ check_name }}.py,args={{ ansible_ssh_host }} + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + alarms: + - { 'name': 'glance_registry_local_status', 'criteria': ':set consecutiveCount={{ maas_alarm_local_consecutive_count }} if (metric["glance_registry_local_status"] != 1) { return new AlarmStatus(CRITICAL, "API unavailable"); }' } + user: root + roles: + - maas_local + +- hosts: heat_apis_container + vars: + check_name: heat_api_local_check + check_details: file={{ check_name }}.py,args={{ ansible_ssh_host }} + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + alarms: + - { 'name': 'heat_api_local_status', 'criteria': ':set consecutiveCount={{ maas_alarm_local_consecutive_count }} if (metric["heat_api_local_status"] != 1) { return new AlarmStatus(CRITICAL, "API unavailable"); }' } + user: root + roles: + - maas_local + +- hosts: heat_apis_container + vars: + check_name: heat_cfn_api_check + check_details: file=service_api_local_check.py,args=heat_cfn,args={{ ansible_ssh_host }},args=8000 + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + alarms: + - { 'name': 'heat_cfn_api_local_status', 'criteria': ':set consecutiveCount={{ maas_alarm_local_consecutive_count }} if (metric["nova_spice_api_local_status"] != 1) { return new AlarmStatus(CRITICAL, "API unavailable"); }' } + user: root + roles: + - maas_local + +- hosts: heat_apis_container + vars: + check_name: heat_cw_api_check + check_details: file=service_api_local_check.py,args=heat_cw,args={{ ansible_ssh_host }},args=8003 + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + alarms: + - { 'name': 'heat_cw_api_local_status', 'criteria': ':set consecutiveCount={{ maas_alarm_local_consecutive_count }} if (metric["nova_spice_api_local_status"] != 1) { return new AlarmStatus(CRITICAL, "API unavailable"); }' } + user: root + roles: + - maas_local + +- hosts: keystone + vars: + check_name: keystone_api_local_check + check_details: file={{ check_name }}.py,args={{ ansible_ssh_host }} + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + alarms: + - { 'name': 'keystone_api_local_status', 'criteria': ':set consecutiveCount={{ maas_alarm_local_consecutive_count }} if (metric["keystone_api_local_status"] != 1) { return new AlarmStatus(CRITICAL, "API unavailable"); }' } + user: root + roles: + - maas_local + +- hosts: neutron_server + vars: + check_name: neutron_api_local_check + check_details: file={{ check_name }}.py,args={{ ansible_ssh_host }} + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + alarms: + - { 'name': 'neutron_api_local_status', 'criteria': ':set consecutiveCount={{ maas_alarm_local_consecutive_count }} if (metric["neutron_api_local_status"] != 1) { return new AlarmStatus(CRITICAL, "API unavailable"); }' } + user: root + roles: + - maas_local + +- hosts: nova_api_os_compute + vars: + check_name: nova_api_local_check + check_details: file={{ check_name }}.py,args={{ ansible_ssh_host }} + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + alarms: + - { 'name': 'nova_api_local_status', 'criteria': ':set consecutiveCount={{ maas_alarm_local_consecutive_count }} if (metric["nova_api_local_status"] != 1) { return new AlarmStatus(CRITICAL, "API unavailable"); }' } + user: root + roles: + - maas_local + +- hosts: nova_spice_console + vars: + check_name: nova_spice_console_check + check_details: file=service_api_local_check.py,args=nova_spice,args={{ ansible_ssh_host }},args=6082 + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + alarms: + - { 'name': 'nova_spice_api_local_status', 'criteria': ':set consecutiveCount={{ maas_alarm_local_consecutive_count }} if (metric["nova_spice_api_local_status"] != 1) { return new AlarmStatus(CRITICAL, "API unavailable"); }' } + user: root + roles: + - maas_local + +- hosts: rabbit + vars: + check_name: rabbitmq_status + check_details: file={{ check_name }}.py,args=-H,args={{ ansible_ssh_host }},args=-n,args={{ ansible_hostname }} + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + alarms: + - { 'name': 'disk_free_alarm', 'criteria': ':set consecutiveCount={{ maas_alarm_local_consecutive_count }} if (metric["disk_free_alarm"] != 1) { return new AlarmStatus(CRITICAL, "disk_free_alarm triggered"); }' } + - { 'name': 'mem_alarm', 'criteria': ':set consecutiveCount={{ maas_alarm_local_consecutive_count }} if (metric["mem_alarm"] != 1) { return new AlarmStatus(CRITICAL, "mem_alarm triggered"); }' } + user: root + roles: + - maas_local + +- hosts: galera + vars: + check_name: galera_check + check_details: file={{ check_name }}.py,args=-H,args={{ ansible_ssh_host }} + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + user: root + roles: + - maas_local + +- hosts: memcached + vars: + check_name: memcached_status + check_details: file={{ check_name }}.py,args={{ ansible_ssh_host }} + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + alarms: + - { 'name': 'memcache_api_local_status', 'criteria': ':set consecutiveCount={{ maas_alarm_local_consecutive_count }} if (metric["memcache_api_local_status"] != 1) { return new AlarmStatus(CRITICAL, "memcached unavailable"); }' } + user: root + roles: + - maas_local diff --git a/rpc_deployment/playbooks/monitoring/maas_remote.yml b/rpc_deployment/playbooks/monitoring/maas_remote.yml new file mode 100644 index 0000000000..26e4547e60 --- /dev/null +++ b/rpc_deployment/playbooks/monitoring/maas_remote.yml @@ -0,0 +1,204 @@ +# Copyright 2014, Rackspace US, Inc. +# +# 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: cinder_api[0] + user: root + roles: + - maas_remote + vars: + entity_name: "{{ lb_name }}" + target_alias: "{{ maas_target_alias }}" + check_type: remote.http + check_name: lb_api_check_cinder + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + monitoring_zones: "{{ maas_monitoring_zones }}" + notification_plan: "{{ maas_notification_plan }}" + scheme: "{{ maas_cinder_scheme | default(maas_scheme)}}" + ip_address: "{{ external_vip_address }}" + port: "{{ cinder_service_port }}" + path: "" + url: "{{ scheme }}://{{ ip_address }}:{{ port }}{{ path }}" + alarm_name: lb_api_alarm_cinder + criteria: ":set consecutiveCount={{ maas_alarm_remote_consecutive_count }} if (metric['code'] != '200') { return new AlarmStatus(CRITICAL, 'API unavailable.'); }" + +- hosts: glance_api[0] + user: root + roles: + - maas_remote + vars: + entity_name: "{{ lb_name }}" + target_alias: "{{ maas_target_alias }}" + check_type: remote.http + check_name: lb_api_check_glance + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + monitoring_zones: "{{ maas_monitoring_zones }}" + notification_plan: "{{ maas_notification_plan }}" + scheme: "{{ maas_glance_scheme | default(maas_scheme)}}" + ip_address: "{{ external_vip_address }}" + port: 9292 + path: "" + url: "{{ scheme }}://{{ ip_address }}:{{ port }}{{ path }}" + alarm_name: lb_api_alarm_glance + criteria: ":set consecutiveCount={{ maas_alarm_remote_consecutive_count }} if (metric['code'] != '300') { return new AlarmStatus(CRITICAL, 'API unavailable.'); }" + +- hosts: keystone[0] + user: root + roles: + - maas_remote + vars: + entity_name: "{{ lb_name }}" + target_alias: "{{ maas_target_alias }}" + check_type: remote.http + check_name: lb_api_check_keystone + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + monitoring_zones: "{{ maas_monitoring_zones }}" + notification_plan: "{{ maas_notification_plan }}" + scheme: "{{ maas_keystone_scheme | default(maas_scheme)}}" + ip_address: "{{ external_vip_address }}" + port: "{{ auth_public_port }}" + path: "" + url: "{{ scheme }}://{{ ip_address }}:{{ port }}{{ path }}" + alarm_name: lb_api_alarm_keystone + criteria: ":set consecutiveCount={{ maas_alarm_remote_consecutive_count }} if (metric['code'] != '300') { return new AlarmStatus(CRITICAL, 'API unavailable.'); }" + +- hosts: neutron_server[0] + user: root + roles: + - maas_remote + vars: + entity_name: "{{ lb_name }}" + target_alias: "{{ maas_target_alias }}" + check_type: remote.http + check_name: lb_api_check_neutron + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + monitoring_zones: "{{ maas_monitoring_zones }}" + notification_plan: "{{ maas_notification_plan }}" + scheme: "{{ maas_neutron_scheme | default(maas_scheme)}}" + ip_address: "{{ external_vip_address }}" + port: 9696 + path: "/" + url: "{{ scheme }}://{{ ip_address }}:{{ port }}{{ path }}" + alarm_name: lb_api_alarm_neutron + criteria: ":set consecutiveCount={{ maas_alarm_remote_consecutive_count }} if (metric['code'] != '200') { return new AlarmStatus(CRITICAL, 'API unavailable.'); }" + +- hosts: nova_api_os_compute[0] + user: root + roles: + - maas_remote + vars: + entity_name: "{{ lb_name }}" + target_alias: "{{ maas_target_alias }}" + check_type: remote.http + check_name: lb_api_check_nova + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + monitoring_zones: "{{ maas_monitoring_zones }}" + notification_plan: "{{ maas_notification_plan }}" + scheme: "{{ maas_nova_scheme | default(maas_scheme)}}" + ip_address: "{{ external_vip_address }}" + port: 8774 + path: "" + url: "{{ scheme }}://{{ ip_address }}:{{ port }}{{ path }}" + alarm_name: lb_api_alarm_nova + criteria: ":set consecutiveCount={{ maas_alarm_remote_consecutive_count }} if (metric['code'] != '200') { return new AlarmStatus(CRITICAL, 'API unavailable.'); }" + +- hosts: horizon[0] + user: root + roles: + - maas_remote + vars: + entity_name: "{{ lb_name }}" + target_alias: "{{ maas_target_alias }}" + check_type: remote.http + check_name: lb_api_check_horizon + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + monitoring_zones: "{{ maas_monitoring_zones }}" + notification_plan: "{{ maas_notification_plan }}" + scheme: "{{ maas_scheme }}" + scheme: "{{ maas_horizon_scheme | default(maas_scheme)}}" + ip_address: "{{ external_vip_address }}" + port: 443 + path: "" + url: "{{ scheme }}://{{ ip_address }}:{{ port }}{{ path }}" + alarm_name: lb_api_alarm_horizon + criteria: ":set consecutiveCount={{ maas_alarm_remote_consecutive_count }} if (metric['code'] != '200') { return new AlarmStatus(CRITICAL, 'API unavailable.'); }" + +- hosts: heat_api[0] + user: root + roles: + - maas_remote + vars: + entity_name: "{{ lb_name }}" + target_alias: "{{ maas_target_alias }}" + check_type: remote.http + check_name: lb_api_check_heat_api + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + monitoring_zones: "{{ maas_monitoring_zones }}" + notification_plan: "{{ maas_notification_plan }}" + scheme: "{{ maas_heat_api_scheme | default(maas_scheme)}}" + ip_address: "{{ external_vip_address }}" + port: 8004 + path: "" + url: "{{ scheme }}://{{ ip_address }}:{{ port }}{{ path }}" + alarm_name: lb_api_alarm_heat_api + criteria: ":set consecutiveCount={{ maas_alarm_remote_consecutive_count }} if (metric['code'] != '300') { return new AlarmStatus(CRITICAL, 'API unavailable.'); }" + +- hosts: heat_api_cfn[0] + user: root + roles: + - maas_remote + vars: + entity_name: "{{ lb_name }}" + target_alias: "{{ maas_target_alias }}" + check_type: remote.http + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + check_name: lb_api_check_heat_cfn + monitoring_zones: "{{ maas_monitoring_zones }}" + notification_plan: "{{ maas_notification_plan }}" + scheme: "{{ maas_scheme }}" + scheme: "{{ maas_heat_cfn_scheme | default(maas_scheme)}}" + ip_address: "{{ external_vip_address }}" + port: 8000 + path: "" + url: "{{ scheme }}://{{ ip_address }}:{{ port }}{{ path }}" + alarm_name: lb_api_alarm_heat_cfn + criteria: ":set consecutiveCount={{ maas_alarm_remote_consecutive_count }} if (metric['code'] != '300') { return new AlarmStatus(CRITICAL, 'API unavailable.'); }" + +- hosts: heat_api_cloudwatch[0] + user: root + roles: + - maas_remote + vars: + entity_name: "{{ lb_name }}" + target_alias: "{{ maas_target_alias }}" + check_type: remote.http + check_name: lb_api_check_heat_cloudwatch + check_period: "{{ maas_check_period }}" + check_timeout: "{{ maas_check_timeout }}" + monitoring_zones: "{{ maas_monitoring_zones }}" + notification_plan: "{{ maas_notification_plan }}" + scheme: "{{ maas_heat_cloudwatch_scheme | default(maas_scheme)}}" + ip_address: "{{ external_vip_address }}" + port: 8003 + path: "" + url: "{{ scheme }}://{{ ip_address }}:{{ port }}{{ path }}" + alarm_name: lb_api_alarm_heat_cloudwatch + criteria: ":set consecutiveCount={{ maas_alarm_remote_consecutive_count }} if (metric['code'] != '300') { return new AlarmStatus(CRITICAL, 'API unavailable.'); }" diff --git a/rpc_deployment/playbooks/monitoring/raxmon-setup.yml b/rpc_deployment/playbooks/monitoring/raxmon-setup.yml new file mode 100644 index 0000000000..226bfa4e08 --- /dev/null +++ b/rpc_deployment/playbooks/monitoring/raxmon-setup.yml @@ -0,0 +1,47 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: hosts + user: root + roles: + - galera_client_cnf + - raxmon_cli + - raxmon_agent_install + vars: + entity_name: "{{ inventory_hostname }}" + +- hosts: keystone[0] + user: root + tasks: + # TODO (mattt): Modify openstack_openrc role to allow us to pass in arbitrary + # details. This is a refactor which will need to wait until a + # later date. + - name: Create keystone user for monitoring + keystone: > + command=ensure_user + token="{{ auth_admin_token }}" + endpoint="{{ auth_admin_uri }}" + user_name="{{ maas_keystone_user }}" + tenant_name="{{ auth_admin_tenant }}" + password="{{ maas_keystone_password }}" + + - name: Add monitoring keystone user to admin role + keystone: > + command=ensure_user_role + token="{{ auth_admin_token }}" + endpoint="{{ auth_admin_uri }}" + user_name="{{ maas_keystone_user }}" + tenant_name=admin + role_name=admin diff --git a/rpc_deployment/playbooks/monitoring/roles b/rpc_deployment/playbooks/monitoring/roles new file mode 120000 index 0000000000..b741aa3dbc --- /dev/null +++ b/rpc_deployment/playbooks/monitoring/roles @@ -0,0 +1 @@ +../../roles \ No newline at end of file diff --git a/rpc_deployment/playbooks/monitoring/vars b/rpc_deployment/playbooks/monitoring/vars new file mode 120000 index 0000000000..8559d2e08f --- /dev/null +++ b/rpc_deployment/playbooks/monitoring/vars @@ -0,0 +1 @@ +../../vars \ No newline at end of file diff --git a/rpc_deployment/playbooks/openstack/cinder-all.yml b/rpc_deployment/playbooks/openstack/cinder-all.yml new file mode 100644 index 0000000000..0e8ee4e28a --- /dev/null +++ b/rpc_deployment/playbooks/openstack/cinder-all.yml @@ -0,0 +1,18 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: cinder-api.yml +- include: cinder-scheduler.yml +- include: cinder-volume.yml diff --git a/rpc_deployment/playbooks/openstack/cinder-api.yml b/rpc_deployment/playbooks/openstack/cinder-api.yml new file mode 100644 index 0000000000..dd300fcd57 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/cinder-api.yml @@ -0,0 +1,62 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: cinder_all + user: root + roles: + - common + - common_sudoers + - container_common + - openstack_common + - openstack_openrc + - galera_client_cnf + vars_files: + - vars/openstack_service_vars/cinder_api.yml + +- hosts: cinder_api[0] + user: root + roles: + - keystone_add_service + vars_files: + - vars/openstack_service_vars/cinder_api_endpoint.yml + +- hosts: cinder_api[0] + user: root + roles: + - keystone_add_service + vars_files: + - vars/openstack_service_vars/cinder_apiv2_endpoint.yml + +- hosts: cinder_api[0] + user: root + roles: + - cinder_common + - galera_db_setup + - cinder_setup + - init_script + vars_files: + - vars/openstack_service_vars/cinder_api.yml + handlers: + - include: handlers/services.yml + +- hosts: cinder_api!:cinder_api[0] + user: root + roles: + - cinder_common + - init_script + vars_files: + - vars/openstack_service_vars/cinder_api.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/cinder-scheduler.yml b/rpc_deployment/playbooks/openstack/cinder-scheduler.yml new file mode 100644 index 0000000000..5d7df61760 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/cinder-scheduler.yml @@ -0,0 +1,30 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: cinder_scheduler + user: root + roles: + - common + - common_sudoers + - container_common + - openstack_common + - openstack_openrc + - cinder_common + - galera_client_cnf + - init_script + vars_files: + - vars/openstack_service_vars/cinder_scheduler.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/cinder-volume.yml b/rpc_deployment/playbooks/openstack/cinder-volume.yml new file mode 100644 index 0000000000..7307f2b71d --- /dev/null +++ b/rpc_deployment/playbooks/openstack/cinder-volume.yml @@ -0,0 +1,35 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: cinder_volume + user: root + roles: + - common + - common_sudoers + - container_extra_setup + - container_common + - openstack_common + - openstack_openrc + - cinder_common + - cinder_volume + - cinder_device_add + - cinder_backend_types + - galera_client_cnf + - init_script + vars_files: + - vars/config_vars/container_config_cinder_volume.yml + - vars/openstack_service_vars/cinder_volume.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/glance-all.yml b/rpc_deployment/playbooks/openstack/glance-all.yml new file mode 100644 index 0000000000..3527853ca8 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/glance-all.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: glance-api.yml +- include: glance-registry.yml diff --git a/rpc_deployment/playbooks/openstack/glance-api.yml b/rpc_deployment/playbooks/openstack/glance-api.yml new file mode 100644 index 0000000000..249656d4a3 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/glance-api.yml @@ -0,0 +1,61 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: glance_all + user: root + roles: + - common + - common_sudoers + - container_common + - openstack_common + - openstack_openrc + - galera_client_cnf + - glance_snet_override + vars_files: + - vars/openstack_service_vars/glance_api.yml + +- hosts: glance_api[0] + user: root + roles: + - keystone_add_service + vars_files: + - vars/openstack_service_vars/glance_api_endpoint.yml + +- hosts: glance_api[0] + user: root + roles: + - glance_common + - galera_db_setup + - glance_setup + - init_script + - glance_cache_crons + vars_files: + - vars/config_vars/glance_config.yml + - vars/openstack_service_vars/glance_api.yml + handlers: + - include: handlers/services.yml + + +- hosts: glance_api!:glance_api[0] + user: root + roles: + - glance_common + - init_script + - glance_cache_crons + vars_files: + - vars/config_vars/glance_config.yml + - vars/openstack_service_vars/glance_api.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/glance-registry.yml b/rpc_deployment/playbooks/openstack/glance-registry.yml new file mode 100644 index 0000000000..15896264b2 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/glance-registry.yml @@ -0,0 +1,33 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# This playbook deploys Glance-Registry. +- hosts: glance_registry + user: root + roles: + - common + - common_sudoers + - container_common + - glance_common + - openstack_common + - openstack_openrc + - galera_client_cnf + - init_script + - glance_snet_override + vars_files: + - vars/config_vars/glance_config.yml + - vars/openstack_service_vars/glance_registry.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/handlers b/rpc_deployment/playbooks/openstack/handlers new file mode 120000 index 0000000000..6bbd2ee9e8 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/handlers @@ -0,0 +1 @@ +../../handlers/ \ No newline at end of file diff --git a/rpc_deployment/playbooks/openstack/heat-all.yml b/rpc_deployment/playbooks/openstack/heat-all.yml new file mode 100644 index 0000000000..e7c49bceac --- /dev/null +++ b/rpc_deployment/playbooks/openstack/heat-all.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: heat-api.yml +- include: heat-api-cfn.yml +- include: heat-api-cloudwatch.yml +- include: heat-engine.yml diff --git a/rpc_deployment/playbooks/openstack/heat-api-cfn.yml b/rpc_deployment/playbooks/openstack/heat-api-cfn.yml new file mode 100644 index 0000000000..eaa982b174 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/heat-api-cfn.yml @@ -0,0 +1,37 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: heat_api_cfn + user: root + roles: + - common + - common_sudoers + - container_common + - heat_common + - openstack_common + - openstack_openrc + - galera_client_cnf + - init_script + vars_files: + - vars/openstack_service_vars/heat_api_cfn.yml + handlers: + - include: handlers/services.yml + +- hosts: heat_api_cfn[0] + user: root + roles: + - keystone_add_service + vars_files: + - vars/openstack_service_vars/heat_api_cfn_endpoint.yml diff --git a/rpc_deployment/playbooks/openstack/heat-api-cloudwatch.yml b/rpc_deployment/playbooks/openstack/heat-api-cloudwatch.yml new file mode 100644 index 0000000000..06bef6c3f7 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/heat-api-cloudwatch.yml @@ -0,0 +1,30 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: heat_api_cloudwatch + user: root + roles: + - common + - common_sudoers + - container_common + - heat_common + - openstack_common + - openstack_openrc + - galera_client_cnf + - init_script + vars_files: + - vars/openstack_service_vars/heat_api_cloudwatch.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/heat-api.yml b/rpc_deployment/playbooks/openstack/heat-api.yml new file mode 100644 index 0000000000..f6403ec42b --- /dev/null +++ b/rpc_deployment/playbooks/openstack/heat-api.yml @@ -0,0 +1,51 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: heat_all + user: root + roles: + - common + - common_sudoers + - container_common + - openstack_common + - openstack_openrc + - galera_client_cnf + vars_files: + - vars/openstack_service_vars/heat_api.yml + +- hosts: heat_api[0] + user: root + roles: + - keystone_add_service + - heat_domain_user + - heat_common + - galera_db_setup + - heat_setup + - init_script + vars_files: + - vars/openstack_service_vars/heat_api.yml + - vars/openstack_service_vars/heat_api_endpoint.yml + handlers: + - include: handlers/services.yml + +- hosts: heat_api!:heat_api[0] + user: root + roles: + - heat_common + - init_script + vars_files: + - vars/openstack_service_vars/heat_api.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/heat-engine.yml b/rpc_deployment/playbooks/openstack/heat-engine.yml new file mode 100644 index 0000000000..eb7f2b005f --- /dev/null +++ b/rpc_deployment/playbooks/openstack/heat-engine.yml @@ -0,0 +1,30 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: heat_engine + user: root + roles: + - common + - common_sudoers + - container_common + - heat_common + - openstack_common + - openstack_openrc + - galera_client_cnf + - init_script + vars_files: + - vars/openstack_service_vars/heat_engine.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/horizon.yml b/rpc_deployment/playbooks/openstack/horizon.yml new file mode 100644 index 0000000000..a33cea0dcf --- /dev/null +++ b/rpc_deployment/playbooks/openstack/horizon.yml @@ -0,0 +1,39 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: horizon_all + user: root + roles: + - common + - container_common + - galera_client_cnf + +- hosts: horizon_all + user: root + roles: + - openstack_common + - openstack_openrc + - horizon_common + +- hosts: horizon_all[0] + user: root + roles: + - galera_db_setup + - horizon_setup + +- hosts: horizon_all + user: root + roles: + - horizon_apache diff --git a/rpc_deployment/playbooks/openstack/inventory b/rpc_deployment/playbooks/openstack/inventory new file mode 120000 index 0000000000..f5a95b1299 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/inventory @@ -0,0 +1 @@ +../../inventory/ \ No newline at end of file diff --git a/rpc_deployment/playbooks/openstack/keystone-add-all-services.yml b/rpc_deployment/playbooks/openstack/keystone-add-all-services.yml new file mode 100644 index 0000000000..bb146ec33a --- /dev/null +++ b/rpc_deployment/playbooks/openstack/keystone-add-all-services.yml @@ -0,0 +1,113 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +## Keystone +- hosts: keystone[0] + user: root + roles: + - keystone_add_service + vars_files: + - inventory/group_vars/keystone_all.yml + - vars/openstack_service_vars/keystone_endpoint.yml + + +## Cinder +- hosts: keystone[0] + user: root + roles: + - keystone_add_service + vars_files: + - inventory/group_vars/cinder_all.yml + - vars/openstack_service_vars/cinder_api_endpoint.yml + +- hosts: keystone[0] + user: root + roles: + - keystone_add_service + vars_files: + - inventory/group_vars/cinder_all.yml + - vars/openstack_service_vars/cinder_apiv2_endpoint.yml + + +## Glance +- hosts: keystone[0] + user: root + roles: + - keystone_add_service + vars_files: + - inventory/group_vars/glance_all.yml + - vars/openstack_service_vars/glance_api_endpoint.yml + + +## Heat +- hosts: keystone[0] + user: root + roles: + - keystone_add_service + vars_files: + - inventory/group_vars/heat_all.yml + - vars/openstack_service_vars/heat_api_endpoint.yml + +- hosts: keystone[0] + user: root + roles: + - keystone_add_service + vars_files: + - inventory/group_vars/heat_all.yml + - vars/openstack_service_vars/heat_api_cfn_endpoint.yml + + +## Neutron +- hosts: keystone[0] + user: root + roles: + - keystone_add_service + vars_files: + - inventory/group_vars/neutron_all.yml + - vars/openstack_service_vars/neutron_server_endpoint.yml + + +## Nova +- hosts: keystone[0] + user: root + roles: + - keystone_add_service + vars_files: + - inventory/group_vars/nova_all.yml + - vars/openstack_service_vars/nova_api_os_compute_endpoint.yml + +- hosts: keystone[0] + user: root + roles: + - keystone_add_service + vars_files: + - inventory/group_vars/nova_all.yml + - vars/openstack_service_vars/nova_api_os_computev3_endpoint.yml + +- hosts: keystone[0] + user: root + roles: + - keystone_add_service + vars_files: + - inventory/group_vars/nova_all.yml + - vars/openstack_service_vars/nova_api_ec2_endpoint.yml + +- hosts: keystone[0] + user: root + roles: + - keystone_add_service + vars_files: + - inventory/group_vars/nova_all.yml + - vars/openstack_service_vars/nova_api_s3_endpoint.yml diff --git a/rpc_deployment/playbooks/openstack/keystone-add-users.yml b/rpc_deployment/playbooks/openstack/keystone-add-users.yml new file mode 100644 index 0000000000..e8598de40e --- /dev/null +++ b/rpc_deployment/playbooks/openstack/keystone-add-users.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Add additional users to keystone if needed. +- hosts: keystone[0] + user: root + roles: + - keystone_add_user diff --git a/rpc_deployment/playbooks/openstack/keystone-local-keys.yml b/rpc_deployment/playbooks/openstack/keystone-local-keys.yml new file mode 100644 index 0000000000..2e1138a509 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/keystone-local-keys.yml @@ -0,0 +1,53 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Setup Keystone +- hosts: keystone[0] + user: root + tasks: + - name: Perform a Keystone PKI Setup + command: > + keystone-manage pki_setup --keystone-user "{{ system_user }}" --keystone-group "{{ system_group }}" + creates=/etc/keystone/ssl/private/signing_key.pem + - name: Create Key directory + file: > + path=/tmp/keystone/ssl/ + state=directory + group="{{ ansible_ssh_user }}" + owner="{{ ansible_ssh_user }}" + recurse=true + delegate_to: localhost + - name: Sync keys from keystone + command: "rsync -az root@{{ ansible_ssh_host }}:/etc/keystone/ssl/ /tmp/keystone/ssl/" + delegate_to: localhost + +# Setup all keystone nodes +- hosts: keystone:!keystone[0] + user: root + tasks: + - name: Sync keys to keystone + command: "rsync -az /tmp/keystone/ssl/ root@{{ ansible_ssh_host }}:/etc/keystone/ssl/" + delegate_to: localhost + +# Remove temp Key Directory +- hosts: local + gather_facts: false + user: root + tasks: + - name: Remove Key directory + file: > + path=/tmp/keystone/ + state=absent + delegate_to: localhost diff --git a/rpc_deployment/playbooks/openstack/keystone.yml b/rpc_deployment/playbooks/openstack/keystone.yml new file mode 100644 index 0000000000..320200a840 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/keystone.yml @@ -0,0 +1,51 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# This playbook deploys Keystone-API. +- hosts: keystone + user: root + roles: + - common + - common_sudoers + - container_common + - keystone_common + - openstack_common + - openstack_openrc + - galera_client_cnf + vars_files: + - vars/config_vars/keystone_config.yml + - vars/openstack_service_vars/keystone.yml + +# Setup Keystone +- hosts: keystone[0] + user: root + roles: + - galera_db_setup + - keystone_apache + - keystone_setup + - keystone_add_service + vars: + auth_admin_uri: "{{ auth_protocol }}://{{ container_address }}:{{ auth_port }}/v2.0" + vars_files: + - vars/openstack_service_vars/keystone.yml + - vars/openstack_service_vars/keystone_endpoint.yml + +# Setup all keystone nodes +- hosts: keystone:!keystone[0] + user: root + roles: + - keystone_apache + vars_files: + - vars/openstack_service_vars/keystone.yml diff --git a/rpc_deployment/playbooks/openstack/library b/rpc_deployment/playbooks/openstack/library new file mode 120000 index 0000000000..63acaa1a76 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/library @@ -0,0 +1 @@ +../../library/ \ No newline at end of file diff --git a/rpc_deployment/playbooks/openstack/neutron-all.yml b/rpc_deployment/playbooks/openstack/neutron-all.yml new file mode 100644 index 0000000000..8085ea1771 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/neutron-all.yml @@ -0,0 +1,21 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: neutron-server.yml +- include: neutron-metadata-agent.yml +- include: neutron-dhcp-agent.yml +- include: neutron-linuxbridge-agent.yml +- include: neutron-l3-agent.yml +- include: neutron-metering-agent.yml diff --git a/rpc_deployment/playbooks/openstack/neutron-dhcp-agent.yml b/rpc_deployment/playbooks/openstack/neutron-dhcp-agent.yml new file mode 100644 index 0000000000..6b9607276c --- /dev/null +++ b/rpc_deployment/playbooks/openstack/neutron-dhcp-agent.yml @@ -0,0 +1,31 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: neutron_dhcp_agent + user: root + roles: + - common + - common_sudoers + - container_common + - neutron_common + - openstack_common + - openstack_openrc + - galera_client_cnf + - init_script + vars_files: + - inventory/group_vars/neutron_all.yml + - vars/openstack_service_vars/neutron_dhcp_agent.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/neutron-l3-agent.yml b/rpc_deployment/playbooks/openstack/neutron-l3-agent.yml new file mode 100644 index 0000000000..0393f1f890 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/neutron-l3-agent.yml @@ -0,0 +1,32 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: neutron_l3_agent + user: root + roles: + - common + - common_sudoers + - container_common + - neutron_common + - openstack_common + - openstack_openrc + - galera_client_cnf + - init_script + - neutron_l3_ha + vars_files: + - inventory/group_vars/neutron_all.yml + - vars/openstack_service_vars/neutron_l3_agent.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/neutron-linuxbridge-agent.yml b/rpc_deployment/playbooks/openstack/neutron-linuxbridge-agent.yml new file mode 100644 index 0000000000..a610dbf4e0 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/neutron-linuxbridge-agent.yml @@ -0,0 +1,33 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: neutron_linuxbridge_agent + user: root + roles: + - container_extra_setup + - common + - common_sudoers + - container_common + - neutron_common + - openstack_common + - openstack_openrc + - galera_client_cnf + - init_script + vars_files: + - inventory/group_vars/neutron_all.yml + - vars/config_vars/container_config_neutron.yml + - vars/openstack_service_vars/neutron_linuxbridge_agent.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/neutron-metadata-agent.yml b/rpc_deployment/playbooks/openstack/neutron-metadata-agent.yml new file mode 100644 index 0000000000..12b140ea40 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/neutron-metadata-agent.yml @@ -0,0 +1,31 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: neutron_metadata_agent + user: root + roles: + - common + - common_sudoers + - container_common + - neutron_common + - openstack_common + - openstack_openrc + - galera_client_cnf + - init_script + vars_files: + - inventory/group_vars/neutron_all.yml + - vars/openstack_service_vars/neutron_metadata_agent.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/neutron-metering-agent.yml b/rpc_deployment/playbooks/openstack/neutron-metering-agent.yml new file mode 100644 index 0000000000..092518f830 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/neutron-metering-agent.yml @@ -0,0 +1,31 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: neutron_metering_agent + user: root + roles: + - common + - common_sudoers + - container_common + - neutron_common + - openstack_common + - openstack_openrc + - galera_client_cnf + - init_script + vars_files: + - inventory/group_vars/neutron_all.yml + - vars/openstack_service_vars/neutron_metering_agent.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/neutron-server.yml b/rpc_deployment/playbooks/openstack/neutron-server.yml new file mode 100644 index 0000000000..9003d4de2b --- /dev/null +++ b/rpc_deployment/playbooks/openstack/neutron-server.yml @@ -0,0 +1,58 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: neutron_all + user: root + roles: + - common + - common_sudoers + - container_common + - openstack_common + - openstack_openrc + - galera_client_cnf + vars_files: + - inventory/group_vars/neutron_all.yml + +- hosts: neutron_server[0] + user: root + roles: + - keystone_add_service + vars_files: + - vars/openstack_service_vars/neutron_server_endpoint.yml + +- hosts: neutron_server[0] + user: root + roles: + - galera_db_setup + - neutron_common + - neutron_setup + - init_script + vars_files: + - inventory/group_vars/neutron_all.yml + - vars/openstack_service_vars/neutron_server.yml + handlers: + - include: handlers/services.yml + +- hosts: neutron_server:!neutron_server[0] + user: root + roles: + - neutron_common + - init_script + vars_files: + - inventory/group_vars/neutron_all.yml + - vars/openstack_service_vars/neutron_server.yml + handlers: + - include: handlers/services.yml + diff --git a/rpc_deployment/playbooks/openstack/nova-all.yml b/rpc_deployment/playbooks/openstack/nova-all.yml new file mode 100644 index 0000000000..ea7d9c51e0 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/nova-all.yml @@ -0,0 +1,22 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: nova-api-os-compute.yml +- include: nova-api-ec2.yml +- include: nova-api-metadata.yml +- include: nova-scheduler.yml +- include: nova-conductor.yml +- include: nova-compute.yml +- include: nova-spice-console.yml diff --git a/rpc_deployment/playbooks/openstack/nova-api-ec2.yml b/rpc_deployment/playbooks/openstack/nova-api-ec2.yml new file mode 100644 index 0000000000..564d380d4b --- /dev/null +++ b/rpc_deployment/playbooks/openstack/nova-api-ec2.yml @@ -0,0 +1,58 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: nova_api_ec2[0] + user: root + roles: + - keystone_add_service + vars_files: + - vars/openstack_service_vars/nova_api_ec2_endpoint.yml + +- hosts: nova_api_ec2[0] + user: root + roles: + - keystone_add_service + vars_files: + - vars/openstack_service_vars/nova_api_s3_endpoint.yml + +- hosts: nova_api_ec2 + user: root + roles: + - common + - common_sudoers + - container_common + - openstack_common + - openstack_openrc + - nova_common + - galera_client_cnf + - init_script + vars_files: + - inventory/group_vars/nova_all.yml + - vars/openstack_service_vars/nova_api_ec2.yml + - vars/openstack_service_vars/nova_spice_console_endpoint.yml + handlers: + - include: handlers/services.yml + +- hosts: nova_api_ec2:!nova_api_ec2[0] + user: root + roles: + - nova_common + - init_script + vars_files: + - inventory/group_vars/nova_all.yml + - vars/openstack_service_vars/nova_api_ec2.yml + - vars/openstack_service_vars/nova_spice_console_endpoint.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/nova-api-metadata.yml b/rpc_deployment/playbooks/openstack/nova-api-metadata.yml new file mode 100644 index 0000000000..2109ac3468 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/nova-api-metadata.yml @@ -0,0 +1,32 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: nova_api_metadata + user: root + roles: + - common + - common_sudoers + - container_common + - openstack_common + - openstack_openrc + - nova_common + - galera_client_cnf + - init_script + vars_files: + - inventory/group_vars/nova_all.yml + - vars/openstack_service_vars/nova_api_metadata.yml + - vars/openstack_service_vars/nova_spice_console_endpoint.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/nova-api-os-compute.yml b/rpc_deployment/playbooks/openstack/nova-api-os-compute.yml new file mode 100644 index 0000000000..8d8bd97280 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/nova-api-os-compute.yml @@ -0,0 +1,66 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: nova_all + user: root + roles: + - common + - common_sudoers + - container_common + - openstack_common + - openstack_openrc + - galera_client_cnf + vars_files: + - inventory/group_vars/nova_all.yml + +- hosts: nova_api_os_compute[0] + user: root + roles: + - keystone_add_service + vars_files: + - vars/openstack_service_vars/nova_api_os_compute_endpoint.yml + +- hosts: nova_api_os_compute[0] + user: root + roles: + - keystone_add_service + vars_files: + - vars/openstack_service_vars/nova_api_os_computev3_endpoint.yml + +- hosts: nova_api_os_compute[0] + user: root + roles: + - galera_db_setup + - nova_common + - nova_setup + - init_script + vars_files: + - inventory/group_vars/nova_all.yml + - vars/openstack_service_vars/nova_api_os_compute.yml + - vars/openstack_service_vars/nova_spice_console_endpoint.yml + handlers: + - include: handlers/services.yml + +- hosts: nova_api_os_compute:!nova_api_os_compute[0] + user: root + roles: + - nova_common + - init_script + vars_files: + - inventory/group_vars/nova_all.yml + - vars/openstack_service_vars/nova_api_os_compute.yml + - vars/openstack_service_vars/nova_spice_console_endpoint.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/nova-compute.yml b/rpc_deployment/playbooks/openstack/nova-compute.yml new file mode 100644 index 0000000000..50e5c13569 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/nova-compute.yml @@ -0,0 +1,37 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: nova_compute + user: root + roles: + - common + - common_sudoers + - container_extra_setup + - neutron_add_network_interfaces + - container_common + - openstack_common + - openstack_openrc + - nova_compute_devices + - nova_common + - nova_libvirt + - galera_client_cnf + - init_script + vars_files: + - inventory/group_vars/nova_all.yml + - vars/config_vars/container_config_nova_compute.yml + - vars/openstack_service_vars/nova_compute.yml + - vars/openstack_service_vars/nova_spice_console_endpoint.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/nova-conductor.yml b/rpc_deployment/playbooks/openstack/nova-conductor.yml new file mode 100644 index 0000000000..7bc3e6e08f --- /dev/null +++ b/rpc_deployment/playbooks/openstack/nova-conductor.yml @@ -0,0 +1,32 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: nova_conductor + user: root + roles: + - common + - common_sudoers + - container_common + - openstack_common + - openstack_openrc + - nova_common + - galera_client_cnf + - init_script + vars_files: + - inventory/group_vars/nova_all.yml + - vars/openstack_service_vars/nova_conductor.yml + - vars/openstack_service_vars/nova_spice_console_endpoint.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/nova-scheduler.yml b/rpc_deployment/playbooks/openstack/nova-scheduler.yml new file mode 100644 index 0000000000..32354091b1 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/nova-scheduler.yml @@ -0,0 +1,32 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: nova_scheduler + user: root + roles: + - common + - common_sudoers + - container_common + - openstack_common + - openstack_openrc + - nova_common + - galera_client_cnf + - init_script + vars_files: + - inventory/group_vars/nova_all.yml + - vars/openstack_service_vars/nova_scheduler.yml + - vars/openstack_service_vars/nova_spice_console_endpoint.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/nova-spice-console.yml b/rpc_deployment/playbooks/openstack/nova-spice-console.yml new file mode 100644 index 0000000000..14b28b07e1 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/nova-spice-console.yml @@ -0,0 +1,48 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: nova_spice_console + user: root + roles: + - common + - common_sudoers + - container_common + - openstack_common + - openstack_openrc + - nova_common + - galera_client_cnf + - init_script + vars_files: + - inventory/group_vars/nova_all.yml + - vars/openstack_service_vars/nova_spice_console.yml + - vars/openstack_service_vars/nova_spice_console_endpoint.yml + handlers: + - include: handlers/services.yml + +- hosts: nova_spice_console + user: root + roles: + - common + - common_sudoers + - container_common + - openstack_common + - openstack_openrc + - nova_common + - galera_client_cnf + - init_script + vars_files: + - vars/openstack_service_vars/nova_console_auth.yml + handlers: + - include: handlers/services.yml diff --git a/rpc_deployment/playbooks/openstack/openstack-common.yml b/rpc_deployment/playbooks/openstack/openstack-common.yml new file mode 100644 index 0000000000..6e97d5d65d --- /dev/null +++ b/rpc_deployment/playbooks/openstack/openstack-common.yml @@ -0,0 +1,22 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: keystone_all:glance_all:heat_all:neutron_all:nova_all:cinder_all:horizon + user: root + roles: + - common + - container_common + - openstack_common + - openstack_openrc diff --git a/rpc_deployment/playbooks/openstack/openstack-setup.yml b/rpc_deployment/playbooks/openstack/openstack-setup.yml new file mode 100644 index 0000000000..c2d8b53219 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/openstack-setup.yml @@ -0,0 +1,26 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: openstack-common.yml +- include: keystone.yml +- include: keystone-add-all-services.yml +- include: glance-all.yml +- include: heat-all.yml +- include: nova-all.yml +- include: neutron-all.yml +- include: cinder-all.yml +- include: horizon.yml +- include: utility.yml +- include: ../infrastructure/rsyslog-config.yml diff --git a/rpc_deployment/playbooks/openstack/roles b/rpc_deployment/playbooks/openstack/roles new file mode 120000 index 0000000000..148b132062 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/roles @@ -0,0 +1 @@ +../../roles/ \ No newline at end of file diff --git a/rpc_deployment/playbooks/openstack/utility.yml b/rpc_deployment/playbooks/openstack/utility.yml new file mode 100644 index 0000000000..5a4119ee87 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/utility.yml @@ -0,0 +1,81 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: utility_all + user: root + roles: + - common + - container_common + - utility_common + - openstack_openrc + - galera_client_cnf + vars_files: + - vars/config_vars/utility_config.yml + +- hosts: all_containers:!utility_all + user: root + roles: + - utility_create_configs + vars_files: + - vars/config_vars/utility_config.yml + +- hosts: glance_api[0] + user: root + roles: + - utility_keystone_checks + vars_files: + - vars/openstack_service_vars/glance_api_endpoint.yml + +- hosts: cinder_api[0] + user: root + roles: + - utility_keystone_checks + vars_files: + - vars/openstack_service_vars/cinder_api_endpoint.yml + +- hosts: nova_api_os_compute[0] + user: root + roles: + - utility_keystone_checks + vars_files: + - vars/openstack_service_vars/nova_api_os_compute_endpoint.yml + +- hosts: nova_api_ec2[0] + user: root + roles: + - utility_keystone_checks + vars_files: + - vars/openstack_service_vars/nova_api_ec2_endpoint.yml + +- hosts: neutron_server[0] + user: root + roles: + - utility_keystone_checks + vars_files: + - vars/openstack_service_vars/neutron_server_endpoint.yml + +- hosts: heat_api[0] + user: root + roles: + - utility_keystone_checks + vars_files: + - vars/openstack_service_vars/heat_api_endpoint.yml + +- hosts: heat_api_cfn[0] + user: root + roles: + - utility_keystone_checks + vars_files: + - vars/openstack_service_vars/heat_api_cfn_endpoint.yml diff --git a/rpc_deployment/playbooks/openstack/vars b/rpc_deployment/playbooks/openstack/vars new file mode 120000 index 0000000000..efa2775e20 --- /dev/null +++ b/rpc_deployment/playbooks/openstack/vars @@ -0,0 +1 @@ +../../vars/ \ No newline at end of file diff --git a/rpc_deployment/playbooks/os-service-config-update.yml b/rpc_deployment/playbooks/os-service-config-update.yml new file mode 100644 index 0000000000..b64ed8632c --- /dev/null +++ b/rpc_deployment/playbooks/os-service-config-update.yml @@ -0,0 +1,32 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# This is a common configuration update play. +# To use this play specify the required arguments on the command line +# Example: +# ansible-playbook -e @/etc/rpc_deploy/user_variables.yml \ +# -e "service_group=nova_api_os_compute service_name=nova" \ +# playbooks/openstack/service-config-update.yml + +- hosts: "{{ service_group }}" + user: root + roles: + - "{{ service_name }}_common" + vars_files: + - "inventory/group_vars/{{ service_name }}_all.yml" + - "vars/openstack_service_vars/{{ service_group }}.yml" + handlers: + - include: handlers/services.yml + diff --git a/rpc_deployment/playbooks/roles b/rpc_deployment/playbooks/roles new file mode 120000 index 0000000000..7b9ade87ed --- /dev/null +++ b/rpc_deployment/playbooks/roles @@ -0,0 +1 @@ +../roles/ \ No newline at end of file diff --git a/rpc_deployment/playbooks/rpc_support.yml b/rpc_deployment/playbooks/rpc_support.yml new file mode 100644 index 0000000000..2dc73aedb4 --- /dev/null +++ b/rpc_deployment/playbooks/rpc_support.yml @@ -0,0 +1,34 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Add all support options to all hosts +- hosts: hosts:all_containers + user: root + roles: + - rpc_support_common + +# Ensure security groups and keys are within the openstack api +- hosts: utility[0] + user: root + roles: + - rpc_support_api + +# Setup holland backup +- hosts: galera + user: root + roles: + - rpc_support_holland + vars: + holland_release: "{{ rpc_support_holland_branch|default('v1.0.10') }}" diff --git a/rpc_deployment/playbooks/setup-everything.yml b/rpc_deployment/playbooks/setup-everything.yml new file mode 100644 index 0000000000..6113f733ce --- /dev/null +++ b/rpc_deployment/playbooks/setup-everything.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: setup/host-setup.yml +- include: infrastructure/infrastructure-setup.yml +- include: openstack/openstack-setup.yml + diff --git a/rpc_deployment/playbooks/setup/archive-container.yml b/rpc_deployment/playbooks/setup/archive-container.yml new file mode 100644 index 0000000000..5ea9df58d7 --- /dev/null +++ b/rpc_deployment/playbooks/setup/archive-container.yml @@ -0,0 +1,39 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Example usage: +# ansible-playbook -i inventory/dynamic_inventory.py -e "host_name=infra1,container_name=horizon_container" setup/archive-container.yml + +# This will create a new archive of an existing container and then retreve +# the container storing the archive on the local system. Once the archive +# has been retrieved the archive is removed from the source system. +- hosts: "{{ host_group|default('hosts') }}" + user: root + tasks: + # Set facts on containers + - name: Get info on a given container + lxc: > + command=info + name={{ container_name }} + - name: Print information on all containers + debug: var=lxc_facts + +- hosts: "{{ host_name|default('hosts') }}" + user: root + roles: + - container_archive + vars: + local_store_path: /tmp + remote_store_path: /tmp diff --git a/rpc_deployment/playbooks/setup/build-containers.yml b/rpc_deployment/playbooks/setup/build-containers.yml new file mode 100644 index 0000000000..7a18a07cb1 --- /dev/null +++ b/rpc_deployment/playbooks/setup/build-containers.yml @@ -0,0 +1,23 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: "{{ host_group|default('hosts') }}" + user: root + roles: + - container_create + vars: + container_groups: "{{ groups[hostvars[inventory_hostname]['container_types']] }}" + +- include: containers-setup.yml diff --git a/rpc_deployment/playbooks/setup/clone-container.yml b/rpc_deployment/playbooks/setup/clone-container.yml new file mode 100644 index 0000000000..91aaece12d --- /dev/null +++ b/rpc_deployment/playbooks/setup/clone-container.yml @@ -0,0 +1,27 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Example usage: +# ansible-playbook -i inventory/hosts -M library/lxc -e "group=infra1-keystone name=keystone new_name=keystone2 address=192.168.18.149" clone-container.yml +- hosts: "{{ group }}" + user: root + roles: + - container_clone + vars: + fssize: "5G" + bdev: "lvm" + snapshot: "false" + state: "stopped" + lxcpath: /var/lib/lxc diff --git a/rpc_deployment/playbooks/setup/containers-setup.yml b/rpc_deployment/playbooks/setup/containers-setup.yml new file mode 100644 index 0000000000..c364fa038a --- /dev/null +++ b/rpc_deployment/playbooks/setup/containers-setup.yml @@ -0,0 +1,26 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: "{{ host_group|default('hosts') }}" + user: root + roles: + - container_setup + vars_files: + - vars/config_vars/container_interfaces.yml + vars: + container_groups: "{{ groups[hostvars[inventory_hostname]['container_types']] }}" + required_container_config_options: + - "lxc.mount.entry=/openstack/log/{{ hostvars[item]['container_name'] }} var/log/{{ hostvars[item]['service_name'] }} none defaults,bind,rw 0 0" + - "lxc.mount.entry=/openstack/monitoring monitoring none defaults,bind,rw 0 0" diff --git a/rpc_deployment/playbooks/setup/deploy-archived-container.yml b/rpc_deployment/playbooks/setup/deploy-archived-container.yml new file mode 100644 index 0000000000..8522814da4 --- /dev/null +++ b/rpc_deployment/playbooks/setup/deploy-archived-container.yml @@ -0,0 +1,163 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Example usage: +# ansible-playbook -i inventory/hosts -M library/lxc -e "group=infra1-keystone name=keystone address=192.168.18.120 archive_name=keystone.tar.bz2" deploy-archived-container.yml + +# This will create a new container from an archive of an existing container. +- hosts: "{{ host_group|default('hosts') }}" + user: root + tasks: + # Create container directory + - name: Create container directory + file: > + path="{{ lxcpath }}/{{ name }}" + state=directory + group="root" + owner="root" + recurse=true + # If check for the lxc VG + - name: Check for lxc volume group + shell: > + (which vgs > /dev/null && vgs | grep -o "{{ vg_name }}") || false + register: vg_result + ignore_errors: True + + # If lxc vg create new lv + - name: Create new LV + lvol: > + vg="{{ vg_name }}" + lv="{{ name }}" + size="{{ lv_size }}" + when: vg_result.rc == 0 + + # If lxc vg format new lv + - name: Format the new LV + filesystem: > + fstype="{{ fstype }}" + dev="/dev/{{ vg_name }}/{{ name }}" + when: vg_result.rc == 0 + + # If lxc vg mount new lv at $container/rootfs + - name: Mount Container LV + mount: > + name="{{ lxcpath }}/{{ name }}/rootfs" + src="/dev/{{ vg_name }}/{{ name }}" + fstype="{{ fstype }}" + state=mounted + when: vg_result.rc == 0 + + # upload new archive to host + - name: Upload Archive to host + synchronize: > + src="{{ local_store_path }}/{{ archive_name }}" + dest="{{ remote_store_path }}/{{ archive_name }}" + archive=yes + mode=push + + # Unarchive container + - name: Unarchive a container + unarchive: > + src="{{ remote_store_path }}/{{ archive_name }}" + dest="{{ lxcpath }}/{{ name }}" + register: result + + # If lxc vg unmount new lv + - name: Unmount Container LV + mount: > + name="{{ lxcpath }}/{{ name }}/rootfs" + src="/dev/{{ vg_name }}/{{ name }}" + fstype="{{ fstype }}" + state=unmounted + when: vg_result.rc == 0 + + # Delete archive directory + - name: Cleanup archive + file: > + path="{{ remote_store_path }}/{{ archive_name }}" + state=absent + when: result|changed + + # Ensure config is without old cruft + - name: Ensure clean config + lineinfile: > + dest="{{ lxcpath }}/{{ name }}/config" + regexp="{{ item.regexp }}" + state=absent + backup=yes + with_items: + - { regexp: "^lxc.network.hwaddr" } + - { regexp: "^lxc.mount.entry" } + + # If not lxc vg set the rootfs + - name: Set rootfs to localfs + lineinfile: > + dest="{{ lxcpath }}/{{ name }}/config" + regexp="^lxc.rootfs" + line="lxc.rootfs = {{ lxcpath }}/{{ name }}/rootfs" + state=present + when: vg_result.rc != 0 + + # If lxc vg set the rootfs + - name: Set rootfs to lvm + lineinfile: > + dest="{{ lxcpath }}/{{ name }}/config" + regexp="^lxc.rootfs" + line="lxc.rootfs = /dev/{{ vg_name }}/{{ name }}" + state=present + when: vg_result.rc == 0 + + # Ensure the configuration is complete + - name: Ensure config updated + lineinfile: > + dest="{{ lxcpath }}/{{ name }}/config" + regexp="^lxc.utsname" + line="lxc.utsname = {{ name }}" + state=present + + # Ensure the mount point is correct + - name: Ensure mount point updated updated + lineinfile: > + dest="{{ lxcpath }}/{{ name }}/config" + regexp="^lxc.mount" + line="lxc.mount = /var/lib/lxc/{{ name }}/fstab" + state=present + + # Start the new container + - name: Start new Container + lxc: > + command=start + name="{{ name }}" + + # If address is set update it in the network script + - name: Update networking + lxc: > + command=attach + name="{{ name }}" + container_command="sed -i 's/address.*/address\ {{ address }}/g' /etc/network/interfaces" + when: address is defined + + # Restart the new container + - name: Restart new container + lxc: > + command=restart + name="{{ name }}" + vars: + local_store_path: /tmp + remote_store_path: /tmp + lv_size: 5g + vg_name: lxc + fstype: ext4 + lxcpath: /var/lib/lxc diff --git a/rpc_deployment/playbooks/setup/destroy-containers.yml b/rpc_deployment/playbooks/setup/destroy-containers.yml new file mode 100644 index 0000000000..619b0455a8 --- /dev/null +++ b/rpc_deployment/playbooks/setup/destroy-containers.yml @@ -0,0 +1,22 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# This playbook destroys all known containers. +- hosts: "{{ host_group|default('hosts') }}" + user: root + roles: + - container_destroy + vars: + container_groups: "{{ groups[container_group|default(hostvars[inventory_hostname]['container_types'])] }}" diff --git a/rpc_deployment/playbooks/setup/host-common.yml b/rpc_deployment/playbooks/setup/host-common.yml new file mode 100644 index 0000000000..a613986d08 --- /dev/null +++ b/rpc_deployment/playbooks/setup/host-common.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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_containers + user: root + roles: + - common + - common_sudoers diff --git a/rpc_deployment/playbooks/setup/host-network-setup.yml b/rpc_deployment/playbooks/setup/host-network-setup.yml new file mode 100644 index 0000000000..2e495fb38e --- /dev/null +++ b/rpc_deployment/playbooks/setup/host-network-setup.yml @@ -0,0 +1,23 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# This playbook deploys All Containers. +- hosts: hosts + user: root + gather_facts: false + roles: + - host_interfaces + vars_prompt: + sanity_check: "This will setup networking devices on your hosts... is that ok? enter: [ 'yes' or 'no' ]" diff --git a/rpc_deployment/playbooks/setup/host-setup.yml b/rpc_deployment/playbooks/setup/host-setup.yml new file mode 100644 index 0000000000..054e3bfb25 --- /dev/null +++ b/rpc_deployment/playbooks/setup/host-setup.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: setup-common.yml +- include: build-containers.yml +- include: restart-containers.yml +- include: host-common.yml + diff --git a/rpc_deployment/playbooks/setup/inventory b/rpc_deployment/playbooks/setup/inventory new file mode 120000 index 0000000000..f5a95b1299 --- /dev/null +++ b/rpc_deployment/playbooks/setup/inventory @@ -0,0 +1 @@ +../../inventory/ \ No newline at end of file diff --git a/rpc_deployment/playbooks/setup/library b/rpc_deployment/playbooks/setup/library new file mode 120000 index 0000000000..63acaa1a76 --- /dev/null +++ b/rpc_deployment/playbooks/setup/library @@ -0,0 +1 @@ +../../library/ \ No newline at end of file diff --git a/rpc_deployment/playbooks/setup/restart-containers.yml b/rpc_deployment/playbooks/setup/restart-containers.yml new file mode 100644 index 0000000000..2a604cf270 --- /dev/null +++ b/rpc_deployment/playbooks/setup/restart-containers.yml @@ -0,0 +1,22 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: "{{ host_group|default('hosts') }}" + user: root + gather_facts: false + roles: + - container_restart + vars: + container_groups: "{{ groups[hostvars[inventory_hostname]['container_types']] }}" diff --git a/rpc_deployment/playbooks/setup/roles b/rpc_deployment/playbooks/setup/roles new file mode 120000 index 0000000000..148b132062 --- /dev/null +++ b/rpc_deployment/playbooks/setup/roles @@ -0,0 +1 @@ +../../roles/ \ No newline at end of file diff --git a/rpc_deployment/playbooks/setup/setup-common.yml b/rpc_deployment/playbooks/setup/setup-common.yml new file mode 100644 index 0000000000..e47360a353 --- /dev/null +++ b/rpc_deployment/playbooks/setup/setup-common.yml @@ -0,0 +1,23 @@ +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# This playbook deploys All Containers. +- hosts: hosts + user: root + roles: + - safe_upgrade + - common + - host_common + - lxc_common + diff --git a/rpc_deployment/playbooks/setup/upgrade-safe.yml b/rpc_deployment/playbooks/setup/upgrade-safe.yml new file mode 100644 index 0000000000..9d81012f7a --- /dev/null +++ b/rpc_deployment/playbooks/setup/upgrade-safe.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: "{{ host_group|default('hosts') }}" + user: root + roles: + - safe_upgrade diff --git a/rpc_deployment/playbooks/setup/vars b/rpc_deployment/playbooks/setup/vars new file mode 120000 index 0000000000..efa2775e20 --- /dev/null +++ b/rpc_deployment/playbooks/setup/vars @@ -0,0 +1 @@ +../../vars/ \ No newline at end of file diff --git a/rpc_deployment/playbooks/vars b/rpc_deployment/playbooks/vars new file mode 120000 index 0000000000..b11f011a5d --- /dev/null +++ b/rpc_deployment/playbooks/vars @@ -0,0 +1 @@ +../vars/ \ No newline at end of file diff --git a/rpc_deployment/roles/cinder_backend_types/tasks/main.yml b/rpc_deployment/roles/cinder_backend_types/tasks/main.yml new file mode 100644 index 0000000000..9adc08f8ca --- /dev/null +++ b/rpc_deployment/roles/cinder_backend_types/tasks/main.yml @@ -0,0 +1,29 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Ensure cinder is online + wait_for: > + port={{ cinder_service_port }} + delay=1 + host="{{ internal_vip_address }}" + + +- name: Add in cinder devices types + shell: | + . ~/openrc + cinder type-create "{{ item.0 }}" + cinder type-key "{{ item.0 }}" set volume_backend_name="{{ cinder_backends[item.0]['backend_name'] }}" + with_items: cinder_backends|dictsort + when: cinder_backends is defined diff --git a/rpc_deployment/roles/cinder_common/tasks/main.yml b/rpc_deployment/roles/cinder_common/tasks/main.yml new file mode 100644 index 0000000000..2e480d5651 --- /dev/null +++ b/rpc_deployment/roles/cinder_common/tasks/main.yml @@ -0,0 +1,28 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Setup Cinder Config + template: > + src="{{ item }}" + dest="/etc/cinder/{{ item }}" + owner="{{ system_group }}" + group="{{ system_user }}" + with_items: + - cinder.conf + - api-paste.ini + - policy.json + - rootwrap.conf + - rootwrap.d/volume.filters + notify: Restart os service diff --git a/rpc_deployment/roles/cinder_common/templates/api-paste.ini b/rpc_deployment/roles/cinder_common/templates/api-paste.ini new file mode 100644 index 0000000000..ff7f11975c --- /dev/null +++ b/rpc_deployment/roles/cinder_common/templates/api-paste.ini @@ -0,0 +1,55 @@ +############# +# OpenStack # +############# + +[composite:osapi_volume] +use = call:cinder.api:root_app_factory +/: apiversions +/v1: openstack_volume_api_v1 +/v2: openstack_volume_api_v2 + +[composite:openstack_volume_api_v1] +use = call:cinder.api.middleware.auth:pipeline_factory +noauth = request_id faultwrap sizelimit noauth apiv1 +keystone = request_id faultwrap sizelimit authtoken keystonecontext apiv1 +keystone_nolimit = request_id faultwrap sizelimit authtoken keystonecontext apiv1 + +[composite:openstack_volume_api_v2] +use = call:cinder.api.middleware.auth:pipeline_factory +noauth = request_id faultwrap sizelimit noauth apiv2 +keystone = request_id faultwrap sizelimit authtoken keystonecontext apiv2 +keystone_nolimit = request_id faultwrap sizelimit authtoken keystonecontext apiv2 + +[filter:request_id] +paste.filter_factory = cinder.openstack.common.middleware.request_id:RequestIdMiddleware.factory + +[filter:faultwrap] +paste.filter_factory = cinder.api.middleware.fault:FaultWrapper.factory + +[filter:noauth] +paste.filter_factory = cinder.api.middleware.auth:NoAuthMiddleware.factory + +[filter:sizelimit] +paste.filter_factory = cinder.api.middleware.sizelimit:RequestBodySizeLimiter.factory + +[app:apiv1] +paste.app_factory = cinder.api.v1.router:APIRouter.factory + +[app:apiv2] +paste.app_factory = cinder.api.v2.router:APIRouter.factory + +[pipeline:apiversions] +pipeline = faultwrap osvolumeversionapp + +[app:osvolumeversionapp] +paste.app_factory = cinder.api.versions:Versions.factory + +########## +# Shared # +########## + +[filter:keystonecontext] +paste.filter_factory = cinder.api.middleware.auth:CinderKeystoneContext.factory + +[filter:authtoken] +paste.filter_factory = keystonemiddleware.auth_token:filter_factory diff --git a/rpc_deployment/roles/cinder_common/templates/cinder.conf b/rpc_deployment/roles/cinder_common/templates/cinder.conf new file mode 100644 index 0000000000..144e8a5e55 --- /dev/null +++ b/rpc_deployment/roles/cinder_common/templates/cinder.conf @@ -0,0 +1,68 @@ +[DEFAULT] +verbose = {{ verbose }} +debug = {{ debug }} + +my_ip={{ container_address }} + +rpc_backend = {{ rpc_backend }} +rabbit_hosts = {{ rabbit_hosts }} +rabbit_userid = {{ rabbit_userid }} +rabbit_password = {{ rabbit_password }} + +lock_path = /var/lock/cinder +rootwrap_config = /etc/cinder/rootwrap.conf +api_paste_config = /etc/cinder/api-paste.ini +auth_strategy = keystone +volume_clear = none + +nova_catalog_info=compute:nova:internalURL +nova_catalog_admin_info=compute:nova:adminURL + +glance_host={{ internal_vip_address }} +glance_port={{ glance_port|default('9292') }} +glance_num_retries=0 +glance_api_servers={% for host in groups['glance_api'] %}{{ hostvars[host]['container_address'] }}:{{ glance_port|default('9292') }}{% if not loop.last %},{% endif %}{% endfor %} + +{% if cinder_default_volume_type is defined %} +default_volume_type = {{ cinder_default_volume_type }} +{% endif %} + +iscsi_helper=tgtadm +volume_name_template = volume-%s + +{% if cinder_backends is defined %} + +enabled_backends={% for backend in cinder_backends|dictsort %}{{ backend.0 }}{% if not loop.last %},{% endif %}{% endfor %} + +{% for backend_section in cinder_backends|dictsort %} +[{{ backend_section.0 }}] +{% for key, value in backend_section.1.items() %} +{{ key }}={{ value }} +{% endfor %} + +{% endfor %} +{% endif %} + +[database] +connection = mysql://{{ container_mysql_user }}:{{ container_mysql_password }}@{{ mysql_address }}/{{ container_database }}?charset=utf8 + + + +[keystone_authtoken] +identity_uri = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }} +auth_uri = {{ auth_identity_uri }} +signing_dir = /var/cache/cinder +admin_tenant_name = {{ service_admin_tenant_name }} +admin_user = {{ service_admin_username }} +admin_password = {{ service_admin_password }} + +memcached_servers = {{ internal_vip_address }}:{{ memcached_port }} +token_cache_time = 300 +revocation_cache_time = 60 + +# if your memcached server is shared, use these settings to avoid cache poisoning +memcache_security_strategy = ENCRYPT +memcache_secret_key = {{ memcached_secret_key }} + +# if your keystone deployment uses PKI, and you value security over performance: +check_revocations_for_cached = {{ hostvars[groups['keystone_all'][0]]['keystone_use_pki'] }} diff --git a/rpc_deployment/roles/cinder_common/templates/policy.json b/rpc_deployment/roles/cinder_common/templates/policy.json new file mode 100644 index 0000000000..202efe1d7c --- /dev/null +++ b/rpc_deployment/roles/cinder_common/templates/policy.json @@ -0,0 +1,59 @@ +{ + "context_is_admin": [["role:admin"]], + "admin_or_owner": [["is_admin:True"], ["project_id:%(project_id)s"]], + "default": [["rule:admin_or_owner"]], + + "admin_api": [["is_admin:True"]], + + "volume:create": [], + "volume:get_all": [], + "volume:get_volume_metadata": [], + "volume:get_volume_admin_metadata": [["rule:admin_api"]], + "volume:delete_volume_admin_metadata": [["rule:admin_api"]], + "volume:update_volume_admin_metadata": [["rule:admin_api"]], + "volume:get_snapshot": [], + "volume:get_all_snapshots": [], + "volume:extend": [], + "volume:update_readonly_flag": [], + "volume:retype": [], + + "volume_extension:types_manage": [["rule:admin_api"]], + "volume_extension:types_extra_specs": [["rule:admin_api"]], + "volume_extension:volume_type_encryption": [["rule:admin_api"]], + "volume_extension:volume_encryption_metadata": [["rule:admin_or_owner"]], + "volume_extension:extended_snapshot_attributes": [], + "volume_extension:volume_image_metadata": [], + + "volume_extension:quotas:show": [], + "volume_extension:quotas:update": [["rule:admin_api"]], + "volume_extension:quota_classes": [], + + "volume_extension:volume_admin_actions:reset_status": [["rule:admin_api"]], + "volume_extension:snapshot_admin_actions:reset_status": [["rule:admin_api"]], + "volume_extension:volume_admin_actions:force_delete": [["rule:admin_api"]], + "volume_extension:snapshot_admin_actions:force_delete": [["rule:admin_api"]], + "volume_extension:volume_admin_actions:migrate_volume": [["rule:admin_api"]], + "volume_extension:volume_admin_actions:migrate_volume_completion": [["rule:admin_api"]], + + "volume_extension:volume_host_attribute": [["rule:admin_api"]], + "volume_extension:volume_tenant_attribute": [["rule:admin_or_owner"]], + "volume_extension:volume_mig_status_attribute": [["rule:admin_api"]], + "volume_extension:hosts": [["rule:admin_api"]], + "volume_extension:services": [["rule:admin_api"]], + "volume:services": [["rule:admin_api"]], + + "volume:create_transfer": [], + "volume:accept_transfer": [], + "volume:delete_transfer": [], + "volume:get_all_transfers": [], + + "backup:create" : [], + "backup:delete": [], + "backup:get": [], + "backup:get_all": [], + "backup:restore": [], + "backup:backup-import": [["rule:admin_api"]], + "backup:backup-export": [["rule:admin_api"]], + + "snapshot_extension:snapshot_actions:update_snapshot_status": [] +} diff --git a/rpc_deployment/roles/cinder_common/templates/rootwrap.conf b/rpc_deployment/roles/cinder_common/templates/rootwrap.conf new file mode 100644 index 0000000000..001b90af5d --- /dev/null +++ b/rpc_deployment/roles/cinder_common/templates/rootwrap.conf @@ -0,0 +1,27 @@ +# Configuration for cinder-rootwrap +# This file should be owned by (and only-writeable by) the root user + +[DEFAULT] +# List of directories to load filter definitions from (separated by ','). +# These directories MUST all be only writeable by root ! +filters_path=/etc/cinder/rootwrap.d,/usr/share/cinder/rootwrap + +# List of directories to search executables in, in case filters do not +# explicitely specify a full path (separated by ',') +# If not specified, defaults to system PATH environment variable. +# These directories MUST all be only writeable by root ! +exec_dirs=/sbin,/usr/sbin,/bin,/usr/bin + +# Enable logging to syslog +# Default value is False +use_syslog=False + +# Which syslog facility to use. +# Valid values include auth, authpriv, syslog, local0, local1... +# Default value is 'syslog' +syslog_log_facility=syslog + +# Which messages to log. +# INFO means log all usage +# ERROR means only log unsuccessful attempts +syslog_log_level=ERROR diff --git a/rpc_deployment/roles/cinder_common/templates/rootwrap.d/volume.filters b/rpc_deployment/roles/cinder_common/templates/rootwrap.d/volume.filters new file mode 100644 index 0000000000..5b574040a7 --- /dev/null +++ b/rpc_deployment/roles/cinder_common/templates/rootwrap.d/volume.filters @@ -0,0 +1,115 @@ +# cinder-rootwrap command filters for volume nodes +# This file should be owned by (and only-writeable by) the root user + +[Filters] +# cinder/volume/iscsi.py: iscsi_helper '--op' ... +ietadm: CommandFilter, ietadm, root +tgtadm: CommandFilter, tgtadm, root +tgt-admin: CommandFilter, tgt-admin, root +cinder-rtstool: CommandFilter, cinder-rtstool, root + +# LVM related show commands +pvs: EnvFilter, env, root, LC_ALL=C, pvs +vgs: EnvFilter, env, root, LC_ALL=C, vgs +lvs: EnvFilter, env, root, LC_ALL=C, lvs +lvdisplay: EnvFilter, env, root, LC_ALL=C, lvdisplay + +# cinder/volume/driver.py: 'lvcreate', '-L', sizestr, '-n', volume_name,.. +# cinder/volume/driver.py: 'lvcreate', '-L', ... +lvcreate: CommandFilter, lvcreate, root + +# cinder/volume/driver.py: 'dd', 'if=%s' % srcstr, 'of=%s' % deststr,... +dd: CommandFilter, dd, root + +# cinder/volume/driver.py: 'lvremove', '-f', %s/%s % ... +lvremove: CommandFilter, lvremove, root + +# cinder/volume/driver.py: 'lvrename', '%(vg)s', '%(orig)s' '(new)s'... +lvrename: CommandFilter, lvrename, root + +# cinder/volume/driver.py: 'lvextend', '-L' '%(new_size)s', '%(lv_name)s' ... +lvextend: CommandFilter, lvextend, root + +# cinder/brick/local_dev/lvm.py: 'lvchange -a y -K ' +lvchange: CommandFilter, lvchange, root + +# cinder/volume/driver.py: 'iscsiadm', '-m', 'discovery', '-t',... +# cinder/volume/driver.py: 'iscsiadm', '-m', 'node', '-T', ... +iscsiadm: CommandFilter, iscsiadm, root + +# cinder/volume/drivers/lvm.py: 'shred', '-n3' +# cinder/volume/drivers/lvm.py: 'shred', '-n0', '-z', '-s%dMiB' +shred: CommandFilter, shred, root + +#cinder/volume/.py: utils.temporary_chown(path, 0), ... +chown: CommandFilter, chown, root +ionice_1: RegExpFilter, ionice, root, ionice, -c[0-3]( -n[0-7])?, dd, if=\S+, of=\S+, count=\d+, bs=\S+ +ionice_2: RegExpFilter, ionice, root, ionice, -c[0-3]( -n[0-7])?, dd, if=\S+, of=\S+, count=\d+, bs=\S+, iflag=direct, oflag=direct +ionice_3: RegExpFilter, ionice, root, ionice, -c[0-3]( -n[0-7])?, dd, if=\S+, of=\S+, count=\d+, bs=\S+, conv=fdatasync + +# cinder/volume/driver.py +dmsetup: CommandFilter, dmsetup, root +ln: CommandFilter, ln, root + +# cinder/image/image_utils.py +qemu-img: EnvFilter, env, root, LC_ALL=C, qemu-img +qemu-img_convert: CommandFilter, qemu-img, root + +udevadm: CommandFilter, udevadm, root + +# cinder/volume/driver.py: utils.read_file_as_root() +cat: CommandFilter, cat, root + +# cinder/volume/nfs.py +stat: CommandFilter, stat, root +mount: CommandFilter, mount, root +df: CommandFilter, df, root +du: CommandFilter, du, root +truncate: CommandFilter, truncate, root +chmod: CommandFilter, chmod, root +rm: CommandFilter, rm, root + +# cinder/volume/drivers/netapp/nfs.py: +netapp_nfs_find: RegExpFilter, find, root, find, ^[/]*([^/\0]+(/+)?)*$, -maxdepth, \d+, -name, img-cache.*, -amin, \+\d+ + +# cinder/volume/drivers/glusterfs.py +chgrp: CommandFilter, chgrp, root + +# cinder/volumes/drivers/hds/hds.py: +hus-cmd: CommandFilter, hus-cmd, root +hus-cmd_local: CommandFilter, /usr/local/bin/hus-cmd, root + +# cinder/brick/initiator/connector.py: +ls: CommandFilter, ls, root +tee: CommandFilter, tee, root +multipath: CommandFilter, multipath, root +systool: CommandFilter, systool, root + +# cinder/volume/drivers/block_device.py +blockdev: CommandFilter, blockdev, root + +# cinder/volume/drivers/ibm/gpfs.py +mv: CommandFilter, mv, root +mmgetstate: CommandFilter, /usr/lpp/mmfs/bin/mmgetstate, root +mmclone: CommandFilter, /usr/lpp/mmfs/bin/mmclone, root +mmlsattr: CommandFilter, /usr/lpp/mmfs/bin/mmlsattr, root +mmchattr: CommandFilter, /usr/lpp/mmfs/bin/mmchattr, root +mmlsconfig: CommandFilter, /usr/lpp/mmfs/bin/mmlsconfig, root +mmlsfs: CommandFilter, /usr/lpp/mmfs/bin/mmlsfs, root +mmlspool: CommandFilter, /usr/lpp/mmfs/bin/mmlspool, root +mkfs: CommandFilter, mkfs, root + +# cinder/volume/drivers/ibm/gpfs.py +# cinder/volume/drivers/ibm/ibmnas.py +find_maxdepth_inum: RegExpFilter, find, root, find, ^[/]*([^/\0]+(/+)?)*$, -maxdepth, \d+, -inum, \d+ + +# cinder/brick/initiator/connector.py: +aoe-revalidate: CommandFilter, aoe-revalidate, root +aoe-discover: CommandFilter, aoe-discover, root +aoe-flush: CommandFilter, aoe-flush, root + +# cinder/brick/initiator/linuxscsi.py: +sg_scan: CommandFilter, sg_scan, root + +#cinder/backup/services/tsm.py +dsmc:CommandFilter,/usr/bin/dsmc,root diff --git a/rpc_deployment/roles/cinder_device_add/tasks/device_add.yml b/rpc_deployment/roles/cinder_device_add/tasks/device_add.yml new file mode 100644 index 0000000000..ca919f64bd --- /dev/null +++ b/rpc_deployment/roles/cinder_device_add/tasks/device_add.yml @@ -0,0 +1,32 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Ensure container is running + lxc: > + name={{ container_name }} + command=start + when: cinder_backends is defined and is_metal != true + delegate_to: "{{ physical_host }}" + +- name: Add volume group block device to cinder + shell: | + if [ "$(pvdisplay | grep -B1 {{ cinder_backends[item.0]['volume_group'] }} | awk '/PV/ {print $3}')" ];then + for device in `pvdisplay | grep -B1 {{ cinder_backends[item.0]['volume_group'] }} | awk '/PV/ {print $3}'` + do lxc-device -n {{ container_name }} add $device + done + fi + with_items: cinder_backends|dictsort + when: cinder_backends is defined and is_metal != true + delegate_to: "{{ physical_host }}" diff --git a/rpc_deployment/roles/cinder_device_add/tasks/main.yml b/rpc_deployment/roles/cinder_device_add/tasks/main.yml new file mode 100644 index 0000000000..c54840248a --- /dev/null +++ b/rpc_deployment/roles/cinder_device_add/tasks/main.yml @@ -0,0 +1,16 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: device_add.yml diff --git a/rpc_deployment/roles/cinder_setup/tasks/main.yml b/rpc_deployment/roles/cinder_setup/tasks/main.yml new file mode 100644 index 0000000000..43a849dc22 --- /dev/null +++ b/rpc_deployment/roles/cinder_setup/tasks/main.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Perform a Cinder DB sync + command: cinder-manage db sync diff --git a/rpc_deployment/roles/cinder_volume/handlers/main.yml b/rpc_deployment/roles/cinder_volume/handlers/main.yml new file mode 100644 index 0000000000..73ff6a3ad0 --- /dev/null +++ b/rpc_deployment/roles/cinder_volume/handlers/main.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Ensure tgt service restarted + service: name=tgt state=restarted pattern=tgtd diff --git a/rpc_deployment/roles/cinder_volume/tasks/main.yml b/rpc_deployment/roles/cinder_volume/tasks/main.yml new file mode 100644 index 0000000000..5ea5ce80e6 --- /dev/null +++ b/rpc_deployment/roles/cinder_volume/tasks/main.yml @@ -0,0 +1,21 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Ensure cinder tgt include + lineinfile: + dest: /etc/tgt/targets.conf + line: "include /var/lib/cinder/volumes/*" + state: present + notify: Ensure tgt service restarted diff --git a/rpc_deployment/roles/common/tasks/get_pip.yml b/rpc_deployment/roles/common/tasks/get_pip.yml new file mode 100644 index 0000000000..057dbd493d --- /dev/null +++ b/rpc_deployment/roles/common/tasks/get_pip.yml @@ -0,0 +1,34 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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 /opt + file: > + state=directory + path=/opt + +- name: Get Modern PIP + get_url: > + url="{{ get_pip_url }}" + dest="/opt/get-pip.py" + validate_certs=no + register: get_pip + until: get_pip|success + retries: 3 + +- name: Install PIP + shell: "python /opt/get-pip.py" + register: pip_install + until: pip_install|success + retries: 3 diff --git a/rpc_deployment/roles/common/tasks/install_pip_deps.yml b/rpc_deployment/roles/common/tasks/install_pip_deps.yml new file mode 100644 index 0000000000..b597f5ce12 --- /dev/null +++ b/rpc_deployment/roles/common/tasks/install_pip_deps.yml @@ -0,0 +1,24 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Install pip dependencies + pip: > + name={{ item }} + extra_args="--allow-all-external" + with_items: service_pip_dependencies + when: service_pip_dependencies is defined + register: pip_install + until: pip_install|success + retries: 3 diff --git a/rpc_deployment/roles/common/tasks/kernel_check.yml b/rpc_deployment/roles/common/tasks/kernel_check.yml new file mode 100644 index 0000000000..df426f9ce7 --- /dev/null +++ b/rpc_deployment/roles/common/tasks/kernel_check.yml @@ -0,0 +1,27 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# This will check for kernel as defined in the required kernel hash +- name: Get kernel release + command: uname -r + register: kernel_release + +- name: Check kernel version + fail: + msg: > + Wrong kernel Version found + [ {{ kernel_release.stdout }} != {{ required_kernel }} ] + Resolve this issue before continuing. + when: kernel_release.stdout != required_kernel diff --git a/rpc_deployment/roles/common/tasks/lvm_conf.yml b/rpc_deployment/roles/common/tasks/lvm_conf.yml new file mode 100644 index 0000000000..fbbbd3e8ad --- /dev/null +++ b/rpc_deployment/roles/common/tasks/lvm_conf.yml @@ -0,0 +1,34 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Discover lvm devices + shell: > + /sbin/pvdisplay | awk '/PV\ Name/ {print $3}' | sed 's/\/dev\///g' + register: lvm_devices + failed_when: false + +- name: Ensure "/etc/lvm" directory + file: + state: directory + path: "/etc/lvm" + when: lvm_devices.rc == 0 + +- name: Drop lvm Config + template: + src: "lvm.conf" + dest: "/etc/lvm/lvm.conf" + owner: "root" + group: "root" + when: lvm_devices.rc == 0 diff --git a/rpc_deployment/roles/common/tasks/main.yml b/rpc_deployment/roles/common/tasks/main.yml new file mode 100644 index 0000000000..13b422ed95 --- /dev/null +++ b/rpc_deployment/roles/common/tasks/main.yml @@ -0,0 +1,22 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: kernel_check.yml +- include: repos.yml +- include: utils.yml +- include: get_pip.yml +- include: install_pip_deps.yml +- include: rpc_release.yml +- include: lvm_conf.yml diff --git a/rpc_deployment/roles/common/tasks/repos.yml b/rpc_deployment/roles/common/tasks/repos.yml new file mode 100644 index 0000000000..0a93ad6253 --- /dev/null +++ b/rpc_deployment/roles/common/tasks/repos.yml @@ -0,0 +1,52 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: add apt-keys + apt_key: > + id="{{ item.hash_id }}" + keyserver="{{ item.keyserver }}" + state=present + with_items: gpg_keys + when: "ansible_distribution_version in ['12.04', '13.04', '13.10', '14.04']" + +- name: Add Common repos + apt_repository: > + repo="{{ item.repo }}" + state="{{ item.state }}" + with_items: apt_common_repos + when: "ansible_distribution_version in ['12.04', '13.04', '13.10', '14.04']" + register: add_repos + until: add_repos|success + retries: 3 + +- name: Add mariadb priority file + template: > + src=mariadb-priority + dest=/etc/apt/preferences.d/mariadb.pref + owner=root + group=root + mode=0644 + +- name: Ensure common Packages are Installed + apt: + pkg: "{{ item }}" + state: present + update_cache: yes + cache_valid_time: 600 + with_items: apt_common_packages + when: "ansible_distribution_version in ['12.04', '13.04', '13.10', '14.04']" + register: common_packages + until: common_packages|success + retries: 3 diff --git a/rpc_deployment/roles/common/tasks/rpc_release.yml b/rpc_deployment/roles/common/tasks/rpc_release.yml new file mode 100644 index 0000000000..b5f8e2eebc --- /dev/null +++ b/rpc_deployment/roles/common/tasks/rpc_release.yml @@ -0,0 +1,21 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Drop rpc version file + template: > + src=rpc-release + dest=/etc/rpc-release + owner="root" + group="root" diff --git a/rpc_deployment/roles/common/tasks/utils.yml b/rpc_deployment/roles/common/tasks/utils.yml new file mode 100644 index 0000000000..21bf98b0dc --- /dev/null +++ b/rpc_deployment/roles/common/tasks/utils.yml @@ -0,0 +1,22 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Ensure common utils + apt: + pkg: "{{ item }}" + state: present + update_cache: yes + cache_valid_time: 600 + with_items: common_util_packages diff --git a/rpc_deployment/roles/common/templates/lvm.conf b/rpc_deployment/roles/common/templates/lvm.conf new file mode 100644 index 0000000000..ce81ba368d --- /dev/null +++ b/rpc_deployment/roles/common/templates/lvm.conf @@ -0,0 +1,121 @@ +{% set used_lvm_devices = [] %} +{% set lv_devices = lvm_devices.stdout.split('\n') %} +{% if lv_devices|length > 0 %} + {% for net in lv_devices %} + {% if net != '' %} + {% set lv_device = '"a/' + net + '/"' %} + {% if used_lvm_devices.append(lv_device) %}{% endif %} + {% endif %} + {% endfor %} +{% endif %} + +# Ansible Discovered LVM Devices {{ lv_devices }} +{% if used_lvm_devices|length <= 0 %} + {% if used_lvm_devices.append('"a/.*/"') %}{% endif %} +{% else %} + {% if used_lvm_devices.append('"r/.*/"') %}{% endif %} +{% endif %} +{% if is_metal != true %} + {% set use_udev = 0 %} +{% else %} + {% set use_udev = 1 %} +{% endif %} + +devices { + dir = "/dev" + scan = [ "/dev" ] + obtain_device_list_from_udev = {{ use_udev }} + preferred_names = [ ] + filter = [ {{ used_lvm_devices|join(', ') }} ] + cache_dir = "/run/lvm" + cache_file_prefix = "" + write_cache_state = 1 + sysfs_scan = 1 + multipath_component_detection = 1 + md_component_detection = 1 + md_chunk_alignment = 1 + data_alignment_detection = 1 + data_alignment = 0 + data_alignment_offset_detection = 1 + ignore_suspended_devices = 0 + disable_after_error_count = 0 + require_restorefile_with_uuid = 1 + pv_min_size = 2048 + issue_discards = 1 +} +allocation { + maximise_cling = 1 + mirror_logs_require_separate_pvs = 0 + thin_pool_metadata_require_separate_pvs = 0 +} +log { + verbose = 0 + silent = 0 + syslog = 1 + overwrite = 0 + level = 0 + indent = 1 + command_names = 0 + prefix = " " +} +backup { + backup = 1 + backup_dir = "/etc/lvm/backup" + archive = 1 + archive_dir = "/etc/lvm/archive" + retain_min = 10 + retain_days = 30 +} +shell { + history_size = 100 +} +global { + umask = 077 + test = 0 + units = "h" + si_unit_consistency = 1 + activation = 1 + proc = "/proc" + locking_type = 1 + wait_for_locks = 1 + fallback_to_clustered_locking = 1 + fallback_to_local_locking = 1 + locking_dir = "/run/lock/lvm" + prioritise_write_locks = 1 + abort_on_internal_errors = 0 + detect_internal_vg_cache_corruption = 0 + metadata_read_only = 0 + mirror_segtype_default = "mirror" + use_lvmetad = 0 + thin_check_executable = "/usr/sbin/thin_check" + thin_check_options = [ "-q" ] +} +activation { + checks = 0 + udev_sync = {{ use_udev }} + udev_rules = {{ use_udev }} + verify_udev_operations = 0 + retry_deactivation = 1 + missing_stripe_filler = "error" + use_linear_target = 1 + reserved_stack = 64 + reserved_memory = 8192 + process_priority = -18 + mirror_region_size = 512 + readahead = "auto" + raid_fault_policy = "warn" + mirror_log_fault_policy = "allocate" + mirror_image_fault_policy = "remove" + snapshot_autoextend_threshold = 100 + snapshot_autoextend_percent = 20 + thin_pool_autoextend_threshold = 100 + thin_pool_autoextend_percent = 20 + use_mlockall = 0 + monitoring = 0 + polling_interval = 15 +} +dmeventd { + mirror_library = "libdevmapper-event-lvm2mirror.so" + snapshot_library = "libdevmapper-event-lvm2snapshot.so" + thin_library = "libdevmapper-event-lvm2thin.so" +} diff --git a/rpc_deployment/roles/common/templates/mariadb-priority b/rpc_deployment/roles/common/templates/mariadb-priority new file mode 100644 index 0000000000..a09d0874d7 --- /dev/null +++ b/rpc_deployment/roles/common/templates/mariadb-priority @@ -0,0 +1,3 @@ +Package: * +Pin: release o=MariaDB +Pin-Priority: 1000 diff --git a/rpc_deployment/roles/common/templates/rpc-release b/rpc_deployment/roles/common/templates/rpc-release new file mode 100644 index 0000000000..1966acf2da --- /dev/null +++ b/rpc_deployment/roles/common/templates/rpc-release @@ -0,0 +1,4 @@ +DISTRIB_ID="RPC" +DISTRIB_RELEASE="9.0.0" +DISTRIB_CODENAME="wee-5ive" +DISTRIB_DESCRIPTION="Rackspace Private Cloud" diff --git a/rpc_deployment/roles/common_sudoers/tasks/main.yml b/rpc_deployment/roles/common_sudoers/tasks/main.yml new file mode 100644 index 0000000000..a9654f01bc --- /dev/null +++ b/rpc_deployment/roles/common_sudoers/tasks/main.yml @@ -0,0 +1,23 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Place the sudoers file + template: > + src=sudoers + dest=/etc/sudoers.d/{{ service_name }}_sudoers + mode=0440 + owner=0 + group=0 + when: service_name is defined and system_user is defined diff --git a/rpc_deployment/roles/common_sudoers/templates/sudoers b/rpc_deployment/roles/common_sudoers/templates/sudoers new file mode 100644 index 0000000000..b9b9a41335 --- /dev/null +++ b/rpc_deployment/roles/common_sudoers/templates/sudoers @@ -0,0 +1,2 @@ +# Defaults:{{ system_user }}!requiretty +{{ system_user }} ALL = (root) NOPASSWD: /usr/local/bin/{{ service_name }}-rootwrap diff --git a/rpc_deployment/roles/container_archive/tasks/main.yml b/rpc_deployment/roles/container_archive/tasks/main.yml new file mode 100644 index 0000000000..ab760b6bd9 --- /dev/null +++ b/rpc_deployment/roles/container_archive/tasks/main.yml @@ -0,0 +1,48 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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 tar archive from Container + lxc: > + name={{ container_name }} + command=createtar + tarpath={{ remote_store_path }}/{{ container_name }} + +- name: set lxc archive + set_fact: + archive: + name: "{{ lxc_facts[container_name]['archive'] | basename }}" + path: "{{ lxc_facts[container_name]['archive'] }}" + +- name: Upload archive to swift + include: swift_upload.yml + when: swift_archive_store is defined + vars: + src: "{{ archive.path }}" + swift_container: "{{ swift_archive_store.container }}" + swift_object: "{{ archive.name }}" + creds_file: "{{ swift_archive_store.creds_file }}" + section: "{{ swift_archive_store.section }}" + +- name: Retrieve container archive locally + fetch: > + dest={{ local_store_path }}/{{ archive.name }} + src={{ archive.path }} + flat=true + when: swift_archive_store is not defined + +- name: Remove container archive from the host + file: > + path={{ archive.path }} + state=absent diff --git a/rpc_deployment/roles/container_archive/tasks/swift_upload.yml b/rpc_deployment/roles/container_archive/tasks/swift_upload.yml new file mode 100644 index 0000000000..70125e4993 --- /dev/null +++ b/rpc_deployment/roles/container_archive/tasks/swift_upload.yml @@ -0,0 +1,51 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Check for local swift creds file + shell: > + [ -f "{{ creds_file }}" ] + register: swift_creds + delegate_to: localhost + ignore_errors: True + +- name: Copy swift credentials to host + copy: > + src="{{ creds_file }}" + dest="{{ creds_file }}" + owner=root + group=root + mode=0600 + register: copy_swift + when: swift_creds|success + +- name: Create container + swift: > + command=create + container="{{ swift_container }}" + config_file="{{ creds_file }}" + section="{{ section }}" + register: container_create + when: copy_swift|success + ignore_errors: True + +- name: Upload object + swift: > + command=upload + src="{{ src }}" + container="{{ swift_container }}" + object="{{ swift_object }}" + config_file="{{ creds_file }}" + section="{{ section }}" + when: container_create|success diff --git a/rpc_deployment/roles/container_clone/tasks/main.yml b/rpc_deployment/roles/container_clone/tasks/main.yml new file mode 100644 index 0000000000..6c00789b1b --- /dev/null +++ b/rpc_deployment/roles/container_clone/tasks/main.yml @@ -0,0 +1,62 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: get container info + lxc: > + command=info + name="{{ container_name }}" + +- name: store_original_ip + set_fact: + orig_ip: "{{ lxc_facts[container_name]['ip_1'] }}" + when: "lxc_facts[container_name]['state'] == 'running'" + +- name: Clone Container + lxc: > + command=clone + orig="{{ container_name }}" + new="{{ new_name }}" + backingstore="{{ bdev }}" + fssize="{{ fssize }}" + snapshot="{{ snapshot }}" + state="{{ state }}" + +- name: Ensure clean config + lineinfile: > + dest="{{ lxcpath }}/{{ new_name }}/config" + regexp="{{ item }}" + state=absent + backup=yes + with_items: + - "^lxc.network.hwaddr" + - "^lxc.mount.entry" + +- name: restart new container + lxc: > + command=start + name="{{ new_name }}" + +- name: Update networking + lxc: > + command=attach + name="{{ new_name }}" + container_command="sed -i 's/{{ orig_ip }}/{{ address }}/g' /etc/network/interfaces" + when: orig_ip is defined + register: result + +- name: restart new container + lxc: > + command=restart + name="{{ new_name }}" diff --git a/rpc_deployment/roles/container_common/tasks/add_interfaces.yml b/rpc_deployment/roles/container_common/tasks/add_interfaces.yml new file mode 100644 index 0000000000..da902af7ae --- /dev/null +++ b/rpc_deployment/roles/container_common/tasks/add_interfaces.yml @@ -0,0 +1,41 @@ +--- +- name: Drop additional lxc network interfaces + template: + src: "host_container_interface.j2" + dest: "/var/lib/lxc/{{ container_name }}/add_network_interface.conf" + register: host_container_interface + when: provider_networks is defined and is_metal != true + delegate_to: "{{ physical_host }}" + +- name: Update container config + lineinfile: + dest: /var/lib/lxc/{{ container_name }}/config + line: "lxc.include = /var/lib/lxc/{{ container_name }}/add_network_interface.conf" + state: present + register: container_net_include + when: host_container_interface|changed and is_metal != true + delegate_to: "{{ physical_host }}" + +- name: Drop additional container network interfaces file(s) + template: + src: "container_interface_file.j2" + dest: "/etc/network/interfaces.d/provider_networks.cfg" + register: container_interface + when: provider_networks is defined and is_metal != true + +- name: Restart container + lxc: > + command=restart + name="{{ container_name }}" + register: restarted_container + when: container_net_include|changed or host_container_interface|changed or container_interface|changed and is_metal != true + delegate_to: "{{ physical_host }}" + +- name: Wait for container networking + wait_for: > + port=22 + timeout=60 + search_regex=OpenSSH + host={{ container_address }} + when: restarted_container|changed and is_metal != true + delegate_to: "{{ physical_host }}" diff --git a/rpc_deployment/roles/container_common/tasks/container_os_setup.yml b/rpc_deployment/roles/container_common/tasks/container_os_setup.yml new file mode 100644 index 0000000000..6ebd0357c6 --- /dev/null +++ b/rpc_deployment/roles/container_common/tasks/container_os_setup.yml @@ -0,0 +1,24 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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 the local directories + file: > + path={{ item }} + state=directory + group={{ system_group|default('root') }} + owner={{ system_user|default('root') }} + recurse=true + when: container_directories is defined + with_items: container_directories diff --git a/rpc_deployment/roles/container_common/tasks/container_packages.yml b/rpc_deployment/roles/container_common/tasks/container_packages.yml new file mode 100644 index 0000000000..9c244461bc --- /dev/null +++ b/rpc_deployment/roles/container_common/tasks/container_packages.yml @@ -0,0 +1,32 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Ensure container packages are installed + apt: + pkg: "{{ item }}" + state: present + update_cache: yes + cache_valid_time: 600 + with_items: container_packages + when: container_packages is defined + +- name: Ensure apt common Packages are installed + apt: + pkg: "{{ item }}" + state: present + update_cache: yes + cache_valid_time: 600 + with_items: apt_common_packages + when: apt_common_packages is defined diff --git a/rpc_deployment/roles/container_common/tasks/container_repos.yml b/rpc_deployment/roles/container_common/tasks/container_repos.yml new file mode 100644 index 0000000000..6863255b82 --- /dev/null +++ b/rpc_deployment/roles/container_common/tasks/container_repos.yml @@ -0,0 +1,36 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Add Container apt keys + apt_key: > + url="{{ item.url }}" + state="{{ item.state }}" + with_items: apt_container_keys + when: "ansible_distribution_version in ['12.04', '13.04', '13.10', '14.04'] and apt_container_keys is defined" + +- name: Add Container GPG Keys + apt_key: > + id="{{ item.hash_id }}" + keyserver="{{ item.keyserver }}" + state=present + with_items: container_gpg_keys + when: "ansible_distribution_version in ['12.04', '13.04', '13.10', '14.04'] and container_gpg_keys is defined" + +- name: Add Container repos + apt_repository: > + repo="{{ item.repo }}" + state="{{ item.state }}" + with_items: apt_container_repos + when: "ansible_distribution_version in ['12.04', '13.04', '13.10', '14.04'] and apt_container_repos is defined" diff --git a/rpc_deployment/roles/container_common/tasks/container_user_create.yml b/rpc_deployment/roles/container_common/tasks/container_user_create.yml new file mode 100644 index 0000000000..2ef40ff4f6 --- /dev/null +++ b/rpc_deployment/roles/container_common/tasks/container_user_create.yml @@ -0,0 +1,31 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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 the system group + group: > + name={{ system_group }} + state=present + system=yes + when: system_group is defined + +- name: create system user + user: > + name={{ system_user }} + shell=/bin/false + group={{ system_group }} + home=/var/lib/{{ system_user }} + system=yes + createhome=yes + when: system_group is defined and system_user is defined diff --git a/rpc_deployment/roles/container_common/tasks/main.yml b/rpc_deployment/roles/container_common/tasks/main.yml new file mode 100644 index 0000000000..7e8b0f3d21 --- /dev/null +++ b/rpc_deployment/roles/container_common/tasks/main.yml @@ -0,0 +1,21 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: container_user_create.yml + when: system_user is defined and system_user not in excluded_user_create +- include: container_os_setup.yml +- include: container_repos.yml +- include: container_packages.yml +- include: add_interfaces.yml diff --git a/rpc_deployment/roles/container_common/templates/container_interface_file.j2 b/rpc_deployment/roles/container_common/templates/container_interface_file.j2 new file mode 100644 index 0000000000..66eaaeaa4f --- /dev/null +++ b/rpc_deployment/roles/container_common/templates/container_interface_file.j2 @@ -0,0 +1,25 @@ +{%- set used_interfaces = [] %} +{%- for net in provider_networks %} + {%- if net.network.container_interface not in used_interfaces %} + {%- for group in net.network.group_binds if group in hostvars[inventory_hostname]['group_names'] %} + {%- if net.network.container_interface not in used_interfaces %} + {%- if used_interfaces.append(net.network.container_interface) %}{%- endif %} + {%- endif %} + {%- endfor %} +{% if net.network.container_interface in used_interfaces %} +{% if net.network.container_bridge != management_bridge %} +auto {{ net.network.container_interface }} + {% if 'ip_from_q' in net.network and hostvars[inventory_hostname][net.network.ip_from_q + '_address'] is defined %} +iface {{ net.network.container_interface }} inet static + address {{ hostvars[inventory_hostname][net.network.ip_from_q + '_address'] }} + netmask {{ net.network.subnetmask|default(hostvars[inventory_hostname][net.network.ip_from_q + '_netmask']) }} + {% else %} +iface {{ net.network.container_interface }} inet manual + {% endif %} +{% endif %} +{% endif %} + +{% endif %} +{% endfor %} + +# Used Devices: {{ used_interfaces }} diff --git a/rpc_deployment/roles/container_common/templates/host_container_interface.j2 b/rpc_deployment/roles/container_common/templates/host_container_interface.j2 new file mode 100644 index 0000000000..9064d14b39 --- /dev/null +++ b/rpc_deployment/roles/container_common/templates/host_container_interface.j2 @@ -0,0 +1,29 @@ +{%- set used_interfaces = [] %} +{%- for net in provider_networks %} + {%- if net.network.container_interface not in used_interfaces %} + {%- for group in net.network.group_binds %} + {%- if group in hostvars[inventory_hostname]['group_names'] %} + {%- if net.network.container_interface not in used_interfaces %} + {%- if used_interfaces.append(net.network.container_interface) %}{%- endif %} + {%- endif %} + {%- endif %} + {%- endfor %} +{% if net.network.container_interface in used_interfaces %} +{% if net.network.container_bridge != management_bridge %} +# Create a veth pair within the container +lxc.network.type = veth +# Network device within the container +lxc.network.name = {{ net.network.container_interface }} +# Host link to attach to, this should be a bridge +lxc.network.link = {{ net.network.container_bridge }} +# Hardware Address +lxc.network.hwaddr = 00:16:3e:xx:xx:xx +# enable the device on boot +lxc.network.flags = up + +{% endif %} +{% endif %} +{%- endif %} +{%- endfor %} +# All used used interfaces built from the provider_networks array +# Devices: {{ used_interfaces }} diff --git a/rpc_deployment/roles/container_create/tasks/main.yml b/rpc_deployment/roles/container_create/tasks/main.yml new file mode 100644 index 0000000000..6dd0257269 --- /dev/null +++ b/rpc_deployment/roles/container_create/tasks/main.yml @@ -0,0 +1,58 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Create an LXC container. + +- name: Check for lxc volume group + shell: > + (which vgs > /dev/null && vgs | grep -o "lxc") || false + register: vg_result + ignore_errors: True + +- name: Create Container Local + lxc: > + name={{ hostvars[item]['container_name'] }} + template={{ container_template }} + config={{ hostvars[item]['container_config'] }} + command=create + state=running + template_options=" + --release {{ container_release }} + " + when: vg_result.rc == 1 + with_items: container_groups + +- name: Check Container Bridge exists + file: > + state=file + path="/sys/class/net/{{ management_bridge }}/bridge/bridge_id" + +- name: Create Container LVM + lxc: > + name={{ hostvars[item]['container_name'] }} + template={{ container_template }} + config={{ hostvars[item]['container_config'] }} + command=create + state=running + bdev=lvm + lvname={{ hostvars[item]['container_name'] }} + vgname=lxc + fstype={{ hostvars[item]['container_lvm_fstype'] }} + fssize={{ hostvars[item]['container_lvm_fssize'] }} + template_options=" + --release {{ container_release }} + " + when: vg_result.rc == 0 + with_items: container_groups diff --git a/rpc_deployment/roles/container_destroy/tasks/main.yml b/rpc_deployment/roles/container_destroy/tasks/main.yml new file mode 100644 index 0000000000..a964a589bc --- /dev/null +++ b/rpc_deployment/roles/container_destroy/tasks/main.yml @@ -0,0 +1,22 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# destroy an LXC container. + +- name: Destroy Containers + lxc: > + name={{ hostvars[item]['container_name'] }} + command=destroy + with_items: container_groups diff --git a/rpc_deployment/roles/container_extra_setup/tasks/container_setup.yml b/rpc_deployment/roles/container_extra_setup/tasks/container_setup.yml new file mode 100644 index 0000000000..2dea846522 --- /dev/null +++ b/rpc_deployment/roles/container_extra_setup/tasks/container_setup.yml @@ -0,0 +1,50 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Ensure extra inner directories + file: > + path={{ item }} + state=directory + with_items: required_inner_dirs + when: required_inner_dirs is defined + register: inner_extra_changed + +- name: Ensure extra local directories + file: > + path={{ item }} + state=directory + when: required_outer_dirs is defined + with_items: required_outer_dirs + register: local_extra_changed + delegate_to: "{{ physical_host }}" + +- name: Ensure extra container config options + lxc: > + name={{ container_name }} + command=config + options="{{ container_config_options }}" + state=running + when: container_config_options is defined and is_metal != true + register: config_extra_changed + delegate_to: "{{ physical_host }}" + +- name: Wait for networking + wait_for: > + port=22 + search_regex=OpenSSH + timeout=60 + host={{ container_address }} + delegate_to: localhost + when: inner_extra_changed|changed or local_extra_changed|changed or config_extra_changed|changed diff --git a/rpc_deployment/roles/container_extra_setup/tasks/kernel_module.yml b/rpc_deployment/roles/container_extra_setup/tasks/kernel_module.yml new file mode 100644 index 0000000000..1b90f435af --- /dev/null +++ b/rpc_deployment/roles/container_extra_setup/tasks/kernel_module.yml @@ -0,0 +1,29 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: "Ensure kernel module(s)" + modprobe: + name: "{{ item }}" + with_items: kernel_modules + when: kernel_modules is defined + delegate_to: "{{ physical_host }}" + +- name: "Ensure kernel module(s) loaded at boot" + lineinfile: + dest: /etc/modules + line: "{{ item }}" + with_items: kernel_modules + when: kernel_modules is defined + delegate_to: "{{ physical_host }}" diff --git a/rpc_deployment/roles/container_extra_setup/tasks/main.yml b/rpc_deployment/roles/container_extra_setup/tasks/main.yml new file mode 100644 index 0000000000..b570c4ba58 --- /dev/null +++ b/rpc_deployment/roles/container_extra_setup/tasks/main.yml @@ -0,0 +1,18 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: kernel_module.yml +- include: sysctl.yml +- include: container_setup.yml diff --git a/rpc_deployment/roles/container_extra_setup/tasks/sysctl.yml b/rpc_deployment/roles/container_extra_setup/tasks/sysctl.yml new file mode 100644 index 0000000000..ccb6da9f70 --- /dev/null +++ b/rpc_deployment/roles/container_extra_setup/tasks/sysctl.yml @@ -0,0 +1,25 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Adding new system tuning + sysctl: > + name="{{ item.key }}" + value="{{ item.value }}" + sysctl_set="{{ item.set|default('yes') }}" + state="{{ item.state|default('present') }}" + reload="{{ item.reload|default('yes') }}" + when: sysctl_options is defined + with_items: sysctl_options + delegate_to: "{{ physical_host }}" diff --git a/rpc_deployment/roles/container_restart/tasks/main.yml b/rpc_deployment/roles/container_restart/tasks/main.yml new file mode 100644 index 0000000000..3c0048f5d4 --- /dev/null +++ b/rpc_deployment/roles/container_restart/tasks/main.yml @@ -0,0 +1,43 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Test Container Networking + wait_for: > + port=22 + timeout=60 + search_regex=OpenSSH + host={{ hostvars[item]['container_address'] }} + with_items: container_groups + delegate_to: localhost + register: network_check + ignore_errors: yes + +- name: Restart containers + lxc: > + name={{ hostvars[item]['container_name'] }} + command=restart + with_items: container_groups + when: network_check|failed + +- name: Check Networking After Restart + wait_for: > + port=22 + timeout=60 + search_regex=OpenSSH + host={{ hostvars[item]['container_address'] }} + with_items: container_groups + delegate_to: localhost + when: network_check|failed + diff --git a/rpc_deployment/roles/container_setup/tasks/main.yml b/rpc_deployment/roles/container_setup/tasks/main.yml new file mode 100644 index 0000000000..0bbcc2e89b --- /dev/null +++ b/rpc_deployment/roles/container_setup/tasks/main.yml @@ -0,0 +1,122 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Obtain the Systems SSH-Key + set_fact: + container_ssh_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" + +- name: Fail when empty or non-existent SSH pub key + fail: > + msg="Failing - ~/.ssh/id_rsa.pub file doesn't exist or is empty" + when: container_ssh_key == "" + +- name: Set the SSH key in place + lxc: > + name={{ hostvars[item]['container_name'] }} + command=attach + container_command=" + mkdir -p ~/.ssh/; + if [ ! -f \"~/.ssh/authorized_keys\" ];then + touch ~/.ssh/authorized_keys; + fi; + grep '{{ container_ssh_key }}' ~/.ssh/authorized_keys || + echo '{{ container_ssh_key }}' | tee -a ~/.ssh/authorized_keys; + " + with_items: container_groups + +- name: Set base network interface + lxc: > + name={{ hostvars[item]['container_name'] }} + command=attach + container_command=" + echo -e '{{ container_interface }}' | tee /etc/network/interfaces; + " + with_items: container_groups + +- name: Set management network interface + lxc: > + name={{ hostvars[item]['container_name'] }} + command=attach + container_command=" + echo -e '{{ management_interface }}' | tee /etc/network/interfaces.d/management.cfg; + " + with_items: container_groups + +- name: Ensure SSH is avail at boot + lxc: > + name={{ hostvars[item]['container_name'] }} + command=attach + container_command="update-rc.d ssh defaults" + with_items: container_groups + +- name: Ensure SSH is available for root + lxc: > + name={{ hostvars[item]['container_name'] }} + command=attach + container_command="sed -i 's/PermitRootLogin.*/PermitRootLogin\ yes/g' /etc/ssh/sshd_config" + with_items: container_groups + +- name: Ensure SSH started + lxc: > + name={{ hostvars[item]['container_name'] }} + command=attach + container_command="service ssh restart" + with_items: container_groups + +- name: Ensure required inner directories + lxc: > + name={{ hostvars[item.1]['container_name'] }} + command=attach + container_command="mkdir -p {{ item.0 }}" + with_nested: + - [ "/monitoring", "/etc/network/interfaces.d" ] + - container_groups + +- name: Create Required local log directories + file: > + path=/openstack/log/{{ hostvars[item]['container_name'] }} + state=directory + with_items: container_groups + +- name: Create Required local monitoring directories + file: > + path={{ item }} + state=directory + with_items: + - "/openstack/monitoring" + +- name: Ensure required inner service directories + lxc: > + name={{ hostvars[item.1]['container_name'] }} + command=attach + container_command="mkdir -p {{ item.0 }}/{{ hostvars[item.1]['service_name'] }}" + with_nested: + - [ "/etc", "/var/log" ] + - container_groups + +- name: Ensure python2.7 installed + lxc: > + name={{ hostvars[item]['container_name'] }} + command=attach + container_command="apt-get -y install python2.7; rm /usr/bin/python; ln -s /usr/bin/python2.7 /usr/bin/python" + with_items: container_groups + +- name: Ensure Required container config options + lxc: > + name={{ hostvars[item]['container_name'] }} + command=config + options="{{ required_container_config_options }}" + state=running + with_items: container_groups diff --git a/rpc_deployment/roles/elasticsearch/tasks/main.yml b/rpc_deployment/roles/elasticsearch/tasks/main.yml new file mode 100644 index 0000000000..8b5a67711d --- /dev/null +++ b/rpc_deployment/roles/elasticsearch/tasks/main.yml @@ -0,0 +1,92 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: ElasticSearch Setup + template: > + src={{ item }} + dest=/etc/elasticsearch/{{ item }} + owner=root + group=root + register: results + with_items: + - elasticsearch.yml + - logging.yml + +- name: ElasticSearch Tuning + template: > + src={{ item }} + dest=/etc/default/{{ item }} + owner=root + group=root + register: results + with_items: + - elasticsearch + +- name: Install ElasticHQ Plugin + command: ./plugin -install {{ item }} + args: + chdir: /usr/share/elasticsearch/bin + creates: /usr/share/elasticsearch/plugins/HQ + with_items: + - royrusso/elasticsearch-HQ + +- name: Install Kopf Plugin + command: ./plugin -install {{ item }} + args: + chdir: /usr/share/elasticsearch/bin + creates: /usr/share/elasticsearch/plugins/kopf + with_items: + - lmenezes/elasticsearch-kopf + +- name: Install Head Plugin + command: ./plugin -install {{ item }} + args: + chdir: /usr/share/elasticsearch/bin + creates: /usr/share/elasticsearch/plugins/head + with_items: + - mobz/elasticsearch-head + +- name: Install BigDesk Plugin + command: ./plugin -install {{ item }} + args: + chdir: /usr/share/elasticsearch/bin + creates: /usr/share/elasticsearch/plugins/bigdesk + with_items: + - lukas-vlcek/bigdesk/2.4.0 + +- name: restart elasticsearch + service: name=elasticsearch state=restarted pattern=elasticsearch enabled=yes + when: results|changed + +- name: Wait for elasticsearch port + wait_for: > + host={{ ansible_ssh_host }} + port=9200 + +- name: Deploy mapping script + template: > + src={{ item }} + dest=/opt/{{ item }} + owner=root + group=root + mode=0755 + with_items: + - mapping.sh + +- name: Add logging template + shell: > + ./mapping.sh + chdir=/opt + diff --git a/rpc_deployment/roles/elasticsearch/templates/elasticsearch b/rpc_deployment/roles/elasticsearch/templates/elasticsearch new file mode 100644 index 0000000000..6805462b76 --- /dev/null +++ b/rpc_deployment/roles/elasticsearch/templates/elasticsearch @@ -0,0 +1,50 @@ +# Run Elasticsearch as this user ID and group ID +#ES_USER=elasticsearch +#ES_GROUP=elasticsearch + +# Heap Size (defaults to 256m min, 1g max) +{% set host_ram = hostvars[inventory_hostname]['ansible_memtotal_mb']|int * 0.5 %} +{% set host_ram_int = host_ram // 1 %} +{% if host_ram > 16384 %} +ES_HEAP_SIZE=16g +{% else %} +ES_HEAP_SIZE={{ host_ram_int|int }}m +{% endif %} + +# Heap new generation +#ES_HEAP_NEWSIZE= + +# max direct memory +#ES_DIRECT_SIZE=16g + +# Maximum number of open files, defaults to 65535. +#MAX_OPEN_FILES=65535 + +# Maximum locked memory size. Set to "unlimited" if you use the +# bootstrap.mlockall option in elasticsearch.yml. You must also set +# ES_HEAP_SIZE. +#MAX_LOCKED_MEMORY=unlimited + +# Maximum number of VMA (Virtual Memory Areas) a process can own +#MAX_MAP_COUNT=262144 + +# Elasticsearch log directory +#LOG_DIR=/var/log/elasticsearch + +# Elasticsearch data directory +#DATA_DIR=/var/lib/elasticsearch + +# Elasticsearch work directory +#WORK_DIR=/tmp/elasticsearch + +# Elasticsearch configuration directory +#CONF_DIR=/etc/elasticsearch + +# Elasticsearch configuration file (elasticsearch.yml) +#CONF_FILE=/etc/elasticsearch/elasticsearch.yml + +# Additional Java OPTS +#ES_JAVA_OPTS= + +# Configure restart on package upgrade (true, every other setting will lead to not restarting) +#RESTART_ON_UPGRADE=true diff --git a/rpc_deployment/roles/elasticsearch/templates/elasticsearch.yml b/rpc_deployment/roles/elasticsearch/templates/elasticsearch.yml new file mode 100644 index 0000000000..123af36094 --- /dev/null +++ b/rpc_deployment/roles/elasticsearch/templates/elasticsearch.yml @@ -0,0 +1,378 @@ +##################### Elasticsearch Configuration Example ##################### + +# This file contains an overview of various configuration settings, +# targeted at operations staff. Application developers should +# consult the guide at . +# +# The installation procedure is covered at +# . +# +# Elasticsearch comes with reasonable defaults for most settings, +# so you can try it out without bothering with configuration. +# +# Most of the time, these defaults are just fine for running a production +# cluster. If you're fine-tuning your cluster, or wondering about the +# effect of certain configuration option, please _do ask_ on the +# mailing list or IRC channel [http://elasticsearch.org/community]. + +# Any element in the configuration can be replaced with environment variables +# by placing them in ${...} notation. For example: +# +#node.rack: ${RACK_ENV_VAR} + +# For information on supported formats and syntax for the config file, see +# + + +################################### Cluster ################################### + +# Cluster name identifies your cluster for auto-discovery. If you're running +# multiple clusters on the same network, make sure you're using unique names. +# +#cluster.name: elasticsearch +cluster.name: {{ elasticsearch_cluster }} + + +#################################### Node ##################################### + +# Node names are generated dynamically on startup, so you're relieved +# from configuring them manually. You can tie this node to a specific name: +# +#node.name: "Franz Kafka" + +# Every node can be configured to allow or deny being eligible as the master, +# and to allow or deny to store the data. +# +# Allow this node to be eligible as a master node (enabled by default): +# +#node.master: true +# +# Allow this node to store data (enabled by default): +# +#node.data: true + +# You can exploit these settings to design advanced cluster topologies. +# +# 1. You want this node to never become a master node, only to hold data. +# This will be the "workhorse" of your cluster. +# +#node.master: false +#node.data: true +# +# 2. You want this node to only serve as a master: to not store any data and +# to have free resources. This will be the "coordinator" of your cluster. +# +#node.master: true +#node.data: false +# +# 3. You want this node to be neither master nor data node, but +# to act as a "search load balancer" (fetching data from nodes, +# aggregating results, etc.) +# +#node.master: false +#node.data: false + +# Use the Cluster Health API [http://localhost:9200/_cluster/health], the +# Node Info API [http://localhost:9200/_nodes] or GUI tools +# such as , +# , +# and +# to inspect the cluster state. + +# A node can have generic attributes associated with it, which can later be used +# for customized shard allocation filtering, or allocation awareness. An attribute +# is a simple key value pair, similar to node.key: value, here is an example: +# +#node.rack: rack314 + +# By default, multiple nodes are allowed to start from the same installation location +# to disable it, set the following: +#node.max_local_storage_nodes: 1 + + +#################################### Index #################################### + +# You can set a number of options (such as shard/replica options, mapping +# or analyzer definitions, translog settings, ...) for indices globally, +# in this file. +# +# Note, that it makes more sense to configure index settings specifically for +# a certain index, either when creating it or by using the index templates API. +# +# See and +# +# for more information. + +# Set the number of shards (splits) of an index (5 by default): +# +#index.number_of_shards: 10 + +# Set the number of replicas (additional copies) of an index (1 by default): +# +#index.number_of_replicas: 2 + +# Note, that for development on a local machine, with small indices, it usually +# makes sense to "disable" the distributed features: +# +index.number_of_shards: 1 +index.number_of_replicas: 0 + +# These settings directly affect the performance of index and search operations +# in your cluster. Assuming you have enough machines to hold shards and +# replicas, the rule of thumb is: +# +# 1. Having more *shards* enhances the _indexing_ performance and allows to +# _distribute_ a big index across machines. +# 2. Having more *replicas* enhances the _search_ performance and improves the +# cluster _availability_. +# +# The "number_of_shards" is a one-time setting for an index. +# +# The "number_of_replicas" can be increased or decreased anytime, +# by using the Index Update Settings API. +# +# Elasticsearch takes care about load balancing, relocating, gathering the +# results from nodes, etc. Experiment with different settings to fine-tune +# your setup. + +# Use the Index Status API () to inspect +# the index status. + + +#################################### Paths #################################### + +# Path to directory containing configuration (this file and logging.yml): +# +#path.conf: /path/to/conf + +# Path to directory where to store index data allocated for this node. +# +#path.data: /path/to/data +# +# Can optionally include more than one location, causing data to be striped across +# the locations (a la RAID 0) on a file level, favouring locations with most free +# space on creation. For example: +# +#path.data: /path/to/data1,/path/to/data2 + +# Path to temporary files: +# +#path.work: /path/to/work + +# Path to log files: +# +#path.logs: /path/to/logs + +# Path to where plugins are installed: +# +#path.plugins: /path/to/plugins + + +#################################### Plugin ################################### + +# If a plugin listed here is not installed for current node, the node will not start. +# +#plugin.mandatory: mapper-attachments,lang-groovy + + +################################### Memory #################################### + +# Elasticsearch performs poorly when JVM starts swapping: you should ensure that +# it _never_ swaps. +# +# Set this property to true to lock the memory: +# +bootstrap.mlockall: true + +# Make sure that the ES_MIN_MEM and ES_MAX_MEM environment variables are set +# to the same value, and that the machine has enough memory to allocate +# for Elasticsearch, leaving enough memory for the operating system itself. +# +# You should also make sure that the Elasticsearch process is allowed to lock +# the memory, eg. by using `ulimit -l unlimited`. + + +############################## Network And HTTP ############################### + +# Elasticsearch, by default, binds itself to the 0.0.0.0 address, and listens +# on port [9200-9300] for HTTP traffic and on port [9300-9400] for node-to-node +# communication. (the range means that if the port is busy, it will automatically +# try the next port). + +# Set the bind address specifically (IPv4 or IPv6): +# +network.bind_host: {{ hostvars[inventory_hostname]['container_address'] }} + +# Set the address other nodes will use to communicate with this node. If not +# set, it is automatically derived. It must point to an actual IP address. +# +network.publish_host: {{ hostvars[inventory_hostname]['container_address'] }} + +# Set both 'bind_host' and 'publish_host': +# +#network.host: 192.168.0.1 + +# Set a custom port for the node to node communication (9300 by default): +# +#transport.tcp.port: 9300 + +# Enable compression for all communication between nodes (disabled by default): +# +#transport.tcp.compress: true + +# Set a custom port to listen for HTTP traffic: +# +#http.port: 9200 + +# Set a custom allowed content length: +# +#http.max_content_length: 100mb + +# Disable HTTP completely: +# +#http.enabled: false + + +################################### Gateway ################################### + +# The gateway allows for persisting the cluster state between full cluster +# restarts. Every change to the state (such as adding an index) will be stored +# in the gateway, and when the cluster starts up for the first time, +# it will read its state from the gateway. + +# There are several types of gateway implementations. For more information, see +# . + +# The default gateway type is the "local" gateway (recommended): +# +#gateway.type: local + +# Settings below control how and when to start the initial recovery process on +# a full cluster restart (to reuse as much local data as possible when using shared +# gateway). + +# Allow recovery process after N nodes in a cluster are up: +# +#gateway.recover_after_nodes: 1 + +# Set the timeout to initiate the recovery process, once the N nodes +# from previous setting are up (accepts time value): +# +#gateway.recover_after_time: 5m + +# Set how many nodes are expected in this cluster. Once these N nodes +# are up (and recover_after_nodes is met), begin recovery process immediately +# (without waiting for recover_after_time to expire): +# +#gateway.expected_nodes: 2 + + +############################# Recovery Throttling ############################# + +# These settings allow to control the process of shards allocation between +# nodes during initial recovery, replica allocation, rebalancing, +# or when adding and removing nodes. + +# Set the number of concurrent recoveries happening on a node: +# +# 1. During the initial recovery +# +#cluster.routing.allocation.node_initial_primaries_recoveries: 4 +# +# 2. During adding/removing nodes, rebalancing, etc +# +#cluster.routing.allocation.node_concurrent_recoveries: 2 + +# Set to throttle throughput when recovering (eg. 100mb, by default 20mb): +# +#indices.recovery.max_bytes_per_sec: 20mb + +# Set to limit the number of open concurrent streams when +# recovering a shard from a peer: +# +#indices.recovery.concurrent_streams: 5 + + +################################## Discovery ################################## + +# Discovery infrastructure ensures nodes can be found within a cluster +# and master node is elected. Multicast discovery is the default. + +# Set to ensure a node sees N other master eligible nodes to be considered +# operational within the cluster. Its recommended to set it to a higher value +# than 1 when running more than 2 nodes in the cluster. +# +#discovery.zen.minimum_master_nodes: 1 + +# Set the time to wait for ping responses from other nodes when discovering. +# Set this option to a higher value on a slow or congested network +# to minimize discovery failures: +# +#discovery.zen.ping.timeout: 3s + +# For more information, see +# + +# Unicast discovery allows to explicitly control which nodes will be used +# to discover the cluster. It can be used when multicast is not present, +# or to restrict the cluster communication-wise. +# +# 1. Disable multicast discovery (enabled by default): +# +#discovery.zen.ping.multicast.enabled: false +# +# 2. Configure an initial list of master nodes in the cluster +# to perform discovery when new nodes (master or data) are started: +# +#discovery.zen.ping.unicast.hosts: ["host1", "host2:port"] + +# EC2 discovery allows to use AWS EC2 API in order to perform discovery. +# +# You have to install the cloud-aws plugin for enabling the EC2 discovery. +# +# For more information, see +# +# +# See +# for a step-by-step tutorial. + +# GCE discovery allows to use Google Compute Engine API in order to perform discovery. +# +# You have to install the cloud-gce plugin for enabling the GCE discovery. +# +# For more information, see . + +# Azure discovery allows to use Azure API in order to perform discovery. +# +# You have to install the cloud-azure plugin for enabling the Azure discovery. +# +# For more information, see . + +################################## Slow Log ################################## + +# Shard level query and fetch threshold logging. + +#index.search.slowlog.threshold.query.warn: 10s +#index.search.slowlog.threshold.query.info: 5s +#index.search.slowlog.threshold.query.debug: 2s +#index.search.slowlog.threshold.query.trace: 500ms + +#index.search.slowlog.threshold.fetch.warn: 1s +#index.search.slowlog.threshold.fetch.info: 800ms +#index.search.slowlog.threshold.fetch.debug: 500ms +#index.search.slowlog.threshold.fetch.trace: 200ms + +#index.indexing.slowlog.threshold.index.warn: 10s +#index.indexing.slowlog.threshold.index.info: 5s +#index.indexing.slowlog.threshold.index.debug: 2s +#index.indexing.slowlog.threshold.index.trace: 500ms + +################################## GC Logging ################################ + +#monitor.jvm.gc.young.warn: 1000ms +#monitor.jvm.gc.young.info: 700ms +#monitor.jvm.gc.young.debug: 400ms + +#monitor.jvm.gc.old.warn: 10s +#monitor.jvm.gc.old.info: 5s +#monitor.jvm.gc.old.debug: 2s diff --git a/rpc_deployment/roles/elasticsearch/templates/logging.yml b/rpc_deployment/roles/elasticsearch/templates/logging.yml new file mode 100644 index 0000000000..9e00d01c66 --- /dev/null +++ b/rpc_deployment/roles/elasticsearch/templates/logging.yml @@ -0,0 +1,56 @@ +# you can override this using by setting a system property, for example -Des.logger.level=DEBUG +es.logger.level: INFO +rootLogger: ${es.logger.level}, console, file +logger: + # log action execution errors for easier debugging + action: DEBUG + # reduce the logging for aws, too much is logged under the default INFO + com.amazonaws: WARN + + # gateway + #gateway: DEBUG + #index.gateway: DEBUG + + # peer shard recovery + #indices.recovery: DEBUG + + # discovery + #discovery: TRACE + + index.search.slowlog: TRACE, index_search_slow_log_file + index.indexing.slowlog: TRACE, index_indexing_slow_log_file + +additivity: + index.search.slowlog: false + index.indexing.slowlog: false + +appender: + console: + type: console + layout: + type: consolePattern + conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n" + + file: + type: dailyRollingFile + file: ${path.logs}/${cluster.name}.log + datePattern: "'.'yyyy-MM-dd" + layout: + type: pattern + conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n" + + index_search_slow_log_file: + type: dailyRollingFile + file: ${path.logs}/${cluster.name}_index_search_slowlog.log + datePattern: "'.'yyyy-MM-dd" + layout: + type: pattern + conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n" + + index_indexing_slow_log_file: + type: dailyRollingFile + file: ${path.logs}/${cluster.name}_index_indexing_slowlog.log + datePattern: "'.'yyyy-MM-dd" + layout: + type: pattern + conversionPattern: "[%d{ISO8601}][%-5p][%-25c] %m%n" diff --git a/rpc_deployment/roles/elasticsearch/templates/mapping.sh b/rpc_deployment/roles/elasticsearch/templates/mapping.sh new file mode 100755 index 0000000000..f8646121fc --- /dev/null +++ b/rpc_deployment/roles/elasticsearch/templates/mapping.sh @@ -0,0 +1,302 @@ +#!/bin/sh +curl --retry 10 -XPUT 'http://{{ hostvars[groups['elasticsearch'][0]]['container_address'] }}:{{ elasticsearch_http_port }}/_template/log_test1' -d ' +{ + "template" : "*", + "order": 0, + "mappings" : { + "_default_" : { + "dynamic_templates" : [ { + "string_fields" : { + "mapping" : { + "index" : "analyzed", + "omit_norms" : true, + "type" : "string", + "fields" : { + "raw" : { + "index" : "not_analyzed", + "ignore_above" : 256, + "type" : "string" + } + } + }, + "match" : "*", + "match_mapping_type" : "string" + } + } ], + "properties" : { + "@version" : { + "type" : "string", + "index" : "not_analyzed" + }, + "geoip" : { + "dynamic" : "true", + "properties" : { + "location" : { + "type" : "geo_point" + } + } + } + } + }, + "logs" : { + "dynamic_templates" : [ { + "string_fields" : { + "mapping" : { + "index" : "analyzed", + "omit_norms" : true, + "type" : "string", + "fields" : { + "raw" : { + "index" : "not_analyzed", + "ignore_above" : 256, + "type" : "string" + } + } + }, + "match" : "*", + "match_mapping_type" : "string" + } + } ], + "properties" : { + "@fields" : { + "properties" : { + "facility" : { + "type" : "string", + "norms" : { + "enabled" : false + }, + "fields" : { + "raw" : { + "type" : "string", + "index" : "not_analyzed", + "ignore_above" : 256 + } + } + }, + "processid" : { + "type" : "string", + "norms" : { + "enabled" : false + }, + "fields" : { + "raw" : { + "type" : "string", + "index" : "not_analyzed", + "ignore_above" : 256 + } + } + }, + "program" : { + "type" : "string", + "norms" : { + "enabled" : false + }, + "fields" : { + "raw" : { + "type" : "string", + "index" : "not_analyzed", + "ignore_above" : 256 + } + } + }, + "severity" : { + "type" : "string", + "norms" : { + "enabled" : false + }, + "fields" : { + "raw" : { + "type" : "string", + "index" : "not_analyzed", + "ignore_above" : 256 + } + } + } + } + }, + "@message" : { + "type" : "string", + "norms" : { + "enabled" : false + }, + "fields" : { + "raw" : { + "type" : "string", + "index" : "not_analyzed", + "ignore_above" : 256 + } + } + }, + "@source" : { + "type" : "string", + "norms" : { + "enabled" : false + }, + "fields" : { + "raw" : { + "type" : "string", + "index" : "not_analyzed", + "ignore_above" : 256 + } + } + }, + "@source_host" : { + "type" : "string", + "norms" : { + "enabled" : false + }, + "fields" : { + "raw" : { + "type" : "string", + "index" : "not_analyzed", + "ignore_above" : 256 + } + } + }, + "@timestamp" : { + "type" : "date", + "format" : "dateOptionalTime" + }, + "@version" : { + "type" : "string", + "index" : "not_analyzed" + }, + "facility" : { + "type" : "long" + }, + "facility_label" : { + "type" : "string", + "norms" : { + "enabled" : false + }, + "fields" : { + "raw" : { + "type" : "string", + "index" : "not_analyzed", + "ignore_above" : 256 + } + } + }, + "geoip" : { + "dynamic" : "true", + "properties" : { + "location" : { + "type" : "geo_point" + } + } + }, + "host" : { + "type" : "ip", + "norms" : { + "enabled" : false + }, + "fields" : { + "raw" : { + "type" : "string", + "index" : "not_analyzed", + "ignore_above" : 256 + } + } + }, + "os_level" : { + "type" : "string", + "norms" : { + "enabled" : false + }, + "fields" : { + "raw" : { + "type" : "string", + "index" : "not_analyzed", + "ignore_above" : 256 + } + } + }, + "os_program" : { + "type" : "string", + "norms" : { + "enabled" : false + }, + "fields" : { + "raw" : { + "type" : "string", + "index" : "not_analyzed", + "ignore_above" : 256 + } + } + }, + "os_program_path" : { + "type" : "string", + "norms" : { + "enabled" : false + }, + "fields" : { + "raw" : { + "type" : "string", + "index" : "not_analyzed", + "ignore_above" : 256 + } + } + }, + "os_program_pid" : { + "type" : "string", + "norms" : { + "enabled" : false + }, + "fields" : { + "raw" : { + "type" : "string", + "index" : "not_analyzed", + "ignore_above" : 256 + } + } + }, + "os_timestamp" : { + "type" : "string", + "norms" : { + "enabled" : false + }, + "fields" : { + "raw" : { + "type" : "string", + "index" : "not_analyzed", + "ignore_above" : 256 + } + } + }, + "priority" : { + "type" : "long" + }, + "severity" : { + "type" : "long" + }, + "severity_label" : { + "type" : "string", + "norms" : { + "enabled" : false + }, + "fields" : { + "raw" : { + "type" : "string", + "index" : "not_analyzed", + "ignore_above" : 256 + } + } + }, + "tags" : { + "type" : "string", + "norms" : { + "enabled" : false + }, + "fields" : { + "raw" : { + "type" : "string", + "index" : "not_analyzed", + "ignore_above" : 256 + } + } + } + } + } + } + } +}' diff --git a/rpc_deployment/roles/galera_bootstrap/tasks/main.yml b/rpc_deployment/roles/galera_bootstrap/tasks/main.yml new file mode 100644 index 0000000000..ccded95b90 --- /dev/null +++ b/rpc_deployment/roles/galera_bootstrap/tasks/main.yml @@ -0,0 +1,39 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Check wsrep cluster size + shell: > + mysql -e 'show status like "wsrep_cluster_size%"\G'|awk '/Value/{print $2}' + register: wsrep_cluster_size + +- name: Stop mariadb + service: + name: mysql + state: stopped + pattern: mysqld + register: mysqlstopped + when: wsrep_cluster_size.stdout | search("1") or wsrep_cluster_size.stderr | search("ERROR") + +- name: Check if mysql is running + shell: > + pgrep -fl mysqld + register: mysql_running + +- name: bootstrap cluster (initialise mysql with --wsrep-new-cluster) + service: + name: mysql + state: restarted + args: --wsrep-new-cluster + when: wsrep_cluster_size.stdout|search("1") or mysqlstopped|changed or not mysql_running.stdout|search("mysql") diff --git a/rpc_deployment/roles/galera_client_cnf/tasks/main.yml b/rpc_deployment/roles/galera_client_cnf/tasks/main.yml new file mode 100644 index 0000000000..c3f1a3c1da --- /dev/null +++ b/rpc_deployment/roles/galera_client_cnf/tasks/main.yml @@ -0,0 +1,22 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Drop local .my.cnf file + template: > + src=client_my.cnf + dest=/root/.my.cnf + owner=root + group=root + mode=0600 diff --git a/rpc_deployment/roles/galera_client_cnf/templates/client_my.cnf b/rpc_deployment/roles/galera_client_cnf/templates/client_my.cnf new file mode 100644 index 0000000000..37e332c084 --- /dev/null +++ b/rpc_deployment/roles/galera_client_cnf/templates/client_my.cnf @@ -0,0 +1,4 @@ +[client] +host={{ mysql_address }} +user=root +password={{ mysql_password }} diff --git a/rpc_deployment/roles/galera_common/files/policy-rc.d b/rpc_deployment/roles/galera_common/files/policy-rc.d new file mode 100644 index 0000000000..ec21cabfa6 --- /dev/null +++ b/rpc_deployment/roles/galera_common/files/policy-rc.d @@ -0,0 +1,3 @@ +#!/bin/sh +echo "All runlevel operations denied by policy" >&2 +exit 101 diff --git a/rpc_deployment/roles/galera_common/tasks/main.yml b/rpc_deployment/roles/galera_common/tasks/main.yml new file mode 100644 index 0000000000..c615647050 --- /dev/null +++ b/rpc_deployment/roles/galera_common/tasks/main.yml @@ -0,0 +1,45 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Prevent mysql from starting on install + copy: + src: "policy-rc.d" + dest: "/usr/sbin/policy-rc.d" + mode: 0744 + backup: yes + +- name: Preseed mysql root password + debconf: + name: "{{ mariadb_server_package }}" + question: "mysql-server/{{ item }}" + value: "{{ mysql_password }}" + vtype: string + with_items: + - root_password + - root_password_again + +- name: Install galera packages + apt: + pkg: "{{ item }}" + state: latest + update_cache: yes + cache_valid_time: 600 + with_items: galera_packages + +# Remove the file that prevents the services from starting +- name: Remove /usr/sbin/policy-rc.d + file: + path: "/usr/sbin/policy-rc.d" + state: absent diff --git a/rpc_deployment/roles/galera_config/tasks/main.yml b/rpc_deployment/roles/galera_config/tasks/main.yml new file mode 100644 index 0000000000..4ae65361bc --- /dev/null +++ b/rpc_deployment/roles/galera_config/tasks/main.yml @@ -0,0 +1,34 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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 the local directories + file: > + path={{ item }} + state=directory + group=root + owner=root + recurse=true + with_items: + - /etc/mysql/conf.d + +- name: Drop mariadb configs + template: > + src={{ item.src }} + dest={{ item.dest }} + register: mariadb_config + with_items: + - { src: my.cnf, dest: /etc/mysql/my.cnf } + - { src: cluster.cnf, dest: /etc/mysql/conf.d/cluster.cnf } + - { src: debian.cnf, dest: /etc/mysql/debian.cnf } diff --git a/rpc_deployment/roles/galera_config/templates/cluster.cnf b/rpc_deployment/roles/galera_config/templates/cluster.cnf new file mode 100644 index 0000000000..51dbeecd73 --- /dev/null +++ b/rpc_deployment/roles/galera_config/templates/cluster.cnf @@ -0,0 +1,28 @@ +[mysqld] +# Path to Galera library +wsrep_provider=/usr/lib/galera/libgalera_smm.so +wsrep_provider_options="gcache.size={{ galera_gcache_size|default('1G') }}" + +# Cluster connection URL contains the IPs of node#1, node#2 and node#3 +wsrep_cluster_address=gcomm://{% for host in groups['galera'] %}{{ hostvars[host]['container_address'] }}{% if not loop.last %},{% endif %}{% endfor %} + +# In order for Galera to work correctly binlog format should be ROW +binlog_format=ROW + +# MyISAM storage engine has only experimental support +default_storage_engine=InnoDB + +# This changes how InnoDB autoincrement locks are managed and is a requirement for Galera +innodb_autoinc_lock_mode=2 + +# This should be the IP and DNS name for the current system on which you're editing the file. +wsrep_node_address={{ container_address }} +wsrep_node_name={{ ansible_hostname }} + +# SST method +wsrep_sst_method=xtrabackup +wsrep_sst_auth=root:{{ mysql_password }} +wsrep_slave_threads=16 + +# Cluster name +wsrep_cluster_name="rpc_galera_cluster" diff --git a/rpc_deployment/roles/galera_config/templates/debian.cnf b/rpc_deployment/roles/galera_config/templates/debian.cnf new file mode 100644 index 0000000000..ec6aebed17 --- /dev/null +++ b/rpc_deployment/roles/galera_config/templates/debian.cnf @@ -0,0 +1,11 @@ +[client] +host = localhost +user = debian-sys-maint +password = {{ debian_sys_maint_password }} +socket = /var/run/mysqld/mysqld.sock +[mysql_upgrade] +host = localhost +user = debian-sys-maint +password = {{ debian_sys_maint_password }} +socket = /var/run/mysqld/mysqld.sock +basedir = /usr diff --git a/rpc_deployment/roles/galera_config/templates/my.cnf b/rpc_deployment/roles/galera_config/templates/my.cnf new file mode 100644 index 0000000000..b2e74fb0a0 --- /dev/null +++ b/rpc_deployment/roles/galera_config/templates/my.cnf @@ -0,0 +1,63 @@ +[client] +port = 3306 +socket = /var/run/mysqld/mysqld.sock +default-character-set = utf8 + + +[mysqld_safe] +socket = /var/run/mysqld/mysqld.sock +nice = 0 + + +[mysql] +default-character-set = utf8 + + +[mysqld] +user = mysql +collation-server = utf8_unicode_ci +init-connect = 'SET NAMES utf8' +character-set-server = utf8 + + +# SAFETY # +max-allowed-packet = 16M +max-connect-errors = 1000000 +max_connections = 500 + +# CACHES AND LIMITS # +tmp-table-size = 32M +max-heap-table-size = 32M +query-cache-type = 1 +query-cache-size = 50M +max-connections = 500 +thread-cache-size = 50 +open-files-limit = 65535 +table-definition-cache = 4096 +table-open-cache = 10240 + +# INNODB # +innodb-flush-method = O_DIRECT +innodb-log-files-in-group = 2 +innodb-log-file-size = 128M +innodb-flush-log-at-trx-commit = 1 +innodb-file-per-table = 1 +innodb-buffer-pool-size = 2G + +datadir = /var/lib/mysql + +# LOGGING # +log-queries-not-using-indexes = 1 +slow-query-log = 1 +slow-query-log-file = /var/log/mysql/mysql-slow.log +log_error = /var/log/mysql/galera_server_error.log +log-bin = /var/lib/mysql/mariadb-bin +log-bin-index = /var/lib/mysql/mariadb-bin.index + +[mysqldump] +quick +quote-names +max_allowed_packet = 16M + + +!includedir /etc/mysql/conf.d/ diff --git a/rpc_deployment/roles/galera_db_setup/tasks/main.yml b/rpc_deployment/roles/galera_db_setup/tasks/main.yml new file mode 100644 index 0000000000..6bec7eb8c5 --- /dev/null +++ b/rpc_deployment/roles/galera_db_setup/tasks/main.yml @@ -0,0 +1,36 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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 DB for service + mysql_db: > + login_user="{{ mysql_user }}" + login_password="{{ mysql_password }}" + login_host="{{ mysql_address }}" + name="{{ container_database }}" + state=present + +- name: Grant access to the DB for the service + mysql_user: > + login_user="{{ mysql_user }}" + login_password="{{ mysql_password }}" + login_host="{{ mysql_address }}" + name="{{ container_mysql_user }}" + password="{{ container_mysql_password }}" + host="{{ item }}" + state=present + priv={{ container_database }}.*:ALL + with_items: + - "localhost" + - "%" diff --git a/rpc_deployment/roles/galera_db_setup/templates/my.cnf b/rpc_deployment/roles/galera_db_setup/templates/my.cnf new file mode 100644 index 0000000000..ba7ab7adee --- /dev/null +++ b/rpc_deployment/roles/galera_db_setup/templates/my.cnf @@ -0,0 +1,3 @@ +[client] +user={{ mysql_user }} +password={{ mysql_password }} diff --git a/rpc_deployment/roles/galera_post_config/tasks/main.yml b/rpc_deployment/roles/galera_post_config/tasks/main.yml new file mode 100644 index 0000000000..160d732ef7 --- /dev/null +++ b/rpc_deployment/roles/galera_post_config/tasks/main.yml @@ -0,0 +1,25 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Ensure permissions on Log dir make it readable by syslog + file: > + path={{ item.path }} + state=directory + group={{ item.owner }} + owner={{ item.owner }} + mode=0755 + recurse=true + with_items: + - { path: '/var/log/mysql/', owner: 'mysql' } diff --git a/rpc_deployment/roles/galera_remove/tasks/main.yml b/rpc_deployment/roles/galera_remove/tasks/main.yml new file mode 100644 index 0000000000..98c23cf771 --- /dev/null +++ b/rpc_deployment/roles/galera_remove/tasks/main.yml @@ -0,0 +1,40 @@ +# Copyright 2014, Rackspace US, Inc. +# +# 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: Stop mysql + service: + name: mysql + state: stopped + ignore_errors: yes + +- name: Remove galera packages + apt: + pkg: "{{ item }}" + state: absent + purge: no + update_cache: no + cache_valid_time: 600 + with_items: galera_packages + ignore_errors: yes + +- name: Remove db related paths + file: + path: "{{ item }}" + state: absent + with_items: + - /var/lib/mysql/* + - /etc/mysql + - /var/log/mysql/* + - /root/.my.cnf + ignore_errors: yes diff --git a/rpc_deployment/roles/galera_restart/tasks/main.yml b/rpc_deployment/roles/galera_restart/tasks/main.yml new file mode 100644 index 0000000000..4cddc7d8ea --- /dev/null +++ b/rpc_deployment/roles/galera_restart/tasks/main.yml @@ -0,0 +1,25 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Get incoming addresses from cluster + shell: > + mysql -e 'show status like "wsrep_incoming_addresses"\G'|awk '/Value/{print $2}' + register: wsrep_incoming_addresses + +- name: Restart mysql + service: + name: mysql + state: restarted + when: not wsrep_incoming_addresses.stdout|search("{{ container_address }}") diff --git a/rpc_deployment/roles/galera_setup/tasks/main.yml b/rpc_deployment/roles/galera_setup/tasks/main.yml new file mode 100644 index 0000000000..abb3c8f221 --- /dev/null +++ b/rpc_deployment/roles/galera_setup/tasks/main.yml @@ -0,0 +1,55 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Debian-sys-maint account is used to start/stop mysql. The password is auto +# generated but must be the same otherwise once data is synced, two nodes +# will not be able to start/stop mysql. +- name: Create mysql users + mysql_user: + name: "{{ item.name }}" + host: "{{ item.host }}" + password: "{{ item.password }}" + priv: "{{ item.priv }}" + state: "{{ item.state }}" + with_items: + - name: "root" + host: "%" + password: "{{ mysql_password }}" + priv: "*.*:ALL,GRANT" + state: present + + - name: "root" + host: "localhost" + password: "" + priv: "*.*:ALL" + state: absent + + - name: "debian-sys-maint" + host: 'localhost' + password: "{{ debian_sys_maint_password }}" + priv: "*.*:ALL" + state: present + + - name: haproxy + host: '%' + password: "" + priv: "*.*:USAGE" + state: present + + - name: haproxy + host: 'localhost' + password: "" + priv: "*.*:USAGE" + state: present diff --git a/rpc_deployment/roles/galera_stop/tasks/main.yml b/rpc_deployment/roles/galera_stop/tasks/main.yml new file mode 100644 index 0000000000..62678692dd --- /dev/null +++ b/rpc_deployment/roles/galera_stop/tasks/main.yml @@ -0,0 +1,26 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Stop MariaDB + service: + name: mysql + state: stopped + register: mariadb_stop + ignore_errors: True + +- name: Force Stop MariaDB + shell: > + killall -15 mysqld + when: mariadb_stop|failed diff --git a/rpc_deployment/roles/glance_cache_crons/tasks/main.yml b/rpc_deployment/roles/glance_cache_crons/tasks/main.yml new file mode 100644 index 0000000000..289dbac473 --- /dev/null +++ b/rpc_deployment/roles/glance_cache_crons/tasks/main.yml @@ -0,0 +1,31 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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 glance cache management cron jobs + cron: + name: "{{ item.name }}" + minute: "{{ 59 |random }}" + day: "*" + hour: "{{ item.hour }}" + month: "*" + state: present + job: "{{ item.name }}" + user: glance + with_items: + - name: glance-cache-pruner + hour: "*" + - name: glance-cache-cleaner + hour: "{{ 23|random }}" + when: flavor | search("cache") diff --git a/rpc_deployment/roles/glance_common/tasks/glance_config.yml b/rpc_deployment/roles/glance_common/tasks/glance_config.yml new file mode 100644 index 0000000000..d10b2fd245 --- /dev/null +++ b/rpc_deployment/roles/glance_common/tasks/glance_config.yml @@ -0,0 +1,41 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Drop Glance Config + template: > + src={{ item }} + dest=/etc/glance/{{ item }} + owner={{ system_user }} + group={{ system_group }} + with_items: + - policy.json + - schema.json + - schema-image.json + notify: Restart os service + +- name: Generate Glance Config + template: > + src=template_gen + dest=/etc/glance/{{ item.file }} + owner={{ system_user }} + group={{ system_group }} + with_items: + - { file: glance-registry-paste.ini, var: "{{ glance_registry_paste_ini }}" } + - { file: glance-api-paste.ini, var: "{{ glance_api_paste_ini }}" } + - { file: glance-registry.conf, var: "{{ glance_registry_conf }}" } + - { file: glance-api.conf, var: "{{ glance_api_conf }}" } + - { file: glance-cache.conf, var: "{{ glance_cache_conf }}" } + - { file: glance-scrubber.conf, var: "{{ glance_scrubber_conf }}" } + notify: Restart os service diff --git a/rpc_deployment/roles/glance_common/tasks/main.yml b/rpc_deployment/roles/glance_common/tasks/main.yml new file mode 100644 index 0000000000..d5830160d7 --- /dev/null +++ b/rpc_deployment/roles/glance_common/tasks/main.yml @@ -0,0 +1,16 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: glance_config.yml diff --git a/rpc_deployment/roles/glance_common/templates/policy.json b/rpc_deployment/roles/glance_common/templates/policy.json new file mode 100644 index 0000000000..d8f0a78cb6 --- /dev/null +++ b/rpc_deployment/roles/glance_common/templates/policy.json @@ -0,0 +1,32 @@ +{ + "context_is_admin": "role:admin", + "default": "", + + "add_image": "", + "delete_image": "", + "get_image": "", + "get_images": "", + "modify_image": "", + "publicize_image": "", + "copy_from": "", + + "download_image": "", + "upload_image": "", + + "delete_image_location": "", + "get_image_location": "", + "set_image_location": "", + + "add_member": "", + "delete_member": "", + "get_member": "", + "get_members": "", + "modify_member": "", + + "manage_image_cache": "role:admin", + + "get_task": "", + "get_tasks": "", + "add_task": "", + "modify_task": "" +} diff --git a/rpc_deployment/roles/glance_common/templates/schema-image.json b/rpc_deployment/roles/glance_common/templates/schema-image.json new file mode 100644 index 0000000000..5aafd6b371 --- /dev/null +++ b/rpc_deployment/roles/glance_common/templates/schema-image.json @@ -0,0 +1,28 @@ +{ + "kernel_id": { + "type": "string", + "pattern": "^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$", + "description": "ID of image stored in Glance that should be used as the kernel when booting an AMI-style image." + }, + "ramdisk_id": { + "type": "string", + "pattern": "^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$", + "description": "ID of image stored in Glance that should be used as the ramdisk when booting an AMI-style image." + }, + "instance_uuid": { + "type": "string", + "description": "ID of instance used to create this image." + }, + "architecture": { + "description": "Operating system architecture as specified in http://docs.openstack.org/trunk/openstack-compute/admin/content/adding-images.html", + "type": "string" + }, + "os_distro": { + "description": "Common name of operating system distribution as specified in http://docs.openstack.org/trunk/openstack-compute/admin/content/adding-images.html", + "type": "string" + }, + "os_version": { + "description": "Operating system version as specified by the distributor", + "type": "string" + } +} diff --git a/rpc_deployment/roles/glance_common/templates/schema.json b/rpc_deployment/roles/glance_common/templates/schema.json new file mode 100644 index 0000000000..5aafd6b371 --- /dev/null +++ b/rpc_deployment/roles/glance_common/templates/schema.json @@ -0,0 +1,28 @@ +{ + "kernel_id": { + "type": "string", + "pattern": "^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$", + "description": "ID of image stored in Glance that should be used as the kernel when booting an AMI-style image." + }, + "ramdisk_id": { + "type": "string", + "pattern": "^([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}$", + "description": "ID of image stored in Glance that should be used as the ramdisk when booting an AMI-style image." + }, + "instance_uuid": { + "type": "string", + "description": "ID of instance used to create this image." + }, + "architecture": { + "description": "Operating system architecture as specified in http://docs.openstack.org/trunk/openstack-compute/admin/content/adding-images.html", + "type": "string" + }, + "os_distro": { + "description": "Common name of operating system distribution as specified in http://docs.openstack.org/trunk/openstack-compute/admin/content/adding-images.html", + "type": "string" + }, + "os_version": { + "description": "Operating system version as specified by the distributor", + "type": "string" + } +} diff --git a/rpc_deployment/roles/glance_common/templates/template_gen b/rpc_deployment/roles/glance_common/templates/template_gen new file mode 100644 index 0000000000..f7ec1856f3 --- /dev/null +++ b/rpc_deployment/roles/glance_common/templates/template_gen @@ -0,0 +1,20 @@ +# {{ ansible_managed }} +# Changes to this file are found within the vars/config_vars + +{% for key, value in item.var.items() %} + +[{{ key }}] +{% for _key, _value in value.items() %} +{% if _value is string %} +{{ _key }} = {{ _value }} +{% elif _value is number %} +{{ _key }} = {{ _value }} +{% elif _value is iterable %} +{{ _key }} = {{ _value|join(", ") }} +{% else %} +# Value type skipped as it was indeterminable +# {{ _value }} +{% endif %} +{% endfor %} + +{% endfor %} diff --git a/rpc_deployment/roles/glance_setup/tasks/main.yml b/rpc_deployment/roles/glance_setup/tasks/main.yml new file mode 100644 index 0000000000..d01a2ed911 --- /dev/null +++ b/rpc_deployment/roles/glance_setup/tasks/main.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Perform a Glance DB sync + command: glance-manage db_sync diff --git a/rpc_deployment/roles/glance_snet_override/tasks/main.yml b/rpc_deployment/roles/glance_snet_override/tasks/main.yml new file mode 100644 index 0000000000..a3f4590768 --- /dev/null +++ b/rpc_deployment/roles/glance_snet_override/tasks/main.yml @@ -0,0 +1,13 @@ +--- +- name: Add hosts entry if glance_swift_enable_snet is True + lineinfile: + dest: /etc/hosts + regexp: "{{ cf_snet_endpoints[glance_swift_store_region]['hostname'] }}" + line: "{{ cf_snet_endpoints[glance_swift_store_region]['ip'] }} {{ cf_snet_endpoints[glance_swift_store_region]['hostname'] }}" + when: glance_swift_enable_snet +- name: Remove hosts entry if glance_swift_enable_snet is False + lineinfile: + dest: /etc/hosts + regexp: "{{ cf_snet_endpoints[glance_swift_store_region]['hostname'] }}" + state: absent + when: not glance_swift_enable_snet diff --git a/rpc_deployment/roles/haproxy_check/tasks/main.yml b/rpc_deployment/roles/haproxy_check/tasks/main.yml new file mode 100644 index 0000000000..9dddd16092 --- /dev/null +++ b/rpc_deployment/roles/haproxy_check/tasks/main.yml @@ -0,0 +1,21 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: "Wait for HAProxy to come up" + wait_for: + host: "{{ internal_vip_address }}" + port: "{{ hap_port }}" + timeout: 5 + delay: 0 diff --git a/rpc_deployment/roles/haproxy_common/files/haproxy.default b/rpc_deployment/roles/haproxy_common/files/haproxy.default new file mode 100644 index 0000000000..6028662686 --- /dev/null +++ b/rpc_deployment/roles/haproxy_common/files/haproxy.default @@ -0,0 +1,7 @@ +# Set ENABLED to 1 if you want the init script to start haproxy. +ENABLED=1 +# Add extra flags here. +#EXTRAOPTS="-de -m 16" + +# Conf.d style configuration dir. Init script has been hacked to support this. +CONFIG_DIR=/etc/haproxy/conf.d diff --git a/rpc_deployment/roles/haproxy_common/files/haproxy.sh b/rpc_deployment/roles/haproxy_common/files/haproxy.sh new file mode 100644 index 0000000000..02fa88892f --- /dev/null +++ b/rpc_deployment/roles/haproxy_common/files/haproxy.sh @@ -0,0 +1,172 @@ +#!/bin/sh +### BEGIN INIT INFO +# Provides: haproxy +# Required-Start: $local_fs $network $remote_fs +# Required-Stop: $local_fs $remote_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: fast and reliable load balancing reverse proxy +# Description: This file should be used to start and stop haproxy. +### END INIT INFO + +# Author: Arnaud Cornet + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +PIDFILE=/var/run/haproxy.pid +CONFIG=/etc/haproxy/haproxy.cfg +HAPROXY=/usr/sbin/haproxy +EXTRAOPTS= +ENABLED=0 + +test -x $HAPROXY || exit 0 + +if [ -e /etc/default/haproxy ]; then + . /etc/default/haproxy +fi + +test -f "$CONFIG" || exit 0 +test "$ENABLED" != "0" || exit 0 + +[ -f /etc/default/rcS ] && . /etc/default/rcS +. /lib/lsb/init-functions + +CONFIG_DIR_FILES="" +if [ ! -z "$CONFIG_DIR" ] +then + for file in $CONFIG_DIR/*; do + CONFIG_DIR_FILES="$CONFIG_DIR_FILES -f $file" + done +fi + +haproxy_start() +{ + start-stop-daemon --start --pidfile "$PIDFILE" \ + --exec $HAPROXY -- -f "$CONFIG" $CONFIG_DIR_FILES -D -p "$PIDFILE" \ + $EXTRAOPTS || return 2 + return 0 +} + +haproxy_stop() +{ + if [ ! -f $PIDFILE ] ; then + # This is a success according to LSB + return 0 + fi + for pid in $(cat $PIDFILE) ; do + /bin/kill $pid || return 4 + done + rm -f $PIDFILE + return 0 +} + +haproxy_reload() +{ + $HAPROXY -f "$CONFIG" $CONFIG_DIR_FILES -p $PIDFILE -D $EXTRAOPTS -sf $(cat $PIDFILE) \ + || return 2 + return 0 +} + +haproxy_status() +{ + if [ ! -f $PIDFILE ] ; then + # program not running + return 3 + fi + + for pid in $(cat $PIDFILE) ; do + if ! ps --no-headers p "$pid" | grep haproxy > /dev/null ; then + # program running, bogus pidfile + return 1 + fi + done + + return 0 +} + + +case "$1" in +start) + log_daemon_msg "Starting haproxy" "haproxy" + haproxy_start + ret=$? + case "$ret" in + 0) + log_end_msg 0 + ;; + 1) + log_end_msg 1 + echo "pid file '$PIDFILE' found, haproxy not started." + ;; + 2) + log_end_msg 1 + ;; + esac + exit $ret + ;; +stop) + log_daemon_msg "Stopping haproxy" "haproxy" + haproxy_stop + ret=$? + case "$ret" in + 0|1) + log_end_msg 0 + ;; + 2) + log_end_msg 1 + ;; + esac + exit $ret + ;; +reload|force-reload) + log_daemon_msg "Reloading haproxy" "haproxy" + haproxy_reload + ret=$? + case "$ret" in + 0|1) + log_end_msg 0 + ;; + 2) + log_end_msg 1 + ;; + esac + exit $ret + ;; +restart) + log_daemon_msg "Restarting haproxy" "haproxy" + haproxy_stop + haproxy_start + ret=$? + case "$ret" in + 0) + log_end_msg 0 + ;; + 1) + log_end_msg 1 + ;; + 2) + log_end_msg 1 + ;; + esac + exit $ret + ;; +status) + haproxy_status + ret=$? + case "$ret" in + 0) + echo "haproxy is running." + ;; + 1) + echo "haproxy dead, but $PIDFILE exists." + ;; + *) + echo "haproxy not running." + ;; + esac + exit $ret + ;; +*) + echo "Usage: /etc/init.d/haproxy {start|stop|reload|restart|status}" + exit 2 + ;; +esac diff --git a/rpc_deployment/roles/haproxy_common/handlers/main.yml b/rpc_deployment/roles/haproxy_common/handlers/main.yml new file mode 100644 index 0000000000..b51a0b5ff2 --- /dev/null +++ b/rpc_deployment/roles/haproxy_common/handlers/main.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Restart haproxy + service: name=haproxy state=restarted pattern=haproxy enabled=yes diff --git a/rpc_deployment/roles/haproxy_common/tasks/main.yml b/rpc_deployment/roles/haproxy_common/tasks/main.yml new file mode 100644 index 0000000000..fd7c10bba0 --- /dev/null +++ b/rpc_deployment/roles/haproxy_common/tasks/main.yml @@ -0,0 +1,50 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Install HAPRoxy Packages + apt: + pkg: "{{ item }}" + state: present + update_cache: yes + cache_valid_time: 600 + ignore_errors: yes + with_items: + - haproxy + - hatop + - vim-haproxy + +- name: Replace haproxy DEFAULT file + copy: + src: haproxy.default + dest: /etc/default/haproxy + +- name: Replace haproxy init script to allow conf.d + copy: + src: haproxy.sh + dest: /etc/init.d/haproxy + +- name: Create haproxy conf.d + file: + path: /etc/haproxy/conf.d + state: directory + recurse: yes + +- name: Drop base haproxy config + template: > + src={{ item }} + dest=/etc/haproxy/{{ item }} + with_items: + - haproxy.cfg + notify: Restart haproxy diff --git a/rpc_deployment/roles/haproxy_common/templates/haproxy.cfg b/rpc_deployment/roles/haproxy_common/templates/haproxy.cfg new file mode 100644 index 0000000000..6ebd1aae59 --- /dev/null +++ b/rpc_deployment/roles/haproxy_common/templates/haproxy.cfg @@ -0,0 +1,27 @@ +global + log 127.0.0.1 local0 + log 127.0.0.1 local1 notice + chroot /var/lib/haproxy + uid haproxy + gid haproxy + daemon + maxconn 4096 + tune.bufsize 384000 + stats socket /var/run/haproxy.stat mode 600 + +defaults + log global + option dontlognull + option redispatch + retries 3 + timeout client 50s + timeout connect 10s + timeout server 50s + maxconn 4096 + errorfile 400 /etc/haproxy/errors/400.http + errorfile 403 /etc/haproxy/errors/403.http + errorfile 408 /etc/haproxy/errors/408.http + errorfile 500 /etc/haproxy/errors/500.http + errorfile 502 /etc/haproxy/errors/502.http + errorfile 503 /etc/haproxy/errors/503.http + errorfile 504 /etc/haproxy/errors/504.http diff --git a/rpc_deployment/roles/haproxy_service/handlers/main.yml b/rpc_deployment/roles/haproxy_service/handlers/main.yml new file mode 100644 index 0000000000..b51a0b5ff2 --- /dev/null +++ b/rpc_deployment/roles/haproxy_service/handlers/main.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Restart haproxy + service: name=haproxy state=restarted pattern=haproxy enabled=yes diff --git a/rpc_deployment/roles/haproxy_service/tasks/main.yml b/rpc_deployment/roles/haproxy_service/tasks/main.yml new file mode 100644 index 0000000000..8ae7bd3b84 --- /dev/null +++ b/rpc_deployment/roles/haproxy_service/tasks/main.yml @@ -0,0 +1,21 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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 haproxy service config files" + template: + src: service + dest: "/etc/haproxy/conf.d/{{ item.service.hap_service_name }}" + with_items: haproxy_config + notify: Restart haproxy diff --git a/rpc_deployment/roles/haproxy_service/templates/service b/rpc_deployment/roles/haproxy_service/templates/service new file mode 100644 index 0000000000..3a50f1e457 --- /dev/null +++ b/rpc_deployment/roles/haproxy_service/templates/service @@ -0,0 +1,42 @@ +frontend {{ item.service.hap_service_name }}-front +bind {{ item.service.hap_bind|default('*') }}:{{ item.service.hap_port }} +{% if item.service.hap_balance_type == "http" %} + option httplog + option forwardfor except 127.0.0.0/8 + option http-server-close + + {% set request_option = "http" %} +{% else %} + option tcplog + {% set request_option = "tcp" %} +{% endif %} + +{% if item.service.hap_whitelist_hosts is defined and item.service.hap_whitelist_hosts == true %} + acl white_list src 127.0.0.1/8 {{ container_cidr }} {% for host_name in groups['hosts'] %} {{ hostvars[host_name]['ansible_ssh_host'] }} {% endfor %} + + {{ request_option }}-request content accept if white_list + {{ request_option }}-request content reject +{% endif %} + + mode {{ item.service.hap_balance_type }} + default_backend {{ item.service.hap_service_name }}-back + + +{% if item.service.hap_backend_port is not defined %} + {% set hap_backend_port = item.service.hap_port %} +{% else %} + {% set hap_backend_port = item.service.hap_backend_port %} +{% endif %} + +backend {{ item.service.hap_service_name }}-back + mode {{ item.service.hap_balance_type }} + balance {{ item.service.hap_balance_alg|default("leastconn") }} +{% for option in item.service.hap_backend_options|default([]) %} + option {{ option }} +{% endfor %} +{% for host_name in item.service.hap_backend_nodes %} + server {{ hostvars[host_name]['container_name']|default(host_name) }} {{ hostvars[host_name]['ansible_ssh_host'] }}:{{ hap_backend_port }} check port {{ hap_backend_port }} inter {{ hap_interval }} rise {{ item.service.hap_backend_nodes|count }} fall {{ item.service.hap_backend_nodes|count }} +{% endfor %} +{% for host_name in item.service.hap_backup_nodes|default([]) %} + server {{ hostvars[host_name]['container_name']|default(host_name) }} {{ hostvars[host_name]['ansible_ssh_host'] }}:{{ hap_backend_port }} check port {{ hap_backend_port }} inter {{ hap_interval }} rise {{ item.service.hap_backend_nodes|count }} fall {{ item.service.hap_backend_nodes|count }} backup +{% endfor %} diff --git a/rpc_deployment/roles/heat_common/tasks/heat_config.yml b/rpc_deployment/roles/heat_common/tasks/heat_config.yml new file mode 100644 index 0000000000..2adb2f9dd8 --- /dev/null +++ b/rpc_deployment/roles/heat_common/tasks/heat_config.yml @@ -0,0 +1,42 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Ensure Heat Domain User + keystone: > + command=ensure_user + token="{{ auth_admin_token }}" + endpoint="{{ auth_admin_uri }}" + user_name="{{ stack_domain_admin }}" + tenant_name=admin + password="{{ stack_domain_admin_password }}" + +- name: set fact for heat domain admin id + set_fact: + stack_user_domain: "{{ keystone_facts['id'] }}" + +- name: Setup Heat Config + template: > + src={{ item }} + dest=/etc/heat/{{ item }} + owner={{ system_user }} + group={{ system_group }} + with_items: + - heat.conf + - environment.d/default.yaml + - templates/AWS_CloudWatch_Alarm.yaml + - templates/AWS_RDS_DBInstance.yaml + - api-paste.ini + - policy.json + notify: Restart os service diff --git a/rpc_deployment/roles/heat_common/tasks/main.yml b/rpc_deployment/roles/heat_common/tasks/main.yml new file mode 100644 index 0000000000..60306c3490 --- /dev/null +++ b/rpc_deployment/roles/heat_common/tasks/main.yml @@ -0,0 +1,16 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: heat_config.yml diff --git a/rpc_deployment/roles/heat_common/templates/api-paste.ini b/rpc_deployment/roles/heat_common/templates/api-paste.ini new file mode 100644 index 0000000000..31a49e9744 --- /dev/null +++ b/rpc_deployment/roles/heat_common/templates/api-paste.ini @@ -0,0 +1,94 @@ +# heat-api pipeline +[pipeline:heat-api] +pipeline = faultwrap ssl versionnegotiation authurl authtoken context apiv1app + +# heat-api pipeline for standalone heat +# ie. uses alternative auth backend that authenticates users against keystone +# using username and password instead of validating token (which requires +# an admin/service token). +# To enable, in heat.conf: +# [paste_deploy] +# flavor = standalone +# +[pipeline:heat-api-standalone] +pipeline = faultwrap ssl versionnegotiation authurl authpassword context apiv1app + +# heat-api pipeline for custom cloud backends +# i.e. in heat.conf: +# [paste_deploy] +# flavor = custombackend +# +[pipeline:heat-api-custombackend] +pipeline = faultwrap versionnegotiation context custombackendauth apiv1app + +# heat-api-cfn pipeline +[pipeline:heat-api-cfn] +pipeline = cfnversionnegotiation ec2authtoken authtoken context apicfnv1app + +# heat-api-cfn pipeline for standalone heat +# relies exclusively on authenticating with ec2 signed requests +[pipeline:heat-api-cfn-standalone] +pipeline = cfnversionnegotiation ec2authtoken context apicfnv1app + +# heat-api-cloudwatch pipeline +[pipeline:heat-api-cloudwatch] +pipeline = versionnegotiation ec2authtoken authtoken context apicwapp + +# heat-api-cloudwatch pipeline for standalone heat +# relies exclusively on authenticating with ec2 signed requests +[pipeline:heat-api-cloudwatch-standalone] +pipeline = versionnegotiation ec2authtoken context apicwapp + +[app:apiv1app] +paste.app_factory = heat.common.wsgi:app_factory +heat.app_factory = heat.api.openstack.v1:API + +[app:apicfnv1app] +paste.app_factory = heat.common.wsgi:app_factory +heat.app_factory = heat.api.cfn.v1:API + +[app:apicwapp] +paste.app_factory = heat.common.wsgi:app_factory +heat.app_factory = heat.api.cloudwatch:API + +[filter:versionnegotiation] +paste.filter_factory = heat.common.wsgi:filter_factory +heat.filter_factory = heat.api.openstack:version_negotiation_filter + +[filter:faultwrap] +paste.filter_factory = heat.common.wsgi:filter_factory +heat.filter_factory = heat.api.openstack:faultwrap_filter + +[filter:cfnversionnegotiation] +paste.filter_factory = heat.common.wsgi:filter_factory +heat.filter_factory = heat.api.cfn:version_negotiation_filter + +[filter:cwversionnegotiation] +paste.filter_factory = heat.common.wsgi:filter_factory +heat.filter_factory = heat.api.cloudwatch:version_negotiation_filter + +[filter:context] +paste.filter_factory = heat.common.context:ContextMiddleware_filter_factory + +[filter:ec2authtoken] +paste.filter_factory = heat.api.aws.ec2token:EC2Token_filter_factory + +[filter:ssl] +paste.filter_factory = heat.common.wsgi:filter_factory +heat.filter_factory = heat.api.openstack:sslmiddleware_filter + +# Middleware to set auth_url header appropriately +[filter:authurl] +paste.filter_factory = heat.common.auth_url:filter_factory + +# Auth middleware that validates token against keystone +[filter:authtoken] +paste.filter_factory = keystonemiddleware.auth_token:filter_factory + +# Auth middleware that validates username/password against keystone +[filter:authpassword] +paste.filter_factory = heat.common.auth_password:filter_factory + +# Auth middleware that validates against custom backend +[filter:custombackendauth] +paste.filter_factory = heat.common.custom_backend_auth:filter_factory diff --git a/rpc_deployment/roles/heat_common/templates/environment.d/default.yaml b/rpc_deployment/roles/heat_common/templates/environment.d/default.yaml new file mode 100644 index 0000000000..388f37af82 --- /dev/null +++ b/rpc_deployment/roles/heat_common/templates/environment.d/default.yaml @@ -0,0 +1,8 @@ +resource_registry: + # allow older templates with Quantum in them. + "OS::Quantum*": "OS::Neutron*" + # Choose your implementation of AWS::CloudWatch::Alarm + #"AWS::CloudWatch::Alarm": "file:///etc/heat/templates/AWS_CloudWatch_Alarm.yaml" + "AWS::CloudWatch::Alarm": "OS::Heat::CWLiteAlarm" + "OS::Metering::Alarm": "OS::Ceilometer::Alarm" + "AWS::RDS::DBInstance": "file:///etc/heat/templates/AWS_RDS_DBInstance.yaml" diff --git a/rpc_deployment/roles/heat_common/templates/heat.conf b/rpc_deployment/roles/heat_common/templates/heat.conf new file mode 100644 index 0000000000..8966f4d771 --- /dev/null +++ b/rpc_deployment/roles/heat_common/templates/heat.conf @@ -0,0 +1,73 @@ +[DEFAULT] +verbose = True +debug = False +use_syslog = False + +log_file = /var/log/heat/heat.log + +stack_domain_admin_password = {{ stack_domain_admin_password }} +stack_domain_admin = {{ stack_domain_admin }} +stack_user_domain = {{ stack_user_domain }} +deferred_auth_method = {{ deferred_auth_method }} + +auth_encryption_key = {{ auth_encryption_key }} + +heat_watch_server_url = {{ heat_watch_server_url }} +heat_waitcondition_server_url = {{ heat_waitcondition_server_url }} +heat_metadata_server_url = {{ heat_metadata_server_url }} + + +## RPC Backend +rpc_backend = {{ rpc_backend }} +rpc_thread_pool_size = {{ rpc_thread_pool_size }} +rpc_conn_pool_size = {{ rpc_conn_pool_size }} +rpc_response_timeout = {{ rpc_response_timeout }} +rpc_cast_timeout = {{ rpc_cast_timeout }} + + +## RabbitMQ + +rabbit_hosts = {{ rabbit_hosts }} + +rabbit_port = {{ rabbit_port }} +rabbit_use_ssl = {{ rabbit_use_ssl }} +rabbit_userid = {{ rabbit_userid }} +rabbit_password = {{ rabbit_password }} +rabbit_virtual_host = {{ rabbit_virtual_host }} + +[clients] +endpoint_type = internalURL + +[database] +connection = mysql://{{ container_mysql_user }}:{{ container_mysql_password }}@{{ mysql_address }}/{{ container_database }}?charset=utf8 + +[ec2authtoken] +auth_uri = {{ auth_identity_uri }} + +[heat_api] +bind_port = 8004 + +[heat_api_cfn] +bind_port = 8000 + +[heat_api_cloudwatch] +bind_port = 8003 + +[keystone_authtoken] +signing_dir = /var/cache/heat +identity_uri = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }} +auth_uri = {{ auth_identity_uri }} +admin_tenant_name = {{ service_admin_tenant_name }} +admin_user = {{ service_admin_username }} +admin_password = {{ service_admin_password }} + +memcached_servers = {{ internal_vip_address }}:{{ memcached_port }} +token_cache_time = 300 +revocation_cache_time = 60 + +# if your memcached server is shared, use these settings to avoid cache poisoning +memcache_security_strategy = ENCRYPT +memcache_secret_key = {{ memcached_secret_key }} + +# if your keystone deployment uses PKI, and you value security over performance: +check_revocations_for_cached = {{ hostvars[groups['keystone_all'][0]]['keystone_use_pki'] }} diff --git a/rpc_deployment/roles/heat_common/templates/policy.json b/rpc_deployment/roles/heat_common/templates/policy.json new file mode 100644 index 0000000000..e3e8822b18 --- /dev/null +++ b/rpc_deployment/roles/heat_common/templates/policy.json @@ -0,0 +1,64 @@ +{ + "context_is_admin": "role:admin", + "deny_stack_user": "not role:heat_stack_user", + "deny_everybody": "!", + + "cloudformation:ListStacks": "rule:deny_stack_user", + "cloudformation:CreateStack": "rule:deny_stack_user", + "cloudformation:DescribeStacks": "rule:deny_stack_user", + "cloudformation:DeleteStack": "rule:deny_stack_user", + "cloudformation:UpdateStack": "rule:deny_stack_user", + "cloudformation:DescribeStackEvents": "rule:deny_stack_user", + "cloudformation:ValidateTemplate": "rule:deny_stack_user", + "cloudformation:GetTemplate": "rule:deny_stack_user", + "cloudformation:EstimateTemplateCost": "rule:deny_stack_user", + "cloudformation:DescribeStackResource": "", + "cloudformation:DescribeStackResources": "rule:deny_stack_user", + "cloudformation:ListStackResources": "rule:deny_stack_user", + + "cloudwatch:DeleteAlarms": "rule:deny_stack_user", + "cloudwatch:DescribeAlarmHistory": "rule:deny_stack_user", + "cloudwatch:DescribeAlarms": "rule:deny_stack_user", + "cloudwatch:DescribeAlarmsForMetric": "rule:deny_stack_user", + "cloudwatch:DisableAlarmActions": "rule:deny_stack_user", + "cloudwatch:EnableAlarmActions": "rule:deny_stack_user", + "cloudwatch:GetMetricStatistics": "rule:deny_stack_user", + "cloudwatch:ListMetrics": "rule:deny_stack_user", + "cloudwatch:PutMetricAlarm": "rule:deny_stack_user", + "cloudwatch:PutMetricData": "", + "cloudwatch:SetAlarmState": "rule:deny_stack_user", + + "actions:action": "rule:deny_stack_user", + "build_info:build_info": "rule:deny_stack_user", + "events:index": "rule:deny_stack_user", + "events:show": "rule:deny_stack_user", + "resource:index": "rule:deny_stack_user", + "resource:metadata": "", + "resource:signal": "", + "resource:show": "rule:deny_stack_user", + "stacks:abandon": "rule:deny_stack_user", + "stacks:create": "rule:deny_stack_user", + "stacks:delete": "rule:deny_stack_user", + "stacks:detail": "rule:deny_stack_user", + "stacks:generate_template": "rule:deny_stack_user", + "stacks:global_index": "rule:deny_everybody", + "stacks:index": "rule:deny_stack_user", + "stacks:list_resource_types": "rule:deny_stack_user", + "stacks:lookup": "", + "stacks:preview": "rule:deny_stack_user", + "stacks:resource_schema": "rule:deny_stack_user", + "stacks:show": "rule:deny_stack_user", + "stacks:template": "rule:deny_stack_user", + "stacks:update": "rule:deny_stack_user", + "stacks:validate_template": "rule:deny_stack_user", + + "software_configs:create": "rule:deny_stack_user", + "software_configs:show": "rule:deny_stack_user", + "software_configs:delete": "rule:deny_stack_user", + "software_deployments:index": "rule:deny_stack_user", + "software_deployments:create": "rule:deny_stack_user", + "software_deployments:show": "rule:deny_stack_user", + "software_deployments:update": "rule:deny_stack_user", + "software_deployments:delete": "rule:deny_stack_user", + "software_deployments:metadata": "" +} diff --git a/rpc_deployment/roles/heat_common/templates/templates/AWS_CloudWatch_Alarm.yaml b/rpc_deployment/roles/heat_common/templates/templates/AWS_CloudWatch_Alarm.yaml new file mode 100644 index 0000000000..e21e500d69 --- /dev/null +++ b/rpc_deployment/roles/heat_common/templates/templates/AWS_CloudWatch_Alarm.yaml @@ -0,0 +1,86 @@ +HeatTemplateFormatVersion: '2012-12-12' +Description: AWS::CloudWatch::Alarm using Ceilometer. +Parameters: + AlarmDescription: + Type: String + Default: An alarm + EvaluationPeriods: + Type: String + MetricName: + Type: String + Namespace: + Type: String + Default: system/linux + Period: + Type: String + ComparisonOperator: + Type: String + AllowedValues: [GreaterThanOrEqualToThreshold, GreaterThanThreshold, + LessThanThreshold, LessThanOrEqualToThreshold] + Statistic: + Type: String + AllowedValues: [SampleCount, Average, Sum, Minimum, Maximum] + Threshold: + Type: String + Units: + Type: String + AllowedValues: [Seconds, Microseconds, Milliseconds, Bytes, Kilobytes, + Megabytes, Gigabytes, Terabytes, Bits, Kilobits, Megabits, + Gigabits, Terabits, Percent, Count, Bytes/Second, + Kilobytes/Second, Megabytes/Second, Gigabytes/Second, + Terabytes/Second, Bits/Second, Kilobits/Second, + Megabits/Second, Gigabits/Second, Terabits/Second, + Count/Second, None] + Default: None + AlarmActions: + Type: CommaDelimitedList + Default: '' + OKActions: + Type: CommaDelimitedList + Default: '' + InsufficientDataActions: + Type: CommaDelimitedList + Default: '' + Dimensions: + Type: CommaDelimitedList + +Mappings: + ComparisonOperatorMap: + LessThanOrEqualToThreshold: {Ceilometer: le} + LessThanThreshold: {Ceilometer: lt} + GreaterThanThreshold: {Ceilometer: gt} + GreaterThanOrEqualToThreshold: {Ceilometer: ge} + StatisticMap: + SampleCount: {Ceilometer: count} + Average: {Ceilometer: avg} + Sum: {Ceilometer: sum} + Minimum: {Ceilometer: min} + Maximum: {Ceilometer: max} + +Resources: + __alarm__: + Type: OS::Ceilometer::Alarm + Properties: + description: + Ref: AlarmDescription + meter_name: + Ref: MetricName + period: + Ref: Period + evaluation_periods: + Ref: EvaluationPeriods + repeat_actions: true + threshold: + Ref: Threshold + alarm_actions: + Ref: AlarmActions + ok_actions: + Ref: OKActions + insufficient_data_actions: + Ref: InsufficientDataActions + statistic: + "Fn::FindInMap": [StatisticMap, {Ref: Statistic}, Ceilometer] + comparison_operator: + "Fn::FindInMap": [ComparisonOperatorMap, {Ref: ComparisonOperator}, Ceilometer] + matching_metadata: + "Fn::MemberListToMap": [Name, Value, {Ref: Dimensions}] diff --git a/rpc_deployment/roles/heat_common/templates/templates/AWS_RDS_DBInstance.yaml b/rpc_deployment/roles/heat_common/templates/templates/AWS_RDS_DBInstance.yaml new file mode 100644 index 0000000000..30173442e6 --- /dev/null +++ b/rpc_deployment/roles/heat_common/templates/templates/AWS_RDS_DBInstance.yaml @@ -0,0 +1,127 @@ +HeatTemplateFormatVersion: '2012-12-12' +Description: 'Builtin AWS::RDS::DBInstance' +Parameters: + AllocatedStorage: + Type: String + DBInstanceClass: + Type: String + DBName: + Type: String + DBSecurityGroups: + Type: CommaDelimitedList + Default: '' + Engine: + Type: String + AllowedValues: ['MySQL'] + MasterUsername: + Type: String + MasterUserPassword: + Type: String + Port: + Type: String + Default: '3306' + KeyName: + Type: String + Default: '' + +Mappings: + DBInstanceToInstance: + db.m1.small: {Instance: m1.small} + db.m1.large: {Instance: m1.large} + db.m1.xlarge: {Instance: m1.xlarge} + db.m2.xlarge: {Instance: m2.xlarge} + db.m2.2xlarge: {Instance: m2.2xlarge} + db.m2.4xlarge: {Instance: m2.4xlarge} + +Resources: + ServerSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupDescription: 'Enable SSH access' + SecurityGroupIngress: + - IpProtocol: icmp + FromPort: '-1' + ToPort: '-1' + CidrIp: '0.0.0.0/0' + - IpProtocol: tcp + FromPort: '22' + ToPort : '22' + CidrIp : '0.0.0.0/0' + - IpProtocol: tcp + FromPort: {Ref: Port} + ToPort : {Ref: Port} + CidrIp : '0.0.0.0/0' + DatabaseInstance: + Type: AWS::EC2::Instance + Metadata: + AWS::CloudFormation::Init: + config: + files: + /tmp/db_setup.sql: + content: + 'Fn::Replace': + - DBName: {Ref: DBName} + MasterUserPassword: {Ref: MasterUserPassword} + MasterUsername: {Ref: MasterUsername} + - | + CREATE DATABASE DBName; + GRANT ALL PRIVILEGES ON DBName.* TO "MasterUsername"@"%" + IDENTIFIED BY "MasterUserPassword"; + FLUSH PRIVILEGES; + EXIT + mode: '000644' + owner: root + group: root + packages: + yum: + mariadb: [] + mariadb-server: [] + services: + systemd: + mysqld: + enabled: true + ensureRunning: true + Properties: + ImageId: F19-x86_64-cfntools + InstanceType: {'Fn::FindInMap': [DBInstanceToInstance, + {Ref: DBInstanceClass}, Instance]} + KeyName: {Ref: KeyName} + SecurityGroups: [{"Ref" : "ServerSecurityGroup"}] + UserData: + Fn::Base64: + Fn::Replace: + - 'AWS::StackName': {Ref: 'AWS::StackName'} + 'AWS::Region': {Ref: 'AWS::Region'} + MasterUserPassword: {Ref: MasterUserPassword} + WaitHandle: {Ref: WaitHandle} + - | + #!/bin/bash -v + # + iptables -F + + # Helper function + function error_exit + { + /opt/aws/bin/cfn-signal -e 1 -r \"$1\" 'WaitHandle' + exit 1 + } + /opt/aws/bin/cfn-init -s AWS::StackName -r DatabaseInstance --region AWS::Region || error_exit 'Failed to run cfn-init' + # Setup MySQL root password and create a user + mysqladmin -u root password 'MasterUserPassword' + mysql -u root --password='MasterUserPassword' < /tmp/db_setup.sql || error_exit 'Failed to setup mysql' + + # Database setup completed, signal success + /opt/aws/bin/cfn-signal -e 0 -r "MySQL server setup complete" 'WaitHandle' + + WaitHandle: + Type: AWS::CloudFormation::WaitConditionHandle + WaitCondition: + Type: AWS::CloudFormation::WaitCondition + DependsOn: DatabaseInstance + Properties: + Handle: {Ref: WaitHandle} + Timeout: "600" + +Outputs: + Endpoint.Address: {'Fn::GetAtt': [DatabaseInstance, PublicIp]} + Endpoint.Port: {Ref: Port} diff --git a/rpc_deployment/roles/heat_domain_user/tasks/main.yml b/rpc_deployment/roles/heat_domain_user/tasks/main.yml new file mode 100644 index 0000000000..d74671eeea --- /dev/null +++ b/rpc_deployment/roles/heat_domain_user/tasks/main.yml @@ -0,0 +1,43 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Ensure heat domain user + keystone: > + command=ensure_user + token="{{ auth_admin_token }}" + endpoint="{{ auth_admin_uri }}" + user_name="{{ stack_domain_admin }}" + tenant_name=admin + password="{{ stack_domain_admin_password }}" + +- name: Ensure stack_owner role + keystone: > + command=ensure_role + login_tenant_name="{{ auth_admin_tenant }}" + login_user="{{ auth_admin_username }}" + login_password="{{ auth_admin_password }}" + endpoint="{{ auth_admin_uri }}" + role_name="heat_stack_owner" + +- name: Ensure admin has stack_owner role + keystone: > + command=ensure_user_role + login_tenant_name="{{ auth_admin_tenant }}" + login_user="{{ auth_admin_username }}" + login_password="{{ auth_admin_password }}" + endpoint="{{ auth_admin_uri }}" + user_name="admin" + tenant_name="admin" + role_name="heat_stack_owner" diff --git a/rpc_deployment/roles/heat_setup/tasks/main.yml b/rpc_deployment/roles/heat_setup/tasks/main.yml new file mode 100644 index 0000000000..6e92b1c163 --- /dev/null +++ b/rpc_deployment/roles/heat_setup/tasks/main.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Perform a Heat DB sync + command: heat-manage db_sync diff --git a/rpc_deployment/roles/horizon_apache/tasks/main.yml b/rpc_deployment/roles/horizon_apache/tasks/main.yml new file mode 100644 index 0000000000..e882c3d03a --- /dev/null +++ b/rpc_deployment/roles/horizon_apache/tasks/main.yml @@ -0,0 +1,56 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Drop apache2 ports file + template: > + src=horizon-ports.conf + dest=/etc/apache2/ports.conf + owner="root" + group="root" + +- name: Drop Horizon config + template: > + src=openstack-dashboard.conf + dest=/etc/apache2/sites-available + owner={{ system_user }} + group={{ system_group }} + +- name: Enable Horizon Site + file: > + src=/etc/apache2/sites-available/{{ item.name }} + dest=/etc/apache2/sites-enabled/{{ item.name }} + state={{ item.state }} + with_items: + - { state: link, name: openstack-dashboard.conf } + - { state: absent, name: 000-default.conf } + +- name: Enable apache2 modules + apache2_module: > + state={{ item.state }} + name={{ item.name }} + with_items: + - { state: present, name: wsgi } + - { state: present, name: ssl } + - { state: absent, name: mpm_event } + - { state: present, name: mpm_worker } + - { state: present, name: rewrite } + +- name: Ensure Apache ServerName + lineinfile: > + dest=/etc/apache2/apache2.conf + line="ServerName {{ container_name }}" + +- name: Ensure Apache is running + service: name=apache2 state=restarted diff --git a/rpc_deployment/roles/horizon_apache/templates/horizon-ports.conf b/rpc_deployment/roles/horizon_apache/templates/horizon-ports.conf new file mode 100644 index 0000000000..24c3bb2555 --- /dev/null +++ b/rpc_deployment/roles/horizon_apache/templates/horizon-ports.conf @@ -0,0 +1,2 @@ +Listen 80 +Listen 443 diff --git a/rpc_deployment/roles/horizon_apache/templates/openstack-dashboard.conf b/rpc_deployment/roles/horizon_apache/templates/openstack-dashboard.conf new file mode 100644 index 0000000000..8d9f7ac21d --- /dev/null +++ b/rpc_deployment/roles/horizon_apache/templates/openstack-dashboard.conf @@ -0,0 +1,35 @@ + + ServerName {{ horizon_server_name }} + RewriteEngine On + RewriteCond %{HTTPS} !=on + RewriteRule ^/?(.*) https://%{HTTP_HOST}/$1 [R,L] + + + + ServerName {{ horizon_server_name }} + + LogLevel {{ horizon_log_level|default('info') }} + ErrorLog /var/log/apache2/horizon-error.log + CustomLog /var/log/apache2/ssl_access.log combined + Options +FollowSymLinks + + SSLEngine on + SSLCertificateFile {{ horizon_ssl_cert|default('/etc/ssl/certs/apache.cert') }} + SSLCertificateKeyFile {{ horizon_ssl_key|default('/etc/ssl/private/apache.key') }} + SSLCACertificatePath {{ horizon_ssl_cert_path|default('/etc/ssl/certs') }} + SSLCARevocationPath {{ horizon_ssl_cert_path|default('/etc/ssl/certs') }} + SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown + + WSGIScriptAlias / {{ install_lib_dir }}/openstack_dashboard/wsgi/django.wsgi + WSGIDaemonProcess horizon user={{ system_user }} group={{ system_group }} processes=3 threads=10 + + Alias /static {{ install_lib_dir }}/openstack_dashboard/static/ + + + Options Indexes FollowSymLinks MultiViews + AllowOverride None + Order allow,deny + allow from all + Require all granted + + diff --git a/rpc_deployment/roles/horizon_common/tasks/main.yml b/rpc_deployment/roles/horizon_common/tasks/main.yml new file mode 100644 index 0000000000..1a70a8968c --- /dev/null +++ b/rpc_deployment/roles/horizon_common/tasks/main.yml @@ -0,0 +1,65 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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 self-signed SSL cert + command: > + openssl req -new -nodes -x509 -subj + "/C=US/ST=Texas/L=San Antonio/O=IT/CN={{ horizon_server_name }}" + -days 3650 + -keyout /etc/ssl/private/apache.key + -out /etc/ssl/certs/apache.cert + -extensions v3_ca + creates=/etc/ssl/certs/apache.cert + when: horizon_self_signed is defined and horizon_self_signed == true + +- name: Setup Horizon config + template: > + src=local_settings.py + dest={{ install_lib_dir }}/openstack_dashboard/local/local_settings.py + owner={{ system_user }} + group={{ system_group }} + +- name: Copy manage.py + command: > + creates={{ install_lib_dir }}/manage.py + cp -a "/opt/{{ service_name }}_{{ git_install_branch | replace('/', '_') }}/manage.py" "{{ install_lib_dir }}" + +- name: Collect static files + command: python /opt/horizon/lib/python2.7/site-packages/manage.py collectstatic --noinput + + +- name: Fix missing file issues (1 of 2) + file: > + src={{ install_lib_dir }}/horizon/static/bootstrap/js + dest={{ install_lib_dir }}/openstack_dashboard/static/bootstrap/js + owner={{ system_group }} + group={{ system_group }} + state=link + +- name: Fix missing file issues (2 of 2) + file: > + src={{ install_lib_dir }}/horizon/static/horizon + dest={{ install_lib_dir }}/openstack_dashboard/static/horizon + owner={{ system_group }} + group={{ system_group }} + state=link + +- name: Set horizon permissions + file: > + state=directory + dest={{ install_root_dir }} + recurse=yes + owner={{ system_group }} + group={{ system_group }} diff --git a/rpc_deployment/roles/horizon_common/templates/local_settings.py b/rpc_deployment/roles/horizon_common/templates/local_settings.py new file mode 100644 index 0000000000..79fe645bd6 --- /dev/null +++ b/rpc_deployment/roles/horizon_common/templates/local_settings.py @@ -0,0 +1,502 @@ +import os +from django.utils.translation import ugettext_lazy as _ +from openstack_dashboard import exceptions + +DEBUG = False +TEMPLATE_DEBUG = DEBUG +COMPRESS_ENABLED = True +COMPRESS_ROOT = '{{ install_lib_dir }}/openstack_dashboard/static' + +# Required for Django 1.5. +# If horizon is running in production (DEBUG is False), set this +# with the list of host/domain names that the application can serve. +# For more information see: +# https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts +ALLOWED_HOSTS = ['*'] + +# Set SSL proxy settings: +# For Django 1.4+ pass this header from the proxy after terminating the SSL, +# and don't forget to strip it from the client's request. +# For more information see: +# https://docs.djangoproject.com/en/1.4/ref/settings/#secure-proxy-ssl-header +# SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTOCOL', 'https') + +# If Horizon is being served through SSL, then uncomment the following two +# settings to better secure the cookies from security exploits +CSRF_COOKIE_SECURE = True +SESSION_COOKIE_SECURE = True + +# Overrides for OpenStack API versions. Use this setting to force the +# OpenStack dashboard to use a specific API version for a given service API. +# NOTE: The version should be formatted as it appears in the URL for the +# service API. For example, The identity service APIs have inconsistent +# use of the decimal point, so valid options would be "2.0" or "3". +# OPENSTACK_API_VERSIONS = { +# "identity": 3, +# "volume": 2 +# } + +# Set this to True if running on multi-domain model. When this is enabled, it +# will require user to enter the Domain name in addition to username for login. +# OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = False + +# Overrides the default domain used when running on single-domain model +# with Keystone V3. All entities will be created in the default domain. +# OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = 'Default' + +# Set Console type: +# valid options would be "AUTO", "VNC", "SPICE" or "RDP" +# CONSOLE_TYPE = "AUTO" + +# Default OpenStack Dashboard configuration. +HORIZON_CONFIG = { + 'dashboards': ('project', 'admin', 'settings',), + 'default_dashboard': 'project', + 'user_home': 'openstack_dashboard.views.get_user_home', + 'ajax_queue_limit': 10, + 'auto_fade_alerts': { + 'delay': 3000, + 'fade_duration': 1500, + 'types': ['alert-success', 'alert-info'] + }, + 'help_url': "http://docs.openstack.org", + 'exceptions': { + 'recoverable': exceptions.RECOVERABLE, + 'not_found': exceptions.NOT_FOUND, + 'unauthorized': exceptions.UNAUTHORIZED}, +} + +# Specify a regular expression to validate user passwords. +# HORIZON_CONFIG["password_validator"] = { +# "regex": '.*', +# "help_text": _("Your password does not meet the requirements.") +# } + +# Disable simplified floating IP address management for deployments with +# multiple floating IP pools or complex network requirements. +# HORIZON_CONFIG["simple_ip_management"] = False + +# Turn off browser autocompletion for the login form if so desired. +# HORIZON_CONFIG["password_autocomplete"] = "off" + +LOCAL_PATH = os.path.dirname(os.path.abspath(__file__)) + +# Set custom secret key: +# You can either set it to a specific value or you can let horizion generate a +# default secret key that is unique on this machine, e.i. regardless of the +# amount of Python WSGI workers (if used behind Apache+mod_wsgi): However, there +# may be situations where you would want to set this explicitly, e.g. when +# multiple dashboard instances are distributed on different machines (usually +# behind a load-balancer). Either you have to make sure that a session gets all +# requests routed to the same dashboard instance or you set the same SECRET_KEY +# for all of them. +from horizon.utils import secret_key +SECRET_KEY = secret_key.generate_or_read_from_file(os.path.join(LOCAL_PATH, '.secret_key_store')) + +# We recommend you use memcached for development; otherwise after every reload +# of the django development server, you will have to login again. To use +# memcached set CACHES to something like +CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', + 'LOCATION': '{{ internal_vip_address }}:{{ memcached_port }}', + } +} + +SESSION_ENGINE = "django.contrib.sessions.backends.cached_db" + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql', + 'HOST': '{{ mysql_address }}', + 'NAME': '{{ container_database }}', + 'USER': '{{ container_mysql_user }}', + 'PASSWORD': '{{ container_mysql_password }}', + 'default-character-set': 'utf8' + }, +} + +# Send email to the console by default +EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' +# Or send them to /dev/null +#EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend' + +# Configure these for your outgoing email host +# EMAIL_HOST = 'smtp.my-company.com' +# EMAIL_PORT = 25 +# EMAIL_HOST_USER = 'djangomail' +# EMAIL_HOST_PASSWORD = 'top-secret!' + +# For multiple regions uncomment this configuration, and add (endpoint, title). +# AVAILABLE_REGIONS = [ +# ('http://cluster1.example.com:5000/v2.0', 'cluster1'), +# ('http://cluster2.example.com:5000/v2.0', 'cluster2'), +# ] + +OPENSTACK_HOST = "{{ auth_host }}" +OPENSTACK_KEYSTONE_URL = "{{ auth_identity_uri }}" +OPENSTACK_KEYSTONE_DEFAULT_ROLE = "_member_" + +# Disable SSL certificate checks (useful for self-signed certificates): +{% if horizon_self_signed == true %} +OPENSTACK_SSL_NO_VERIFY = True +{% else %} +OPENSTACK_SSL_NO_VERIFY = False +OPENSTACK_SSL_CACERT = "{{ horizon_cacert_pem }}" +{% endif %} + +# The CA certificate to use to verify SSL connections +# OPENSTACK_SSL_CACERT = '/path/to/cacert.pem' + +# The OPENSTACK_KEYSTONE_BACKEND settings can be used to identify the +# capabilities of the auth backend for Keystone. +# If Keystone has been configured to use LDAP as the auth backend then set +# can_edit_user to False and name to 'ldap'. +# +# TODO(tres): Remove these once Keystone has an API to identify auth backend. +OPENSTACK_KEYSTONE_BACKEND = { + 'name': 'native', + 'can_edit_user': True, + 'can_edit_group': True, + 'can_edit_project': True, + 'can_edit_domain': True, + 'can_edit_role': True +} + +#Setting this to True, will add a new "Retrieve Password" action on instance, +#allowing Admin session password retrieval/decryption. +#OPENSTACK_ENABLE_PASSWORD_RETRIEVE = False + +# The Xen Hypervisor has the ability to set the mount point for volumes +# attached to instances (other Hypervisors currently do not). Setting +# can_set_mount_point to True will add the option to set the mount point +# from the UI. +OPENSTACK_HYPERVISOR_FEATURES = { + 'can_set_mount_point': False, + 'can_set_password': False, +} + +# The OPENSTACK_NEUTRON_NETWORK settings can be used to enable optional +# services provided by neutron. Options currently available are load +# balancer service, security groups, quotas, VPN service. +OPENSTACK_NEUTRON_NETWORK = { + 'enable_lb': False, + 'enable_firewall': False, + 'enable_quotas': True, + 'enable_vpn': False, + # The profile_support option is used to detect if an external router can be + # configured via the dashboard. When using specific plugins the + # profile_support can be turned on if needed. + 'profile_support': None, + #'profile_support': 'cisco', +} + +# The OPENSTACK_IMAGE_BACKEND settings can be used to customize features +# in the OpenStack Dashboard related to the Image service, such as the list +# of supported image formats. +OPENSTACK_IMAGE_BACKEND = { + 'image_formats': [ + ('', ''), + ('aki', _('AKI - Amazon Kernel Image')), + ('ami', _('AMI - Amazon Machine Image')), + ('ari', _('ARI - Amazon Ramdisk Image')), + ('iso', _('ISO - Optical Disk Image')), + ('qcow2', _('QCOW2 - QEMU Emulator')), + ('raw', _('Raw')), + ('vdi', _('VDI')), + ('vhd', _('VHD')), + ('vmdk', _('VMDK')) + ] +} + +# The IMAGE_CUSTOM_PROPERTY_TITLES settings is used to customize the titles for +# image custom property attributes that appear on image detail pages. +IMAGE_CUSTOM_PROPERTY_TITLES = { + "architecture": _("Architecture"), + "kernel_id": _("Kernel ID"), + "ramdisk_id": _("Ramdisk ID"), + "image_state": _("Euca2ools state"), + "project_id": _("Project ID"), + "image_type": _("Image Type") +} + +# OPENSTACK_ENDPOINT_TYPE specifies the endpoint type to use for the endpoints +# in the Keystone service catalog. Use this setting when Horizon is running +# external to the OpenStack environment. The default is 'publicURL'. +#OPENSTACK_ENDPOINT_TYPE = "publicURL" + +# SECONDARY_ENDPOINT_TYPE specifies the fallback endpoint type to use in the +# case that OPENSTACK_ENDPOINT_TYPE is not present in the endpoints +# in the Keystone service catalog. Use this setting when Horizon is running +# external to the OpenStack environment. The default is None. This +# value should differ from OPENSTACK_ENDPOINT_TYPE if used. +#SECONDARY_ENDPOINT_TYPE = "publicURL" + +# The number of objects (Swift containers/objects or images) to display +# on a single page before providing a paging element (a "more" link) +# to paginate results. +API_RESULT_LIMIT = 1000 +API_RESULT_PAGE_SIZE = 20 + +# The timezone of the server. This should correspond with the timezone +# of your entire OpenStack installation, and hopefully be in UTC. +TIME_ZONE = "UTC" + +# When launching an instance, the menu of available flavors is +# sorted by RAM usage, ascending. If you would like a different sort order, +# you can provide another flavor attribute as sorting key. Alternatively, you +# can provide a custom callback method to use for sorting. You can also provide +# a flag for reverse sort. For more info, see +# http://docs.python.org/2/library/functions.html#sorted +# CREATE_INSTANCE_FLAVOR_SORT = { +# 'key': 'name', +# # or +# 'key': my_awesome_callback_method, +# 'reverse': False, +# } + +# The Horizon Policy Enforcement engine uses these values to load per service +# policy rule files. The content of these files should match the files the +# OpenStack services are using to determine role based access control in the +# target installation. + +# Path to directory containing policy.json files +#POLICY_FILES_PATH = os.path.join(ROOT_PATH, "conf") +# Map of local copy of service policy files +#POLICY_FILES = { +# 'identity': 'keystone_policy.json', +# 'compute': 'nova_policy.json', +# 'volume': 'cinder_policy.json', +# 'image': 'glance_policy.json', +#} + +# Trove user and database extension support. By default support for +# creating users and databases on database instances is turned on. +# To disable these extensions set the permission here to something +# unusable such as ["!"]. +# TROVE_ADD_USER_PERMS = [] +# TROVE_ADD_DATABASE_PERMS = [] + +LOGGING = { + 'version': 1, + # When set to True this will disable all logging except + # for loggers specified in this configuration dictionary. Note that + # if nothing is specified here and disable_existing_loggers is True, + # django.db.backends will still log unless it is disabled explicitly. + 'disable_existing_loggers': False, + 'handlers': { + 'null': { + 'level': 'DEBUG', + 'class': 'django.utils.log.NullHandler', + }, + 'console': { + # Set the level to "DEBUG" for verbose output logging. + 'level': 'INFO', + 'class': 'logging.StreamHandler', + }, + }, + 'loggers': { + # Logging from django.db.backends is VERY verbose, send to null + # by default. + 'django.db.backends': { + 'handlers': ['null'], + 'propagate': False, + }, + 'requests': { + 'handlers': ['null'], + 'propagate': False, + }, + 'horizon': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': False, + }, + 'openstack_dashboard': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': False, + }, + 'novaclient': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': False, + }, + 'cinderclient': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': False, + }, + 'keystoneclient': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': False, + }, + 'glanceclient': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': False, + }, + 'neutronclient': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': False, + }, + 'heatclient': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': False, + }, + 'ceilometerclient': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': False, + }, + 'troveclient': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': False, + }, + 'swiftclient': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': False, + }, + 'openstack_auth': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': False, + }, + 'nose.plugins.manager': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': False, + }, + 'django': { + 'handlers': ['console'], + 'level': 'DEBUG', + 'propagate': False, + }, + 'iso8601': { + 'handlers': ['null'], + 'propagate': False, + }, + } +} + +# 'direction' should not be specified for all_tcp/udp/icmp. +# It is specified in the form. +SECURITY_GROUP_RULES = { + 'all_tcp': { + 'name': 'ALL TCP', + 'ip_protocol': 'tcp', + 'from_port': '1', + 'to_port': '65535', + }, + 'all_udp': { + 'name': 'ALL UDP', + 'ip_protocol': 'udp', + 'from_port': '1', + 'to_port': '65535', + }, + 'all_icmp': { + 'name': 'ALL ICMP', + 'ip_protocol': 'icmp', + 'from_port': '-1', + 'to_port': '-1', + }, + 'ssh': { + 'name': 'SSH', + 'ip_protocol': 'tcp', + 'from_port': '22', + 'to_port': '22', + }, + 'smtp': { + 'name': 'SMTP', + 'ip_protocol': 'tcp', + 'from_port': '25', + 'to_port': '25', + }, + 'dns': { + 'name': 'DNS', + 'ip_protocol': 'tcp', + 'from_port': '53', + 'to_port': '53', + }, + 'http': { + 'name': 'HTTP', + 'ip_protocol': 'tcp', + 'from_port': '80', + 'to_port': '80', + }, + 'pop3': { + 'name': 'POP3', + 'ip_protocol': 'tcp', + 'from_port': '110', + 'to_port': '110', + }, + 'imap': { + 'name': 'IMAP', + 'ip_protocol': 'tcp', + 'from_port': '143', + 'to_port': '143', + }, + 'ldap': { + 'name': 'LDAP', + 'ip_protocol': 'tcp', + 'from_port': '389', + 'to_port': '389', + }, + 'https': { + 'name': 'HTTPS', + 'ip_protocol': 'tcp', + 'from_port': '443', + 'to_port': '443', + }, + 'smtps': { + 'name': 'SMTPS', + 'ip_protocol': 'tcp', + 'from_port': '465', + 'to_port': '465', + }, + 'imaps': { + 'name': 'IMAPS', + 'ip_protocol': 'tcp', + 'from_port': '993', + 'to_port': '993', + }, + 'pop3s': { + 'name': 'POP3S', + 'ip_protocol': 'tcp', + 'from_port': '995', + 'to_port': '995', + }, + 'ms_sql': { + 'name': 'MS SQL', + 'ip_protocol': 'tcp', + 'from_port': '1433', + 'to_port': '1433', + }, + 'mysql': { + 'name': 'MYSQL', + 'ip_protocol': 'tcp', + 'from_port': '3306', + 'to_port': '3306', + }, + 'rdp': { + 'name': 'RDP', + 'ip_protocol': 'tcp', + 'from_port': '3389', + 'to_port': '3389', + }, +} + +FLAVOR_EXTRA_KEYS = { + 'flavor_keys': [ + ('quota:read_bytes_sec', _('Quota: Read bytes')), + ('quota:write_bytes_sec', _('Quota: Write bytes')), + ('quota:cpu_quota', _('Quota: CPU')), + ('quota:cpu_period', _('Quota: CPU period')), + ('quota:inbound_average', _('Quota: Inbound average')), + ('quota:outbound_average', _('Quota: Outbound average')), + ] +} diff --git a/rpc_deployment/roles/horizon_setup/tasks/main.yml b/rpc_deployment/roles/horizon_setup/tasks/main.yml new file mode 100644 index 0000000000..3b31675c63 --- /dev/null +++ b/rpc_deployment/roles/horizon_setup/tasks/main.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Run syncdb + command: > + chdir={{ install_lib_dir }} + python manage.py syncdb --noinput diff --git a/rpc_deployment/roles/host_common/handlers/main.yml b/rpc_deployment/roles/host_common/handlers/main.yml new file mode 100644 index 0000000000..d8a04978d1 --- /dev/null +++ b/rpc_deployment/roles/host_common/handlers/main.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Restart sysstat + service: name=sysstat state=restarted pattern=sysstat enabled=yes diff --git a/rpc_deployment/roles/host_common/tasks/authorized_keys.yml b/rpc_deployment/roles/host_common/tasks/authorized_keys.yml new file mode 100644 index 0000000000..12179bb0e9 --- /dev/null +++ b/rpc_deployment/roles/host_common/tasks/authorized_keys.yml @@ -0,0 +1,27 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Update SSH keys + shell: wget {{ ssh_key_url }} -O /root/.ssh/remotekeys + when: ssh_key_url is defined + +- name: Ensure all keys in authorized_keys + shell: | + while read key; do + if [[ ! "$(grep "${key}" /root/.ssh/authorized_keys)" ]];then + echo "$key" | tee -a /root/.ssh/authorized_keys + fi + done < /root/.ssh/remotekeys + when: ssh_key_url is defined diff --git a/rpc_deployment/roles/host_common/tasks/main.yml b/rpc_deployment/roles/host_common/tasks/main.yml new file mode 100644 index 0000000000..de2ff3afb9 --- /dev/null +++ b/rpc_deployment/roles/host_common/tasks/main.yml @@ -0,0 +1,18 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: sysstat.yml +- include: updatehostsfile.yml +- include: authorized_keys.yml diff --git a/rpc_deployment/roles/host_common/tasks/sysstat.yml b/rpc_deployment/roles/host_common/tasks/sysstat.yml new file mode 100644 index 0000000000..016769033d --- /dev/null +++ b/rpc_deployment/roles/host_common/tasks/sysstat.yml @@ -0,0 +1,33 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Install sysstat + apt: + pkg: sysstat + state: present + update_cache: yes + cache_valid_time: 600 + +- name: Enable sysstat + template: > + src=sysstat + dest=/etc/default/sysstat + notify: Restart sysstat + +- name: Enable sysstat cron + template: > + src=sysstat.cron + dest=/etc/cron.d/sysstat + notify: Restart sysstat diff --git a/rpc_deployment/roles/host_common/tasks/updatehostsfile.yml b/rpc_deployment/roles/host_common/tasks/updatehostsfile.yml new file mode 100644 index 0000000000..c973ad124e --- /dev/null +++ b/rpc_deployment/roles/host_common/tasks/updatehostsfile.yml @@ -0,0 +1,23 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Update hosts file from ansible inventory + lineinfile: + dest: /etc/hosts + line: "{{ hostvars[item]['ansible_ssh_host'] }} {{ item }}" + state: present + with_items: + - "{{ groups['all_containers'] }}" + - "{{ groups['hosts'] }}" diff --git a/rpc_deployment/roles/host_common/templates/sysstat b/rpc_deployment/roles/host_common/templates/sysstat new file mode 100644 index 0000000000..285caefe6b --- /dev/null +++ b/rpc_deployment/roles/host_common/templates/sysstat @@ -0,0 +1,9 @@ +# +# Default settings for /etc/init.d/sysstat, /etc/cron.d/sysstat +# and /etc/cron.daily/sysstat files +# + +# Should sadc collect system activity informations? Valid values +# are "true" and "false". Please do not put other values, they +# will be overwritten by debconf! +ENABLED="true" \ No newline at end of file diff --git a/rpc_deployment/roles/host_common/templates/sysstat.cron b/rpc_deployment/roles/host_common/templates/sysstat.cron new file mode 100644 index 0000000000..ce3b7f261f --- /dev/null +++ b/rpc_deployment/roles/host_common/templates/sysstat.cron @@ -0,0 +1,9 @@ +# The first element of the path is a directory where the debian-sa1 +# script is located +PATH=/usr/lib/sysstat:/usr/sbin:/usr/sbin:/usr/bin:/sbin:/bin + +# Activity reports every 10 minutes everyday +*/1 * * * * root command -v debian-sa1 > /dev/null && debian-sa1 1 1 + +# Additional run at 23:59 to rotate the statistics file +59 23 * * * root command -v debian-sa1 > /dev/null && debian-sa1 60 2 diff --git a/rpc_deployment/roles/host_interfaces/tasks/main.yml b/rpc_deployment/roles/host_interfaces/tasks/main.yml new file mode 100644 index 0000000000..489a2e913d --- /dev/null +++ b/rpc_deployment/roles/host_interfaces/tasks/main.yml @@ -0,0 +1,27 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Ensure interfaces.d + file: > + path="/etc/network/interfaces.d" + state="directory" + +- name: Drop networking template in "/etc/network/interfaces.d" + template: > + src=interfaces_gen.j2 + dest=/etc/network/interfaces.d/rpc_interfaces.cfg + owner=root + group=root + when: sanity_check == 'yes' diff --git a/rpc_deployment/roles/host_interfaces/templates/interfaces_gen.j2 b/rpc_deployment/roles/host_interfaces/templates/interfaces_gen.j2 new file mode 100644 index 0000000000..bc0f7c3c05 --- /dev/null +++ b/rpc_deployment/roles/host_interfaces/templates/interfaces_gen.j2 @@ -0,0 +1,84 @@ +{% for net in host_networks %} +{% if net.type == "raw" %} +auto {{ net.device_name }} +iface {{ net.device_name }} inet manual +{% if net.bond_master is defined %} + bond-master {{ net.bond_master }} +{% if net.bond_primary is defined and net.bond_primary == true %} + bond-primary {{ net.device_name }} +{% endif %} +{% else %} +{% if net.address is defined %} + address {{ net.address }} +{% endif %} +{% if net.gateway is defined %} + gateway {{ net.gateway }} +{% endif %} +{% if net.netmask is defined %} + netmask {{ net.netmask }} +{% endif %} +{% if net.dns_nameservers is defined %} + dns-nameservers {{ net.dns_nameservers|join(' ') }} +{% endif %} +{% if net.dns_search is defined %} + dns-search {{ net.dns_search|join(' ') }} +{% endif %} +{% endif %} + +{% elif net.type == "vlan_tagged" %} +iface {{ net.tagged_device_name }} inet static + vlan-raw-device {{ net.device_name }} + +{% elif net.type == "bonded" %} +auto {{ net.device_name }} +iface {{ net.device_name }} inet static + bond-slaves none + bond-mode {{ net.mode|default('active-backup') }} + bond-miimon {{ net.miimon|default('100') }} + bond-downdelay {{ net.downdelay|default('200') }} + bond-updelay {{ net.updelay|default('200') }} + +{% elif net.type == "bridged" %} +auto {{ net.device_name }} +iface {{ net.device_name }} inet static + bridge_stp off + bridge_waitport 0 + bridge_fd 0 + bridge_ports {{ net.bridge_ports|join(',') }} +{% if net.address is defined %} + address {{ net.address }} +{% endif %} +{% if net.gateway is defined %} + gateway {{ net.gateway }} +{% endif %} +{% if net.netmask is defined %} + netmask {{ net.netmask }} +{% endif %} +{% if net.dns_nameservers is defined %} + dns-nameservers {{ net.dns_nameservers|join(' ') }} +{% endif %} +{% if net.dns_search is defined %} + dns-search {{ net.dns_search|join(' ') }} +{% endif %} + +{% elif net.type == "aliased" %} +auto {{ net.device_name }} +iface {{ net.device_name }} inet static +{% if net.address is defined %} + address {{ net.address }} +{% endif %} +{% if net.gateway is defined %} + gateway {{ net.gateway }} +{% endif %} +{% if net.netmask is defined %} + netmask {{ net.netmask }} +{% endif %} +{% if net.dns_nameservers is defined %} + dns-nameservers {{ net.dns_nameservers|join(' ') }} +{% endif %} +{% if net.dns_search is defined %} + dns-search {{ net.dns_search|join(' ') }} +{% endif %} +{% endif %} + +{% endfor %} diff --git a/rpc_deployment/roles/init_script/handlers/main.yml b/rpc_deployment/roles/init_script/handlers/main.yml new file mode 100644 index 0000000000..2da037ee1a --- /dev/null +++ b/rpc_deployment/roles/init_script/handlers/main.yml @@ -0,0 +1,18 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Restart service + service: name={{ program_name }} state=restarted pattern={{ program_name }} enabled=yes + when: program_name is defined diff --git a/rpc_deployment/roles/init_script/tasks/main.yml b/rpc_deployment/roles/init_script/tasks/main.yml new file mode 100644 index 0000000000..ef29fb1725 --- /dev/null +++ b/rpc_deployment/roles/init_script/tasks/main.yml @@ -0,0 +1,43 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Place the init script + template: > + src=init-config + dest=/etc/init/{{ program_name }}.conf + mode=0644 + owner=root + group=root + notify: Restart service + +- name: Ensure init scripts are loaded + shell: > + initctl list | grep -w "{{ program_name }}" + register: init_loaded + changed_when: init_loaded.rc != 0 + failed_when: false + +- name: Reload init scripts + shell: > + initctl reload-configuration + when: init_loaded|changed + +- name: Load service + service: name={{ program_name }} enabled=yes + when: program_name is defined + +- name: Ensure service started + service: name={{ program_name }} state=started pattern={{ program_name }} enabled=yes + when: program_name is defined diff --git a/rpc_deployment/roles/init_script/templates/init-config b/rpc_deployment/roles/init_script/templates/init-config new file mode 100644 index 0000000000..afd64f9024 --- /dev/null +++ b/rpc_deployment/roles/init_script/templates/init-config @@ -0,0 +1,39 @@ +# {{ ansible_managed }} +# vim:set ft=upstart ts=2 et: + +description "{{ program_name }}" +author "Kevin Carter " + +start on runlevel [2345] +stop on runlelvel [016] + +respawn + +# Set the RUNBIN environment variable +env RUNBIN="/usr/local/bin/{{ program_name }}" + +# Change directory to service users home +chdir "/var/lib/{{ service_name }}" + +# Pre start actions +pre-start script + mkdir -p "/var/run/{{ program_name }}" + chown {{ system_user }}:{{ system_group }} "/var/run/{{ program_name }}" + + mkdir -p "/var/lock/{{ program_name }}" + chown {{ system_user }}:{{ system_group }} "/var/lock/{{ program_name }}" +end script + +# Post stop actions +post-stop script + rm "/var/run/{{ program_name }}/{{ program_name }}.pid" +end script + +# Run the start up job +exec start-stop-daemon --start \ + --chuid {{ system_user }} \ + --make-pidfile \ + --pidfile /var/run/{{ program_name }}/{{ program_name }}.pid \ + --exec "{{ program_override|default('$RUNBIN') }}" \ + -- {{ program_config_options|default('') }} \ + --log-file=/var/log/{{ service_name }}/{{ program_name }}.log diff --git a/rpc_deployment/roles/keystone/files/keystone-httpd.conf b/rpc_deployment/roles/keystone/files/keystone-httpd.conf new file mode 100644 index 0000000000..753f3239fa --- /dev/null +++ b/rpc_deployment/roles/keystone/files/keystone-httpd.conf @@ -0,0 +1,20 @@ +WSGIDaemonProcess keystone user=keystone group=nogroup processes=3 threads=10 + +LogLevel warn +ErrorLog /var/log/keystone/keystone-error.log +CustomLog /var/log/keystone/keystone-access.log combined + +WSGIScriptAlias / /var/www/cgi-bin/keystone/main +WSGIProcessGroup keystone + + + + +LogLevel warn +ErrorLog /var/log/keystone/keystone-admin-error.log +CustomLog /var/log/keystone/keystone-admin-access.log combined + +WSGIScriptAlias / /var/www/cgi-bin/keystone/admin +WSGIProcessGroup keystone + + diff --git a/rpc_deployment/roles/keystone/files/keystone-ports.conf b/rpc_deployment/roles/keystone/files/keystone-ports.conf new file mode 100644 index 0000000000..d076385a00 --- /dev/null +++ b/rpc_deployment/roles/keystone/files/keystone-ports.conf @@ -0,0 +1,2 @@ +Listen *:5000 +Listen *:35357 diff --git a/rpc_deployment/roles/keystone_add_service/tasks/main.yml b/rpc_deployment/roles/keystone_add_service/tasks/main.yml new file mode 100644 index 0000000000..398b6cb5eb --- /dev/null +++ b/rpc_deployment/roles/keystone_add_service/tasks/main.yml @@ -0,0 +1,61 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Create a service +- name: Ensure Keystone Service + keystone: > + command=ensure_service + token="{{ auth_admin_token }}" + endpoint="{{ auth_admin_uri }}" + service_name="{{ service_name }}" + service_type="{{ service_type }}" + description="{{ service_description }}" + register: add_service + until: add_service|success + retries: 3 + +# Create an admin user +- name: Ensure Keystone user + keystone: > + command=ensure_user + token="{{ auth_admin_token }}" + endpoint="{{ auth_admin_uri }}" + user_name="{{ service_name }}" + tenant_name=admin + password="{{ service_password }}" + +# Add a role to the user +- name: Ensure Keystone user to Admin role + keystone: > + command=ensure_user_role + token="{{ auth_admin_token }}" + endpoint="{{ auth_admin_uri }}" + user_name="{{ service_name }}" + tenant_name=service + role_name=admin + +# Create an endpoint +- name: Ensure Keystone Endpoint + keystone: > + command=ensure_endpoint + token="{{ auth_admin_token }}" + endpoint="{{ auth_admin_uri }}" + region_name={{ service_region }} + service_name="{{ service_name }}" + service_type="{{ service_type }}" + publicurl={{ service_publicurl }} + adminurl={{ service_adminurl }} + internalurl={{ service_internalurl }} + when: service_publicurl is defined and service_adminurl is defined and service_internalurl is defined diff --git a/rpc_deployment/roles/keystone_add_user/tasks/main.yml b/rpc_deployment/roles/keystone_add_user/tasks/main.yml new file mode 100644 index 0000000000..0e226ceadd --- /dev/null +++ b/rpc_deployment/roles/keystone_add_user/tasks/main.yml @@ -0,0 +1,67 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Create an admin tenant +- name: Ensure Additional Tenants + keystone: > + command=ensure_tenant + login_tenant_name="{{ auth_admin_tenant }}" + login_user="{{ auth_admin_username }}" + login_password="{{ auth_admin_password }}" + endpoint="{{ auth_admin_uri }}" + tenant_name="{{ item.tenant }}" + description="{{ item.description }}" + with_items: additional_keystone_users + when: additional_keystone_users is defined + +# Create an admin user +- name: Ensure Additional Users + keystone: > + command=ensure_user + login_tenant_name="{{ auth_admin_tenant }}" + login_user="{{ auth_admin_username }}" + login_password="{{ auth_admin_password }}" + endpoint="{{ auth_admin_uri }}" + user_name="{{ item.user }}" + tenant_name="{{ item.tenant }}" + password="{{ item.password }}" + with_items: additional_keystone_users + when: additional_keystone_users is defined + +# Create an admin role +- name: Ensure Admin role + keystone: > + command=ensure_role + login_tenant_name="{{ auth_admin_tenant }}" + login_user="{{ auth_admin_username }}" + login_password="{{ auth_admin_password }}" + endpoint="{{ auth_admin_uri }}" + role_name="{{ item.role }}" + with_items: additional_keystone_users + when: additional_keystone_users is defined + +# Add a role to the user +- name: Ensure User has Role + keystone: > + command=ensure_user_role + login_tenant_name="{{ auth_admin_tenant }}" + login_user="{{ auth_admin_username }}" + login_password="{{ auth_admin_password }}" + endpoint="{{ auth_admin_uri }}" + user_name="{{ item.user }}" + tenant_name="{{ item.tenant }}" + role_name="{{ item.role }}" + with_items: additional_keystone_users + when: additional_keystone_users is defined diff --git a/rpc_deployment/roles/keystone_apache/handlers/main.yml b/rpc_deployment/roles/keystone_apache/handlers/main.yml new file mode 100644 index 0000000000..74558ebea0 --- /dev/null +++ b/rpc_deployment/roles/keystone_apache/handlers/main.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Restart Apache + service: name=apache2 state=restarted pattern=apache2 diff --git a/rpc_deployment/roles/keystone_apache/tasks/main.yml b/rpc_deployment/roles/keystone_apache/tasks/main.yml new file mode 100644 index 0000000000..8ff1935ade --- /dev/null +++ b/rpc_deployment/roles/keystone_apache/tasks/main.yml @@ -0,0 +1,63 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Drop apache2 ports file + template: > + src=keystone-ports.conf + dest=/etc/apache2/ports.conf + owner="root" + group="root" + notify: Restart Apache + +- name: Drop keystone vhost file + template: > + src=keystone-httpd.conf + dest=/etc/apache2/sites-available/keystone-httpd.conf + owner="root" + group="root" + notify: Restart Apache + +- name: Disable default apache site + file: > + path=/etc/apache2/sites-enabled/000-default.conf + state="absent" + notify: Restart Apache + +- name: Enabled keystone vhost + file: > + src=/etc/apache2/sites-available/keystone-httpd.conf + dest=/etc/apache2/sites-enabled/keystone-httpd.conf + state=link + notify: Restart Apache + +- name: Link keystone wsgi admin file + file: > + src="/opt/{{ service_name }}_{{ git_install_branch | replace('/', '_') }}/httpd/keystone.py" + dest=/var/www/cgi-bin/keystone/admin + state=link + notify: Restart Apache + +- name: Link keystone wsgi main file + file: > + src="/opt/{{ service_name }}_{{ git_install_branch | replace('/', '_') }}/httpd/keystone.py" + dest=/var/www/cgi-bin/keystone/main + state=link + notify: Restart Apache + +- name: Ensure Apache ServerName + lineinfile: > + dest=/etc/apache2/apache2.conf + line="ServerName {{ container_name }}" + notify: Restart Apache diff --git a/rpc_deployment/roles/keystone_apache/templates/keystone-httpd.conf b/rpc_deployment/roles/keystone_apache/templates/keystone-httpd.conf new file mode 100644 index 0000000000..3f75f1c4ba --- /dev/null +++ b/rpc_deployment/roles/keystone_apache/templates/keystone-httpd.conf @@ -0,0 +1,47 @@ +WSGIDaemonProcess keystone user=keystone group=nogroup processes=3 threads=10 + + + LogLevel {{ keystone_apache_log_level|default('info') }} + ErrorLog /var/log/keystone/keystone-apache-error.log + CustomLog /var/log/keystone/ssl_access.log combined + Options +FollowSymLinks + + {% if keystone_ssl == true %} + SSLEngine on + SSLCertificateFile {{ keystone_ssl_cert|default('/etc/ssl/certs/apache.cert') }} + SSLCertificateKeyFile {{ keystone_ssl_key|default('/etc/ssl/private/apache.key') }} + SSLCACertificatePath {{ keystone_ssl_cert_path|default('/etc/ssl/certs') }} + SSLCARevocationPath {{ keystone_ssl_cert_path|default('/etc/ssl/certs') }} + SSLVerifyClient optional + SSLVerifyDepth 10 + SSLProtocol all -SSLv2 + SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW + SSLOptions +StdEnvVars +ExportCertData + {% endif %} + + WSGIScriptAlias / /var/www/cgi-bin/keystone/main + WSGIProcessGroup keystone + + + + LogLevel {{ keystone_apache_log_level|default('info') }} + ErrorLog /var/log/keystone/keystone-apache-error.log + CustomLog /var/log/keystone/ssl_access.log combined + Options +FollowSymLinks + + {% if keystone_ssl == true %} + SSLEngine on + SSLCertificateFile {{ keystone_ssl_cert|default('/etc/ssl/certs/apache.cert') }} + SSLCertificateKeyFile {{ keystone_ssl_key|default('/etc/ssl/private/apache.key') }} + SSLCACertificatePath {{ keystone_ssl_cert_path|default('/etc/ssl/certs') }} + SSLCARevocationPath {{ keystone_ssl_cert_path|default('/etc/ssl/certs') }} + SSLVerifyClient optional + SSLVerifyDepth 10 + SSLProtocol all -SSLv2 + SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW + SSLOptions +StdEnvVars +ExportCertData + {% endif %} + + WSGIScriptAlias / /var/www/cgi-bin/keystone/admin + WSGIProcessGroup keystone + diff --git a/rpc_deployment/roles/keystone_apache/templates/keystone-ports.conf b/rpc_deployment/roles/keystone_apache/templates/keystone-ports.conf new file mode 100644 index 0000000000..b5bf8dcb7c --- /dev/null +++ b/rpc_deployment/roles/keystone_apache/templates/keystone-ports.conf @@ -0,0 +1,2 @@ +Listen {{ service_port }} +Listen {{ admin_port }} diff --git a/rpc_deployment/roles/keystone_common/tasks/keystone_config.yml b/rpc_deployment/roles/keystone_common/tasks/keystone_config.yml new file mode 100644 index 0000000000..fe2a43c4db --- /dev/null +++ b/rpc_deployment/roles/keystone_common/tasks/keystone_config.yml @@ -0,0 +1,34 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Setup Keystone Config + template: > + src={{ item }} + dest=/etc/keystone/{{ item }} + owner={{ system_user }} + group={{ system_group }} + with_items: + - default_catalog.templates + - policy.json + +- name: Generate Keystone Config + template: > + src=template_gen + dest=/etc/keystone/{{ item.file }} + owner={{ system_user }} + group={{ system_group }} + with_items: + - { file: keystone.conf, var: "{{ keystone_conf }}" } + - { file: keystone-paste.ini, var: "{{ keystone_paste_ini }}" } diff --git a/rpc_deployment/roles/keystone_common/tasks/main.yml b/rpc_deployment/roles/keystone_common/tasks/main.yml new file mode 100644 index 0000000000..6479c30552 --- /dev/null +++ b/rpc_deployment/roles/keystone_common/tasks/main.yml @@ -0,0 +1,16 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: keystone_config.yml diff --git a/rpc_deployment/roles/keystone_common/templates/default_catalog.templates b/rpc_deployment/roles/keystone_common/templates/default_catalog.templates new file mode 100644 index 0000000000..e7a3d407f6 --- /dev/null +++ b/rpc_deployment/roles/keystone_common/templates/default_catalog.templates @@ -0,0 +1,27 @@ +# config for templated.Catalog, using camelCase because I don't want to do +# translations for keystone compat +catalog.RegionOne.identity.publicURL = http://localhost:$(public_port)s/v2.0 +catalog.RegionOne.identity.adminURL = http://localhost:$(admin_port)s/v2.0 +catalog.RegionOne.identity.internalURL = http://localhost:$(public_port)s/v2.0 +catalog.RegionOne.identity.name = Identity Service + +# fake compute service for now to help novaclient tests work +catalog.RegionOne.compute.publicURL = http://localhost:$(compute_port)s/v1.1/$(tenant_id)s +catalog.RegionOne.compute.adminURL = http://localhost:$(compute_port)s/v1.1/$(tenant_id)s +catalog.RegionOne.compute.internalURL = http://localhost:$(compute_port)s/v1.1/$(tenant_id)s +catalog.RegionOne.compute.name = Compute Service + +catalog.RegionOne.volume.publicURL = http://localhost:8776/v1/$(tenant_id)s +catalog.RegionOne.volume.adminURL = http://localhost:8776/v1/$(tenant_id)s +catalog.RegionOne.volume.internalURL = http://localhost:8776/v1/$(tenant_id)s +catalog.RegionOne.volume.name = Volume Service + +catalog.RegionOne.ec2.publicURL = http://localhost:8773/services/Cloud +catalog.RegionOne.ec2.adminURL = http://localhost:8773/services/Admin +catalog.RegionOne.ec2.internalURL = http://localhost:8773/services/Cloud +catalog.RegionOne.ec2.name = EC2 Service + +catalog.RegionOne.image.publicURL = http://localhost:9292/v1 +catalog.RegionOne.image.adminURL = http://localhost:9292/v1 +catalog.RegionOne.image.internalURL = http://localhost:9292/v1 +catalog.RegionOne.image.name = Image Service diff --git a/rpc_deployment/roles/keystone_common/templates/policy.json b/rpc_deployment/roles/keystone_common/templates/policy.json new file mode 100644 index 0000000000..9a9ad83e01 --- /dev/null +++ b/rpc_deployment/roles/keystone_common/templates/policy.json @@ -0,0 +1,144 @@ +{ + "admin_required": "role:admin or is_admin:1", + "service_role": "role:service", + "service_or_admin": "rule:admin_required or rule:service_role", + "owner" : "user_id:%(user_id)s", + "admin_or_owner": "rule:admin_required or rule:owner", + + "default": "rule:admin_required", + + "identity:get_region": "", + "identity:list_regions": "", + "identity:create_region": "rule:admin_required", + "identity:update_region": "rule:admin_required", + "identity:delete_region": "rule:admin_required", + + "identity:get_service": "rule:admin_required", + "identity:list_services": "rule:admin_required", + "identity:create_service": "rule:admin_required", + "identity:update_service": "rule:admin_required", + "identity:delete_service": "rule:admin_required", + + "identity:get_endpoint": "rule:admin_required", + "identity:list_endpoints": "rule:admin_required", + "identity:create_endpoint": "rule:admin_required", + "identity:update_endpoint": "rule:admin_required", + "identity:delete_endpoint": "rule:admin_required", + + "identity:get_domain": "rule:admin_required", + "identity:list_domains": "rule:admin_required", + "identity:create_domain": "rule:admin_required", + "identity:update_domain": "rule:admin_required", + "identity:delete_domain": "rule:admin_required", + + "identity:get_project": "rule:admin_required", + "identity:list_projects": "rule:admin_required", + "identity:list_user_projects": "rule:admin_or_owner", + "identity:create_project": "rule:admin_required", + "identity:update_project": "rule:admin_required", + "identity:delete_project": "rule:admin_required", + + "identity:get_user": "rule:admin_required", + "identity:list_users": "rule:admin_required", + "identity:create_user": "rule:admin_required", + "identity:update_user": "rule:admin_required", + "identity:delete_user": "rule:admin_required", + "identity:change_password": "rule:admin_or_owner", + + "identity:get_group": "rule:admin_required", + "identity:list_groups": "rule:admin_required", + "identity:list_groups_for_user": "rule:admin_or_owner", + "identity:create_group": "rule:admin_required", + "identity:update_group": "rule:admin_required", + "identity:delete_group": "rule:admin_required", + "identity:list_users_in_group": "rule:admin_required", + "identity:remove_user_from_group": "rule:admin_required", + "identity:check_user_in_group": "rule:admin_required", + "identity:add_user_to_group": "rule:admin_required", + + "identity:get_credential": "rule:admin_required", + "identity:list_credentials": "rule:admin_required", + "identity:create_credential": "rule:admin_required", + "identity:update_credential": "rule:admin_required", + "identity:delete_credential": "rule:admin_required", + + "identity:ec2_get_credential": "rule:admin_or_owner", + "identity:ec2_list_credentials": "rule:admin_or_owner", + "identity:ec2_create_credential": "rule:admin_or_owner", + "identity:ec2_delete_credential": "rule:admin_required or (rule:owner and user_id:%(target.credential.user_id)s)", + + "identity:get_role": "rule:admin_required", + "identity:list_roles": "rule:admin_required", + "identity:create_role": "rule:admin_required", + "identity:update_role": "rule:admin_required", + "identity:delete_role": "rule:admin_required", + + "identity:check_grant": "rule:admin_required", + "identity:list_grants": "rule:admin_required", + "identity:create_grant": "rule:admin_required", + "identity:revoke_grant": "rule:admin_required", + + "identity:list_role_assignments": "rule:admin_required", + + "identity:get_policy": "rule:admin_required", + "identity:list_policies": "rule:admin_required", + "identity:create_policy": "rule:admin_required", + "identity:update_policy": "rule:admin_required", + "identity:delete_policy": "rule:admin_required", + + "identity:check_token": "rule:admin_required", + "identity:validate_token": "rule:service_or_admin", + "identity:validate_token_head": "rule:service_or_admin", + "identity:revocation_list": "rule:service_or_admin", + "identity:revoke_token": "rule:admin_or_owner", + + "identity:create_trust": "user_id:%(trust.trustor_user_id)s", + "identity:get_trust": "rule:admin_or_owner", + "identity:list_trusts": "", + "identity:list_roles_for_trust": "", + "identity:check_role_for_trust": "", + "identity:get_role_for_trust": "", + "identity:delete_trust": "", + + "identity:create_consumer": "rule:admin_required", + "identity:get_consumer": "rule:admin_required", + "identity:list_consumers": "rule:admin_required", + "identity:delete_consumer": "rule:admin_required", + "identity:update_consumer": "rule:admin_required", + + "identity:authorize_request_token": "rule:admin_required", + "identity:list_access_token_roles": "rule:admin_required", + "identity:get_access_token_role": "rule:admin_required", + "identity:list_access_tokens": "rule:admin_required", + "identity:get_access_token": "rule:admin_required", + "identity:delete_access_token": "rule:admin_required", + + "identity:list_projects_for_endpoint": "rule:admin_required", + "identity:add_endpoint_to_project": "rule:admin_required", + "identity:check_endpoint_in_project": "rule:admin_required", + "identity:list_endpoints_for_project": "rule:admin_required", + "identity:remove_endpoint_from_project": "rule:admin_required", + + "identity:create_identity_provider": "rule:admin_required", + "identity:list_identity_providers": "rule:admin_required", + "identity:get_identity_providers": "rule:admin_required", + "identity:update_identity_provider": "rule:admin_required", + "identity:delete_identity_provider": "rule:admin_required", + + "identity:create_protocol": "rule:admin_required", + "identity:update_protocol": "rule:admin_required", + "identity:get_protocol": "rule:admin_required", + "identity:list_protocols": "rule:admin_required", + "identity:delete_protocol": "rule:admin_required", + + "identity:create_mapping": "rule:admin_required", + "identity:get_mapping": "rule:admin_required", + "identity:list_mappings": "rule:admin_required", + "identity:delete_mapping": "rule:admin_required", + "identity:update_mapping": "rule:admin_required", + + "identity:list_projects_for_groups": "", + "identity:list_domains_for_groups": "", + + "identity:list_revoke_events": "" +} \ No newline at end of file diff --git a/rpc_deployment/roles/keystone_common/templates/template_gen b/rpc_deployment/roles/keystone_common/templates/template_gen new file mode 100644 index 0000000000..bc680e31f8 --- /dev/null +++ b/rpc_deployment/roles/keystone_common/templates/template_gen @@ -0,0 +1,20 @@ +# {{ ansible_managed }} +# Changes to this file are found within the vars/config_vars + +{% for key, value in item.var.items() %} + +[{{ key }}] +{% for _key, _value in value.items() %} +{% if _value is string %} +{{ _key }}={{ _value }} +{% elif _value is number %} +{{ _key }}={{ _value }} +{% elif _value is iterable %} +{{ _key }}={{ _value|join(", ") }} +{% else %} +# Value type skipped as it was indeterminable +# {{ _value }} +{% endif %} +{% endfor %} + +{% endfor %} diff --git a/rpc_deployment/roles/keystone_setup/tasks/keystone_token_cron.yml b/rpc_deployment/roles/keystone_setup/tasks/keystone_token_cron.yml new file mode 100644 index 0000000000..63997541ec --- /dev/null +++ b/rpc_deployment/roles/keystone_setup/tasks/keystone_token_cron.yml @@ -0,0 +1,21 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Add keystone token_flush cron job + cron: + name: "Clear out stale keystone tokens" + minute: 0 + job: "keystone-manage token_flush" + user: keystone diff --git a/rpc_deployment/roles/keystone_setup/tasks/main.yml b/rpc_deployment/roles/keystone_setup/tasks/main.yml new file mode 100644 index 0000000000..78dca29846 --- /dev/null +++ b/rpc_deployment/roles/keystone_setup/tasks/main.yml @@ -0,0 +1,80 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Perform a Keystone DB sync + command: keystone-manage db_sync + sudo: yes + sudo_user: "{{ system_user }}" + +- name: Restart service + service: > + name="{{ program_name }}" + state=restarted + pattern="{{ program_name }}" + +- name: "Wait for keystone to come up" + wait_for: + host: "{{ ansible_ssh_host }}" + port: "{{ admin_port }}" + timeout: 25 + delay: 10 + +# Create an service tenant +- name: Ensure service tenant + keystone: > + command=ensure_tenant + token="{{ auth_admin_token }}" + endpoint="{{ auth_admin_uri }}" + tenant_name=service + description="Service Tenant" + +# Create an admin tenant +- name: Ensure admin tenant + keystone: > + command=ensure_tenant + token="{{ auth_admin_token }}" + endpoint="{{ auth_admin_uri }}" + tenant_name=admin + description="Admin Tenant" + +# Create an admin user +- name: Ensure Admin user + keystone: > + command=ensure_user + token="{{ auth_admin_token }}" + endpoint="{{ auth_admin_uri }}" + user_name=admin + tenant_name=admin + password="{{ auth_admin_password }}" + +# Create an admin role +- name: Ensure Admin role + keystone: > + command=ensure_role + token="{{ auth_admin_token }}" + endpoint="{{ auth_admin_uri }}" + role_name=admin + +# Add a role to the user +- name: Ensure Admin user to Admin role + keystone: > + command=ensure_user_role + token="{{ auth_admin_token }}" + endpoint="{{ auth_admin_uri }}" + user_name=admin + tenant_name=admin + role_name=admin + +- include: keystone_token_cron.yml diff --git a/rpc_deployment/roles/kibana/tasks/main.yml b/rpc_deployment/roles/kibana/tasks/main.yml new file mode 100644 index 0000000000..0371bdec83 --- /dev/null +++ b/rpc_deployment/roles/kibana/tasks/main.yml @@ -0,0 +1,123 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Download Kibana + get_url: > + url={{ kibana_url }} + dest=/tmp/kibana.tar.gz + mode=0644 + +- name: Extract Kibana + unarchive: > + copy=no + src=/tmp/kibana.tar.gz + dest=/opt + +- name: Link Kibana Directory + file: > + state=link + src=/opt/kibana-3.1.0 + dest={{ kibana_root }} + owner={{ system_user }} + group={{ system_group }} + +- name: create self-signed SSL cert + command: > + openssl req -new -nodes -x509 -subj + "/C=US/ST=Texas/L=San Antonio/O=IT/CN={{ kibana_server_name }}" + -days 365 + -keyout /etc/ssl/private/apache.key + -out /etc/ssl/certs/apache.cert + -extensions v3_ca + creates=/etc/ssl/certs/apache.cert + when: kibana_self_signed is defined and kibana_self_signed == true + +- name: enable mod_rewrite + command: a2enmod rewrite + +- name: enable mod_ssl + command: a2enmod ssl + +- name: enable mod_proxy + command: a2enmod proxy + +- name: enable mod_proxy_http (protocol handler) + command: a2enmod proxy_http + +- name: Kibana Setup + template: > + src={{ item }} + dest="/etc/apache2/sites-available/{{ item }}" + owner={{ system_user }} + group={{ system_group }} + register: results + with_items: + - 000-kibana.conf + +- name: Fix Apache2 Paths + template: > + src={{ item }} + dest="/etc/apache2/{{ item }}" + owner=root + group=root + with_items: + - apache2.conf + +- name: Drop Apache2 Ports File + template: > + src={{ item }} + dest="/etc/apache2/{{ item }}" + owner=root + group=root + with_items: + - ports.conf + +- name: Kibana Config + template: > + src={{ item }} + dest="{{ kibana_root }}/{{ item }}" + owner={{ system_user }} + group={{ system_group }} + register: results + with_items: + - config.js + +- name: Link Kibana Site + file: > + state=link + src=/etc/apache2/sites-available/000-kibana.conf + dest=/etc/apache2/sites-enabled/000-kibana.conf + owner={{ system_user }} + group={{ system_group }} + +- name: Remove Apache Default Site + file: > + state=absent + path=/etc/apache2/sites-enabled/000-default.conf + +- name: Create kibana http_auth user + htpasswd: path=/etc/apache2/users name=kibana password={{ kibana_password }} owner=root group=www-data mode=0640 create=yes state=present + +- name: Install Next Gen RPC Dashboard + template: > + src={{ item }} + dest="/opt/kibana/app/dashboards/{{ item }}" + owner=root + group=root + with_items: + - Next-Gen-RPC.json + +- name: Restart Apache + service: name=apache2 state=restarted diff --git a/rpc_deployment/roles/kibana/templates/000-kibana.conf b/rpc_deployment/roles/kibana/templates/000-kibana.conf new file mode 100644 index 0000000000..b606f56d61 --- /dev/null +++ b/rpc_deployment/roles/kibana/templates/000-kibana.conf @@ -0,0 +1,44 @@ + + ServerName {{ kibana_server_name }} + RewriteEngine On + RewriteCond %{HTTPS} !=on + RewriteRule ^/?(.*) https://%{HTTP_HOST}:{{ kibana_ssl_port }}/$1 [R,L] + + + + ServerName {{ kibana_server_name }} + + LogLevel {{ kibana_log_level|default('info') }} + ErrorLog /var/log/apache2/kibana-error.log + CustomLog /var/log/apache2/ssl_access.log combined + Options +FollowSymLinks + + SSLEngine on + SSLCertificateFile {{ kibana_ssl_cert|default('/etc/ssl/certs/apache.cert') }} + SSLCertificateKeyFile {{ kibana_ssl_key|default('/etc/ssl/private/apache.key') }} + SSLCACertificatePath {{ kibana_ssl_cert_path|default('/etc/ssl/certs') }} + SSLCARevocationPath {{ kibana_ssl_cert_path|default('/etc/ssl/certs') }} + SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown + + DocumentRoot {{ kibana_root }} + + + Options FollowSymLinks + AllowOverride None + + + # ElasticSearch Reverse Proxy + + ProxyPass http://{{ hostvars[groups['elasticsearch'][0]]['container_address'] }}:{{ elasticsearch_http_port }}/ + ProxyPassReverse / + + + + Options Indexes FollowSymLinks MultiViews + AllowOverride AuthConfig + AuthType Basic + AuthName Kibana + AuthUserFile /etc/apache2/users + Require user kibana + + diff --git a/rpc_deployment/roles/kibana/templates/Next-Gen-RPC.json b/rpc_deployment/roles/kibana/templates/Next-Gen-RPC.json new file mode 100644 index 0000000000..da60e4a8ae --- /dev/null +++ b/rpc_deployment/roles/kibana/templates/Next-Gen-RPC.json @@ -0,0 +1,470 @@ +{ + "title": "Next Gen RPC", + "services": { + "query": { + "list": { + "0": { + "id": 0, + "color": "#7EB26D", + "alias": "", + "pin": false, + "type": "lucene", + "enable": true, + "query": "tags:neutron*" + }, + "1": { + "id": 1, + "color": "#EAB839", + "alias": "", + "pin": false, + "type": "lucene", + "enable": true, + "query": "tags:cinder*" + }, + "2": { + "id": 2, + "color": "#6ED0E0", + "alias": "", + "pin": false, + "type": "lucene", + "enable": true, + "query": "tags:nova*" + }, + "3": { + "id": 3, + "color": "#EF843C", + "alias": "", + "pin": false, + "type": "lucene", + "enable": true, + "query": "tags:keystone*" + }, + "4": { + "id": 4, + "color": "#E24D42", + "alias": "", + "pin": false, + "type": "lucene", + "enable": true, + "query": "tags:routes*" + }, + "5": { + "id": 5, + "color": "#1F78C1", + "alias": "", + "pin": false, + "type": "lucene", + "enable": true, + "query": "tags:sqlalchemy*" + }, + "6": { + "id": 6, + "color": "#BA43A9", + "alias": "", + "pin": false, + "type": "lucene", + "enable": true, + "query": "tags:rsyslog*" + } + }, + "ids": [ + 2, + 0, + 1, + 3, + 4, + 5, + 6 + ] + }, + "filter": { + "list": { + "0": { + "type": "time", + "field": "@timestamp", + "from": "now-5m", + "to": "now", + "mandate": "must", + "active": true, + "alias": "", + "id": 0 + } + }, + "ids": [ + 0 + ] + } + }, + "rows": [ + { + "title": "Graph", + "height": "350px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "span": 12, + "editable": true, + "group": [ + "default" + ], + "type": "histogram", + "mode": "count", + "time_field": "@timestamp", + "value_field": null, + "auto_int": true, + "resolution": 100, + "interval": "1s", + "fill": 3, + "linewidth": 3, + "timezone": "browser", + "spyable": true, + "zoomlinks": true, + "bars": false, + "stack": false, + "points": false, + "lines": true, + "legend": true, + "x-axis": true, + "y-axis": true, + "percentage": false, + "interactive": true, + "queries": { + "mode": "all", + "ids": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ] + }, + "title": "Events over time", + "intervals": [ + "auto", + "1s", + "1m", + "5m", + "10m", + "30m", + "1h", + "3h", + "12h", + "1d", + "1w", + "1M", + "1y" + ], + "options": true, + "tooltip": { + "value_type": "cumulative", + "query_as_alias": true + }, + "scale": 1, + "y_format": "none", + "grid": { + "max": null, + "min": 0 + }, + "annotate": { + "enable": false, + "query": "*", + "size": 20, + "field": "_type", + "sort": [ + "_score", + "desc" + ] + }, + "pointradius": 5, + "show_query": true, + "legend_counts": true, + "zerofill": true, + "derivative": false + } + ], + "notice": false + }, + { + "title": "Services", + "height": "250px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "error": false, + "span": 4, + "editable": true, + "type": "terms", + "loadingEditor": false, + "field": "os_level", + "exclude": [], + "missing": false, + "other": false, + "size": 10, + "order": "count", + "style": { + "font-size": "10pt" + }, + "donut": true, + "tilt": true, + "labels": true, + "arrangement": "horizontal", + "chart": "pie", + "counter_pos": "above", + "spyable": true, + "queries": { + "mode": "all", + "ids": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ] + }, + "tmode": "terms", + "tstat": "total", + "valuefield": "", + "title": "Level" + }, + { + "error": false, + "span": 4, + "editable": true, + "type": "terms", + "loadingEditor": false, + "field": "os_program", + "exclude": [], + "missing": false, + "other": false, + "size": 10, + "order": "count", + "style": { + "font-size": "10pt" + }, + "donut": true, + "tilt": true, + "labels": true, + "arrangement": "vertical", + "chart": "pie", + "counter_pos": "above", + "spyable": true, + "queries": { + "mode": "all", + "ids": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ] + }, + "tmode": "terms", + "tstat": "total", + "valuefield": "", + "title": "Service" + }, + { + "error": false, + "span": 4, + "editable": true, + "type": "terms", + "loadingEditor": false, + "field": "host.raw", + "exclude": [], + "missing": false, + "other": false, + "size": 10, + "order": "count", + "style": { + "font-size": "10pt" + }, + "donut": true, + "tilt": true, + "labels": true, + "arrangement": "horizontal", + "chart": "pie", + "counter_pos": "above", + "spyable": true, + "queries": { + "mode": "all", + "ids": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ] + }, + "tmode": "terms", + "tstat": "total", + "valuefield": "", + "title": "Logging Host" + } + ], + "notice": false + }, + { + "title": "Events", + "height": "350px", + "editable": true, + "collapse": false, + "collapsable": true, + "panels": [ + { + "title": "All events", + "error": false, + "span": 12, + "editable": true, + "group": [ + "default" + ], + "type": "table", + "size": 100, + "pages": 5, + "offset": 0, + "sort": [ + "@timestamp", + "desc" + ], + "style": { + "font-size": "9pt" + }, + "overflow": "min-height", + "fields": [ + "@timestamp", + "os_program", + "os_level", + "host", + "openstack_message" + ], + "localTime": true, + "timeField": "@timestamp", + "highlight": [], + "sortable": true, + "header": true, + "paging": true, + "spyable": true, + "queries": { + "mode": "all", + "ids": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6 + ] + }, + "field_list": true, + "status": "Stable", + "trimFactor": 300, + "normTimes": true, + "all_fields": false + } + ], + "notice": false + } + ], + "editable": true, + "failover": false, + "index": { + "interval": "day", + "pattern": "[logstash-]YYYY.MM.DD", + "default": "NO_TIME_FILTER_OR_INDEX_PATTERN_NOT_MATCHED", + "warm_fields": true + }, + "style": "dark", + "panel_hints": true, + "pulldowns": [ + { + "type": "query", + "collapse": true, + "notice": false, + "query": "*", + "pinned": true, + "history": [ + "tags:rsyslog*", + "tags:sqlalchemy*", + "tags:routes*", + "tags:keystone*", + "tags:nova*", + "tags:cinder*", + "tags:neutron*", + "tags:neutron", + "*", + "" + ], + "remember": 10, + "enable": true + }, + { + "type": "filtering", + "collapse": false, + "notice": true, + "enable": true + } + ], + "nav": [ + { + "type": "timepicker", + "collapse": false, + "notice": false, + "status": "Stable", + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ], + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "timefield": "@timestamp", + "now": true, + "filter_id": 0, + "enable": true + } + ], + "loader": { + "save_gist": false, + "save_elasticsearch": true, + "save_local": true, + "save_default": true, + "save_temp": true, + "save_temp_ttl_enable": true, + "save_temp_ttl": "30d", + "load_gist": true, + "load_elasticsearch": true, + "load_elasticsearch_size": 20, + "load_local": true, + "hide": false + }, + "refresh": false +} \ No newline at end of file diff --git a/rpc_deployment/roles/kibana/templates/apache2.conf b/rpc_deployment/roles/kibana/templates/apache2.conf new file mode 100644 index 0000000000..c5d6d91cee --- /dev/null +++ b/rpc_deployment/roles/kibana/templates/apache2.conf @@ -0,0 +1,218 @@ +# This is the main Apache server configuration file. It contains the +# configuration directives that give the server its instructions. +# See http://httpd.apache.org/docs/2.4/ for detailed information about +# the directives and /usr/share/doc/apache2/README.Debian about Debian specific +# hints. +# +# +# Summary of how the Apache 2 configuration works in Debian: +# The Apache 2 web server configuration in Debian is quite different to +# upstream's suggested way to configure the web server. This is because Debian's +# default Apache2 installation attempts to make adding and removing modules, +# virtual hosts, and extra configuration directives as flexible as possible, in +# order to make automating the changes and administering the server as easy as +# possible. + +# It is split into several files forming the configuration hierarchy outlined +# below, all located in the /etc/apache2/ directory: +# +# /etc/apache2/ +# |-- apache2.conf +# | `-- ports.conf +# |-- mods-enabled +# | |-- *.load +# | `-- *.conf +# |-- conf-enabled +# | `-- *.conf +# `-- sites-enabled +# `-- *.conf +# +# +# * apache2.conf is the main configuration file (this file). It puts the pieces +# together by including all remaining configuration files when starting up the +# web server. +# +# * ports.conf is always included from the main configuration file. It is +# supposed to determine listening ports for incoming connections which can be +# customized anytime. +# +# * Configuration files in the mods-enabled/, conf-enabled/ and sites-enabled/ +# directories contain particular configuration snippets which manage modules, +# global configuration fragments, or virtual host configurations, +# respectively. +# +# They are activated by symlinking available configuration files from their +# respective *-available/ counterparts. These should be managed by using our +# helpers a2enmod/a2dismod, a2ensite/a2dissite and a2enconf/a2disconf. See +# their respective man pages for detailed information. +# +# * The binary is called apache2. Due to the use of environment variables, in +# the default configuration, apache2 needs to be started/stopped with +# /etc/init.d/apache2 or apache2ctl. Calling /usr/bin/apache2 directly will not +# work with the default configuration. + + +# Global configuration +# + +# +# ServerRoot: The top of the directory tree under which the server's +# configuration, error, and log files are kept. +# +# NOTE! If you intend to place this on an NFS (or otherwise network) +# mounted filesystem then please read the Mutex documentation (available +# at ); +# you will save yourself a lot of trouble. +# +# Do NOT add a slash at the end of the directory path. +# +#ServerRoot "/etc/apache2" + +# +# The accept serialization lock file MUST BE STORED ON A LOCAL DISK. +# +Mutex file:${APACHE_LOCK_DIR} default + +# +# PidFile: The file in which the server should record its process +# identification number when it starts. +# This needs to be set in /etc/apache2/envvars +# +PidFile ${APACHE_PID_FILE} + +# +# Timeout: The number of seconds before receives and sends time out. +# +Timeout 300 + +# +# KeepAlive: Whether or not to allow persistent connections (more than +# one request per connection). Set to "Off" to deactivate. +# +KeepAlive On + +# +# MaxKeepAliveRequests: The maximum number of requests to allow +# during a persistent connection. Set to 0 to allow an unlimited amount. +# We recommend you leave this number high, for maximum performance. +# +MaxKeepAliveRequests 100 + +# +# KeepAliveTimeout: Number of seconds to wait for the next request from the +# same client on the same connection. +# +KeepAliveTimeout 5 + + +# These need to be set in /etc/apache2/envvars +User ${APACHE_RUN_USER} +Group ${APACHE_RUN_GROUP} + +# +# HostnameLookups: Log the names of clients or just their IP addresses +# e.g., www.apache.org (on) or 204.62.129.132 (off). +# The default is off because it'd be overall better for the net if people +# had to knowingly turn this feature on, since enabling it means that +# each client request will result in AT LEAST one lookup request to the +# nameserver. +# +HostnameLookups Off + +# ErrorLog: The location of the error log file. +# If you do not specify an ErrorLog directive within a +# container, error messages relating to that virtual host will be +# logged here. If you *do* define an error logfile for a +# container, that host's errors will be logged there and not here. +# +ErrorLog ${APACHE_LOG_DIR}/error.log + +# +# LogLevel: Control the severity of messages logged to the error_log. +# Available values: trace8, ..., trace1, debug, info, notice, warn, +# error, crit, alert, emerg. +# It is also possible to configure the log level for particular modules, e.g. +# "LogLevel info ssl:warn" +# +LogLevel warn + +# Include module configuration: +IncludeOptional mods-enabled/*.load +IncludeOptional mods-enabled/*.conf + +# Include list of ports to listen on +Include ports.conf + + +# Sets the default security model of the Apache2 HTTPD server. It does +# not allow access to the root filesystem outside of /usr/share and /var/www. +# The former is used by web applications packaged in Debian, +# the latter may be used for local directories served by the web server. If +# your system is serving content from a sub-directory in /srv you must allow +# access here, or in any related virtual host. + + Options FollowSymLinks + AllowOverride None + Require all denied + + + + AllowOverride None + Require all granted + + + + Options Indexes FollowSymLinks + AllowOverride None + Require all granted + + + + Options Indexes FollowSymLinks + AllowOverride None + Require all granted + + +# AccessFileName: The name of the file to look for in each directory +# for additional configuration directives. See also the AllowOverride +# directive. +# +AccessFileName .htaccess + +# +# The following lines prevent .htaccess and .htpasswd files from being +# viewed by Web clients. +# + + Require all denied + + + +# +# The following directives define some format nicknames for use with +# a CustomLog directive. +# +# These deviate from the Common Log Format definitions in that they use %O +# (the actual bytes sent including headers) instead of %b (the size of the +# requested file), because the latter makes it impossible to detect partial +# requests. +# +# Note that the use of %{X-Forwarded-For}i instead of %h is not recommended. +# Use mod_remoteip instead. +# +LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined +LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined +LogFormat "%h %l %u %t \"%r\" %>s %O" common +LogFormat "%{Referer}i -> %U" referer +LogFormat "%{User-agent}i" agent + +# Include of directories ignores editors' and dpkg's backup files, +# see README.Debian for details. + +# Include generic snippets of statements +IncludeOptional conf-enabled/*.conf + +# Include the virtual host configurations: +IncludeOptional sites-enabled/*.conf + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/rpc_deployment/roles/kibana/templates/config.js b/rpc_deployment/roles/kibana/templates/config.js new file mode 100644 index 0000000000..1d41d3a4f3 --- /dev/null +++ b/rpc_deployment/roles/kibana/templates/config.js @@ -0,0 +1,81 @@ +/** @scratch /configuration/config.js/1 + * + * == Configuration + * config.js is where you will find the core Kibana configuration. This file contains parameter that + * must be set before kibana is run for the first time. + */ +define(['settings'], +function (Settings) { + + + /** @scratch /configuration/config.js/2 + * + * === Parameters + */ + return new Settings({ + + /** @scratch /configuration/config.js/5 + * + * ==== elasticsearch + * + * The URL to your elasticsearch server. You almost certainly don't + * want +http://localhost:9200+ here. Even if Kibana and Elasticsearch are on + * the same host. By default this will attempt to reach ES at the same host you have + * kibana installed on. You probably want to set it to the FQDN of your + * elasticsearch host + * + * Note: this can also be an object if you want to pass options to the http client. For example: + * + * +elasticsearch: {server: "http://localhost:9200", withCredentials: true}+ + * + */ + /* elasticsearch: "http://{{ elasticsearch_vip }}:{{ elasticsearch_http_port }}/", */ + elasticsearch: "https://{{ external_vip_address }}:8443/elasticsearch/", + + /** @scratch /configuration/config.js/5 + * + * ==== default_route + * + * This is the default landing page when you don't specify a dashboard to load. You can specify + * files, scripts or saved dashboards here. For example, if you had saved a dashboard called + * `WebLogs' to elasticsearch you might use: + * + * default_route: '/dashboard/elasticsearch/WebLogs', + */ + default_route : '/dashboard/file/Next-Gen-RPC.json', + + /** @scratch /configuration/config.js/5 + * + * ==== kibana-int + * + * The default ES index to use for storing Kibana specific object + * such as stored dashboards + */ + kibana_index: "kibana-int", + + /** @scratch /configuration/config.js/5 + * + * ==== panel_name + * + * An array of panel modules available. Panels will only be loaded when they are defined in the + * dashboard, but this list is used in the "add panel" interface. + */ + panel_names: [ + 'histogram', + 'map', + 'goal', + 'table', + 'filtering', + 'timepicker', + 'text', + 'hits', + 'column', + 'trends', + 'bettermap', + 'query', + 'terms', + 'stats', + 'sparklines' + ] + }); +}); diff --git a/rpc_deployment/roles/kibana/templates/ports.conf b/rpc_deployment/roles/kibana/templates/ports.conf new file mode 100644 index 0000000000..bb8601afc7 --- /dev/null +++ b/rpc_deployment/roles/kibana/templates/ports.conf @@ -0,0 +1,13 @@ +# If you just change the port or add more ports here, you will likely also +# have to change the VirtualHost statement in +# /etc/apache2/sites-enabled/000-default.conf + +Listen 80 + + + Listen {{ kibana_ssl_port }} + + + + Listen {{ kibana_ssl_port }} + diff --git a/rpc_deployment/roles/logging_common/tasks/main.yml b/rpc_deployment/roles/logging_common/tasks/main.yml new file mode 100644 index 0000000000..bc0f82f734 --- /dev/null +++ b/rpc_deployment/roles/logging_common/tasks/main.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Install OpenJDK + apt: + pkg: openjdk-7-jre + state: latest + update_cache: yes diff --git a/rpc_deployment/roles/logstash/tasks/main.yml b/rpc_deployment/roles/logstash/tasks/main.yml new file mode 100644 index 0000000000..f49429e6ab --- /dev/null +++ b/rpc_deployment/roles/logstash/tasks/main.yml @@ -0,0 +1,54 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Logstash Setup + template: > + src={{ item }} + dest=/etc/logstash/conf.d/{{ item }} + owner=root + group=root + register: results + with_items: + - 01-input.conf + - 02-rsyslog.conf + - 03-generic.conf + - 04-routes.conf + - 05-cinder.conf + - 06-nova.conf + - 07-sqlalchemy.conf + - 99-output.conf + +- name: Logstash Extra Patterns + template: > + src={{ item }} + dest=/opt/logstash/patterns/{{ item }} + owner=logstash + group=logstash + register: results + with_items: + - extras + +- name: Logstash Tuning + template: > + src={{ item }} + dest=/etc/default/{{ item }} + owner=root + group=root + register: results + with_items: + - logstash + +- name: restart logstash + service: name=logstash state=restarted pattern=logstash diff --git a/rpc_deployment/roles/logstash/templates/01-input.conf b/rpc_deployment/roles/logstash/templates/01-input.conf new file mode 100644 index 0000000000..da4644462f --- /dev/null +++ b/rpc_deployment/roles/logstash/templates/01-input.conf @@ -0,0 +1,8 @@ +#=============================================================================== +input { + syslog { + port => {{ logstash_port }} + codec => json + } +} +#=============================================================================== diff --git a/rpc_deployment/roles/logstash/templates/02-rsyslog.conf b/rpc_deployment/roles/logstash/templates/02-rsyslog.conf new file mode 100644 index 0000000000..5cc959c1e1 --- /dev/null +++ b/rpc_deployment/roles/logstash/templates/02-rsyslog.conf @@ -0,0 +1,23 @@ +filter { + # Look for rsyslog in the program name and tag it as such, otherwise it's an openstack log. + if [@fields][program] =~ /rsyslogd*/ { + mutate { + add_tag => [ "rsyslogd" ] + add_field => { + "os_program" => "rsyslogd" + "openstack_message" => "%{@message}" + "os_level" => "%{severity_label}" + } + remove_tag => [ "_grokparsefailure" ] + } + } + #--------------------------------------------------------------------------- + # Parse & tag generic openstack log message + else { + grok { + match => { "@fields[program]" => "%{CONTAINER_STRIP:os_program}" } + remove_tag => [ "_grokparsefailure" ] + add_tag => [ "_parse_start", "%{os_program}", "openstack-generic" ] + } + } +} diff --git a/rpc_deployment/roles/logstash/templates/03-generic.conf b/rpc_deployment/roles/logstash/templates/03-generic.conf new file mode 100644 index 0000000000..b3fb6defcf --- /dev/null +++ b/rpc_deployment/roles/logstash/templates/03-generic.conf @@ -0,0 +1,122 @@ +#=============================================================================== +filter { + #--------------------------------------------------------------------------- + # Parse & tag generic openstack log message + grok { + match => { "@message" => "%{TIMESTAMP_ISO8601:os_timestamp} %{POSINT:os_program_pid} %{AUDITLOGLEVEL:os_level} %{OPENSTACK_FUNCTION:openstack_function} %{OPENSTACK_CODE:openstack_code} %{GREEDYDATA:openstack_message}" } +# add_tag => [ "openstack-generic" ] + break_on_match => false + tag_on_failure => [] + } + #--------------------------------------------------------------------------- + # Parse & tag specific openstack project log messages + if "openstack-generic" in [tags] { + #--------------------------------------------------------------------------- + # Parse & tag multiline logs where subsequent lines are added to the original, previous line +# multiline { +# pattern => "^(([0-9]+-(?:0?[1-9]|1[0-2])-(?:3[01]|[1-2]?[0-9]|0?[1-9]))|((?:0?[1-9]|1[0-2])/(?:3[01]|[1-2]?[0-9]|0?[1-9]))).*$" +# negate => true +# what => "previous" +# } + #----------------------------------------------------------------------- + # Parse & tag generic nova logs + # i.e.: + # 1) nova-api-os-compute.log: nova.osapi_compute.wsgi.server [-] (11093) accepted ('192.168.1.100', 53437) + # 2) nova-compute.log: nova.compute.resource_tracker [-] Auditing locally available compute resources + grok { + match => ["os_program", "nova.%{GREEDYDATA:os_program_path}"] + add_tag => [ "nova-generic" ] + break_on_match => false + tag_on_failure => [] + } + #----------------------------------------------------------------------- + # Parse & tag generic keystoneclient logs (as used by nova) + # i.e.: + # 1) nova-api-os-compute.log: keystonemiddleware.auth_token [-] Using /tmp/keystone-signing-FI3PTe as cache directory for signing certificate + grok { + match => ["os_program", "keystonemiddleware.%{GREEDYDATA:os_program_path}"] + add_tag => [ "keystoneclient-generic" ] + break_on_match => false + tag_on_failure => [] + } + #----------------------------------------------------------------------- + # Parse & tag generic keystone logs + # i.e.: + # 1) keystone.log: keystone.common.controller [-] RBAC: Bypassing authorization + # 2) keystone.log: keystone-all [-] Configuration options gathered from: log_opt_values /usr/lib/python2.7/dist-packages/oslo/config/cfg.py:1929 + grok { + match => ["os_program", "keystone[.-]%{GREEDYDATA:os_program_path}"] + add_tag => [ "keystone-generic" ] + break_on_match => false + tag_on_failure => [] + } + #----------------------------------------------------------------------- + # Parse & tag generic routes logs (as used by keystone & nova) + # i.e.: + # 1) keystone.log: routes.middleware [-] Initialized with method overriding = True, and path info altering = True __init__ /usr/lib/python2.7/dist-packages/routes/middleware.py:41 + # 2) keystone.log: routes.middleware [-] Matched GET /tenants __call__ /usr/lib/python2.7/dist-packages/routes/middleware.py:100 + grok { + match => ["os_program", "routes[.-]%{GREEDYDATA:os_program_path}"] + add_tag => [ "routes-generic" ] + break_on_match => false + tag_on_failure => [] + } + #----------------------------------------------------------------------- + # Parse & tag generic sqlalchemy logs (as used by keystone) + # i.e.: + # 1) keystone.log: 2014-06-10 13:41:24.789 18755 INFO sqlalchemy.engine.base.Engine [-] ('default',) + grok { + match => ["os_program", "sqlalchemy.%{GREEDYDATA:os_program_path}"] + add_tag => [ "sqlalchemy-generic" ] + break_on_match => false + tag_on_failure => [] + } + #----------------------------------------------------------------------- + # Parse & tag generic cinder logs + # i.e.: + # 1) cinder.log: 2014-06-11 16:00:30.546 4131 INFO cinder.api.openstack.wsgi [-] http://10.127.26.62:8776/ returned with HTTP 200 + grok { + match => ["os_program", "cinder.%{GREEDYDATA:os_program_path}"] + add_tag => [ "cinder-generic" ] + break_on_match => false + tag_on_failure => [] + } + #----------------------------------------------------------------------- + # Parse & tag generic neutron logs + # i.e.: + # 1) neutron.log: 2014-06-11 16:00:30.546 4131 INFO cinder.api.openstack.wsgi [-] http://10.127.26.62:8776/ returned with HTTP 200 + grok { + match => ["os_program", "neutron.%{GREEDYDATA:os_program_path}"] + add_tag => [ "neutron-generic" ] + break_on_match => false + tag_on_failure => [] + } + #----------------------------------------------------------------------- + # Parse & tag generic glance logs + # i.e.: + # 1) neutron.log: 2014-06-11 16:00:30.546 4131 INFO cinder.api.openstack.wsgi [-] http://10.127.26.62:8776/ returned with HTTP 200 + grok { + match => ["os_program", "glance.%{GREEDYDATA:os_program_path}"] + add_tag => [ "glance-generic" ] + break_on_match => false + tag_on_failure => [] + } + + #----------------------------------------------------------------------- + # Generic Apache log (primarily GET/POST requests as seen in keystone) + # i.e.: + # 1) 192.168.1.100 - - [10/Jun/2014:11:43:14 +0000] "POST http://192.168.1.100:5000/v2.0/tokens HTTP/1.0" 200 8374 + grok { + match => [ + "message", "%{COMMONAPACHELOG}" + ] + add_tag => [ "generic-apache-request" ] + break_on_match => false + remove_field => ["message"] # overwrites original message with whats left + tag_on_failure => [] + } + #----------------------------------------------------------------------- + } + #--------------------------------------------------------------------------- +} +#=============================================================================== diff --git a/rpc_deployment/roles/logstash/templates/04-routes.conf b/rpc_deployment/roles/logstash/templates/04-routes.conf new file mode 100644 index 0000000000..6cfc9b1dcb --- /dev/null +++ b/rpc_deployment/roles/logstash/templates/04-routes.conf @@ -0,0 +1,73 @@ +#=============================================================================== +filter { + #--------------------------------------------------------------------------- + # Parse & tag routes logs (as used by keystone & nova) + if "routes-generic" in [tags] { + #----------------------------------------------------------------------- + # routes GET requests i.e.: + # 1) keystone.log: Matched GET /tenants __call__ /usr/lib/python2.7/dist-packages/routes/middleware.py:100 + # 2) keystone.log: Matched GET /users __call__ /usr/lib/python2.7/dist-packages/routes/middleware.py:100 + # 3) keystone.log: Matched GET /tenants/47942f2dc60d4b88804b8573c0e78d7e/users __call__ /usr/lib/python2.7/dist-packages/routes/middleware.py:100 + # 4) keystone.log: Matched GET /tenants/47942f2dc60d4b88804b8573c0e78d7e/users/29f569a2066745659b4fb080ff3b5a67/roles # __call__ /usr/lib/python2.7/dist-packages/routes/middleware.py:100 + # 5) keystone.log: Matched GET /users/965fbe7ab90d4b1b912f85d4eb34d1cd/credentials/OS-EC2 __call__ # # /usr/lib/python2.7/dist-packages/routes/middleware.py:100 + grok { + match => [ + "@message", "GET /%{DATA:api_func}(/%{DATA:api_func_path})? %{GREEDYDATA:message}" + ] + add_tag => [ "routes-get-request" ] + break_on_match => false + overwrite => ["message"] # overwrites original message with whats left + tag_on_failure => [] + } + #----------------------------------------------------------------------- + if "routes-get-request" in [tags] { + #------------------------------------------------------------------- + # Tenants GET requests i.e.: + # 1) keystone.log: Matched GET /tenants/47942f2dc60d4b88804b8573c0e78d7e/users __call__ /usr/lib/python2.7/dist-packages/routes/middleware.py:100 + # 2) keystone.log: Matched GET /tenants/47942f2dc60d4b88804b8573c0e78d7e/users/29f569a2066745659b4fb080ff3b5a67/roles # __call__ /usr/lib/python2.7/dist-packages/routes/middleware.py:100 + if [api_func] == "tenants" { + grok { + match => [ + "api_func_path", "%{WORD:tenant_id}/%{WORD:tenant_func}(/%{WORD:user_id}/%{WORD:user_func})?" + ] + add_tag => [ "routes-tenants-get-request" ] + break_on_match => false + remove_field => ["api_func_path"] + tag_on_failure => [] + } + } + #------------------------------------------------------------------- + # Users GET requests i.e.: + # 1) Matched GET /users/965fbe7ab90d4b1b912f85d4eb34d1cd/credentials/OS-EC2 __call__ # # /usr/lib/python2.7/dist-packages/routes/middleware.py:100 + if [api_func] == "users" { + grok { + match => [ + "api_func_path", "%{WORD:user_id}/%{WORD:user_func}(/%{PROG:user_func_detail})?" + ] + add_tag => [ "routes-users-get-request" ] + break_on_match => false + remove_field => ["api_func_path"] + tag_on_failure => [] + } + } + #------------------------------------------------------------------- + } + #----------------------------------------------------------------------- + # Parse & tag routes POST requests + #----------------------------------------------------------------------- + # routes POSTS requests i.e.: + # 1) routes.middleware [-] Matched POST /tokens __call__ /usr/lib/python2.7/dist-packages/routes/middleware.py:100 + grok { + match => [ + "@message", "POST /%{DATA:api_func} %{GREEDYDATA:message}" + ] + add_tag => [ "routes-post-request" ] + break_on_match => false + overwrite => ["message"] # overwrites original message with whats left + tag_on_failure => [] + } + #----------------------------------------------------------------------- + } + #--------------------------------------------------------------------------- +} +#=============================================================================== diff --git a/rpc_deployment/roles/logstash/templates/05-cinder.conf b/rpc_deployment/roles/logstash/templates/05-cinder.conf new file mode 100644 index 0000000000..c14df967e0 --- /dev/null +++ b/rpc_deployment/roles/logstash/templates/05-cinder.conf @@ -0,0 +1,40 @@ +#=============================================================================== +filter { + #--------------------------------------------------------------------------- + # Parse & tag cinder logs + if "cinder-generic" in [tags] { + #----------------------------------------------------------------------- + # Parse & tag cinder request-id's + # i.e.: + # 1) 2014-06-11 16:00:36.270 4131 AUDIT cinder.api.v1.volumes [req-6d007686-a7d7-4252-912a-0cb224dc148f 3701c870aea549039fdeb22a3ec36864 e77cc2a25f004ec099497d95f02f96dd] ... + grok { + match => ["@message", "\[req-%{UUID:request_id} %{WORD:request_user_id} %{WORD:request_tenant_id}\] %{GREEDYDATA:message}"] + add_tag => [ "cinder-request-id" ] + break_on_match => false + overwrite => ["message"] # overwrites original message with whats left + tag_on_failure => [] + } + #----------------------------------------------------------------------- + # Parse & tag volume info from 'message' field in cinder-request-id + if "cinder-request-id" in [tags] { + grok { + match => ["@message", "vol=%{GREEDYDATA:vol}"] + add_tag => [ "cinder-request-volume-info" ] + break_on_match => false + remove_field => ["message"] # overwrites original message with whats left + tag_on_failure => [] + } + if "cinder-request-volume-info" not in [tags] { + grok { + match => ["@message", "%{GREEDYDATA:message}"] + add_tag => [ "cinder-action" ] + break_on_match => false + overwrite => ["message"] # overwrites original message with whats left + tag_on_failure => [] + } + } + } + #----------------------------------------------------------------------- + } +} +#=============================================================================== diff --git a/rpc_deployment/roles/logstash/templates/06-nova.conf b/rpc_deployment/roles/logstash/templates/06-nova.conf new file mode 100644 index 0000000000..0e9e489822 --- /dev/null +++ b/rpc_deployment/roles/logstash/templates/06-nova.conf @@ -0,0 +1,65 @@ +#=============================================================================== +filter { + #--------------------------------------------------------------------------- + # Parse & tag nova logs + if "nova-generic" in [tags] { + #----------------------------------------------------------------------- + # Parse & tag nova request-id's + # i.e.: + # 1) nova-api-os-compute.log: nova.osapi_compute.wsgi.server [req-264fe290-42c6-4252-9a87-c20685d360f1 23101739b41842babf322615686cdbf9 d6a76ef3d2a54fbbbdcf7694e4900c5d] 192.168.1.100 "GET /v2/d6a76ef3d2a54fbbbdcf7694e4900c5d/flavors/detail HTTP/1.1" status: 200 len: 2273 time: 0.1098659 + grok { + match => ["@message", "\[req-%{UUID:request_id} %{WORD:request_user_id} %{WORD:request_tenant_id}\] %{GREEDYDATA:message}"] + add_tag => [ "nova-request-id" ] + break_on_match => false + overwrite => ["message"] # overwrites original message with whats left + tag_on_failure => [] + } + #----------------------------------------------------------------------- + # Parse & tag nova HTTP GET requests + # i.e.: + # 1) nova-api-os-compute.log: nova.osapi_compute.wsgi.server [req-264fe290-42c6-4252-9a87-c20685d360f1 23101739b41842babf322615686cdbf9 d6a76ef3d2a54fbbbdcf7694e4900c5d] 192.168.1.100 "GET /v2/d6a76ef3d2a54fbbbdcf7694e4900c5d/flavors/detail HTTP/1.1" status: 200 len: 2273 time: 0.1098659 + grok { + match => [ + "@message", "GET (/v%{NUMBER:api_version})?/%{WORD:tenant_id}/%{DATA:api_func}(/%{DATA:api_func_path})? %{GREEDYDATA:message}" + ] + add_tag => [ "nova-get-request" ] + break_on_match => false + overwrite => ["message"] # overwrites original message with whats left + tag_on_failure => [] + } + #----------------------------------------------------------------------- + # Parse & tag nova HTTP POST requests + # i.e.: + # 1) nova-api-os-compute.log: nova.osapi_compute.wsgi.server [req-1020ef31-7c3f-4ae9-a156-d04cbff43026 44aecbd3d6e34b90a8c2028c5352175b e8ca4ebd592b4e20861c5a06813d3c78] 192.168.1.100 "POST /v2/e8ca4ebd592b4e20861c5a06813d3c78/servers HTTP/1.1" status: 202 len: 739 time: 0.6813190 + grok { + match => [ + "@message", "POST (/v%{NUMBER:api_version})?/%{WORD:tenant_id}/%{DATA:api_func}(/%{DATA:api_func_path})? %{GREEDYDATA:message}" + ] + add_tag => [ "nova-post-request" ] + break_on_match => false + overwrite => ["message"] # overwrites original message with whats left + tag_on_failure => [] + } + #----------------------------------------------------------------------- + # Parse & tag nova HTTP info from GET & POST requests + if "nova-get-request" in [tags] or "nova-post-request" in [tags] { + #------------------------------------------------------------------- + # Generic HTTP info i.e.: + # 1) nova-api-os-compute.log: nova.osapi_compute.wsgi.server [req-264fe290-42c6-4252-9a87-c20685d360f1 23101739b41842babf322615686cdbf9 d6a76ef3d2a54fbbbdcf7694e4900c5d] 192.168.1.100 "GET /v2/d6a76ef3d2a54fbbbdcf7694e4900c5d/flavors/detail HTTP/1.1" status: 200 len: 2273 time: 0.1098659 + # 2) nova-api-os-compute.log: nova.osapi_compute.wsgi.server [req-1020ef31-7c3f-4ae9-a156-d04cbff43026 44aecbd3d6e34b90a8c2028c5352175b e8ca4ebd592b4e20861c5a06813d3c78] 192.168.1.100 "POST /v2/e8ca4ebd592b4e20861c5a06813d3c78/servers HTTP/1.1" status: 202 len: 739 time: 0.6813190 + grok { + match => [ + "@message", 'HTTP/%{NUMBER:httpversion}\" status: %{NUMBER:response} len: %{NUMBER:bytes} time: %{NUMBER:httptime}' + ] + add_tag => [ "nova-http-request" ] + remove_field => ["message"] + break_on_match => false + tag_on_failure => [] + } + #------------------------------------------------------------------- + } + #----------------------------------------------------------------------- + } + #--------------------------------------------------------------------------- +} +#=============================================================================== diff --git a/rpc_deployment/roles/logstash/templates/07-sqlalchemy.conf b/rpc_deployment/roles/logstash/templates/07-sqlalchemy.conf new file mode 100644 index 0000000000..7162b52918 --- /dev/null +++ b/rpc_deployment/roles/logstash/templates/07-sqlalchemy.conf @@ -0,0 +1,28 @@ +#=============================================================================== +filter { + #--------------------------------------------------------------------------- + # Parse & tag generic sqlalchemy logs (as used by keystone) + if "sqlalchemy-generic" in [tags] { + #----------------------------------------------------------------------- + grok { + match => [ + "@message", "('%{WORD:sqlalchemy_id}', %{DATA:expires}, '%{DATA:extra}', %{NUMBER:valid}, '%{WORD:user_id}', (')?%{WORD:trust_id}(')?)" + ] + add_tag => [ "sqlalchemy-issued-token" ] + break_on_match => false + remove_field => ["message"] + tag_on_failure => [] + } + #----------------------------------------------------------------------- + # Parse & tag json from 'extra' field in sqlalchemy-issued-token + if "sqlalchemy-issued-token" in [tags] { + json { + source => "extra" + add_tag => "token-extra-json" + } + } + #----------------------------------------------------------------------- + } + #--------------------------------------------------------------------------- +} +#=============================================================================== diff --git a/rpc_deployment/roles/logstash/templates/99-output.conf b/rpc_deployment/roles/logstash/templates/99-output.conf new file mode 100644 index 0000000000..3214e08517 --- /dev/null +++ b/rpc_deployment/roles/logstash/templates/99-output.conf @@ -0,0 +1,10 @@ +#=============================================================================== +output { + elasticsearch { + host => '{{ hostvars[groups['elasticsearch'][0]]['container_address'] }}' + port => '{{ elasticsearch_tcp_port }}' + protocol => '{{ elasticsearch_mode }}' + cluster => '{{ elasticsearch_cluster }}' + } +} +#=============================================================================== diff --git a/rpc_deployment/roles/logstash/templates/extras b/rpc_deployment/roles/logstash/templates/extras new file mode 100644 index 0000000000..f87c54923c --- /dev/null +++ b/rpc_deployment/roles/logstash/templates/extras @@ -0,0 +1,15 @@ +AUDITLOGLEVEL ([C|c]ritical|CRITICAL[A|a]udit|AUDIT|[D|d]ebug|DEBUG|[N|n]otice|NOTICE|[I|i]nfo|INFO|[W|w]arn?(?:ing)?|WARN?(?:ING)?|[E|e]rr?(?:or)?|ERR?(?:OR)?|[C|c]rit?(?:ical)?|CRIT?(?:ICAL)?|[F|f]atal|FATAL|[S|s]evere|SEVERE|TRACE|[T|t]race) + +APACHE_LOG_LEVEL (?:emerg|alert|crit|error|warn|notice|info|debug) + +APACHE_DATETIME_ERROR %{DAY} %{MONTH} %{MONTHDAY} %{TIME} %{YEAR} + +RABBITMQ_DATE %{MONTHDAY}-%{MONTH}-%{YEAR}::%{TIME} + +RSYSLOG_DATE %{MONTH} %{MONTHDAY} %{TIME} + +OPENSTACK_FUNCTION ((?:\w+)\.?)+ + +OPENSTACK_CODE (?:\[.*\]) + +CONTAINER_STRIP (?:(\w+)(?=_container-\S+)) diff --git a/rpc_deployment/roles/logstash/templates/logstash b/rpc_deployment/roles/logstash/templates/logstash new file mode 100644 index 0000000000..4892afe67e --- /dev/null +++ b/rpc_deployment/roles/logstash/templates/logstash @@ -0,0 +1,42 @@ +############################### +# Default settings for logstash +############################### + +# Override Java location +#JAVACMD=/usr/bin/java + +# Set a home directory +#LS_HOME=/var/lib/logstash + +# Arguments to pass to logstash agent +LS_OPTS="-w 40 --verbose" + +# Arguments to pass to java +{% set host_ram = hostvars[inventory_hostname]['ansible_memtotal_mb']|int * 0.5 %} +{% set host_ram_int = host_ram // 1 %} +{% if host_ram > 16384 %} +LS_HEAP_SIZE=16g +{% else %} +LS_HEAP_SIZE={{ host_ram_int|int }}m +{% endif %} + +#LS_JAVA_OPTS="-Djava.io.tmpdir=$HOME" + +# pidfiles aren't used for upstart; this is for sysv users. +#LS_PIDFILE=/var/run/logstash.pid + +# user id to be invoked as; for upstart: edit /etc/init/logstash.conf +#LS_USER=logstash + +# logstash logging +#LS_LOG_FILE=/var/log/logstash/logstash.log +#LS_USE_GC_LOGGING="true" + +# logstash configuration directory +#LS_CONF_DIR=/etc/logstash/conf.d + +# Open file limit; cannot be overridden in upstart +#LS_OPEN_FILES=16384 + +# Nice level +#LS_NICE=19 diff --git a/rpc_deployment/roles/lxc_common/files/lxc-openstack b/rpc_deployment/roles/lxc_common/files/lxc-openstack new file mode 100644 index 0000000000..0c48cd3c25 --- /dev/null +++ b/rpc_deployment/roles/lxc_common/files/lxc-openstack @@ -0,0 +1,25 @@ +# Do not load this file. Rather, load /etc/apparmor.d/lxc-containers, which +# will source all profiles under /etc/apparmor.d/lxc + +profile lxc-openstack flags=(attach_disconnected,mediate_deleted) { + #include + +# allow standard blockdevtypes. +# The concern here is in-kernel superblock parsers bringing down the +# host with bad data. However, we continue to disallow proc, sys, securityfs, +# etc to nonstandard locations. + mount fstype=ext* -> /**, + mount fstype=nbd* -> /**, + mount fstype=xfs -> /**, + mount fstype=btrfs -> /**, + mount fstype=vfat* -> /**, + mount fstype=fuseblk -> /**, + mount fstype=nbd* -> /**, + mount fstype=devpts, + +# allow System access. + mount fstype=cgroup -> /sys/fs/cgroup/**, + mount fstype=proc -> /var/cache/lxc/**, + mount fstype=sysfs -> /var/cache/lxc/**, + mount options=(rw,bind) /var/cache/lxc/**/dev/shm/ -> /var/cache/lxc/**/run/shm/, +} \ No newline at end of file diff --git a/rpc_deployment/roles/lxc_common/handlers/main.yml b/rpc_deployment/roles/lxc_common/handlers/main.yml new file mode 100644 index 0000000000..9d065a05d7 --- /dev/null +++ b/rpc_deployment/roles/lxc_common/handlers/main.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Reindex apparmor profiles for lxc + shell: "apparmor_parser -Kr /etc/apparmor.d/lxc-containers && service apparmor restart" diff --git a/rpc_deployment/roles/lxc_common/tasks/lxc_container_cache.yml b/rpc_deployment/roles/lxc_common/tasks/lxc_container_cache.yml new file mode 100644 index 0000000000..105167b9be --- /dev/null +++ b/rpc_deployment/roles/lxc_common/tasks/lxc_container_cache.yml @@ -0,0 +1,32 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Download lxc cache + get_url: > + url="{{ rpc_repo_url }}/rpc-trusty-container.tgz" + dest=/var/cache/lxc/rpc-trusty-container.tgz + mode=0440 + register: cache_download + async: 600 + poll: 15 + retries: 3 + until: cache_download|success + +- name: Move lxc cached image into place + unarchive: > + src=/var/cache/lxc/rpc-trusty-container.tgz + dest=/var/cache/lxc/ + copy=no + when: cache_download|changed diff --git a/rpc_deployment/roles/lxc_common/tasks/lxc_host_setup.yml b/rpc_deployment/roles/lxc_common/tasks/lxc_host_setup.yml new file mode 100644 index 0000000000..6d3d964a1e --- /dev/null +++ b/rpc_deployment/roles/lxc_common/tasks/lxc_host_setup.yml @@ -0,0 +1,37 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: set base lxc template + template: > + src={{ item.src }} + dest={{ item.dest }} + owner=root + group=root + mode={{ item.mode }} + with_items: + - { src: lxc-rpc.conf, dest: "/etc/lxc/lxc-rpc.conf", mode: "0644" } + - { src: lxc-rpc, dest: "/usr/share/lxc/templates/lxc-rpc", mode: "0755" } + +- name: Set apparmor profile for nova-compute + copy: > + src=lxc-openstack + dest=/etc/apparmor.d/lxc/lxc-openstack + owner="root" + group="root" + register: apparmor_update + notify: Reindex apparmor profiles for lxc + +# Ensure apparmor reindex runs before other things that may fail +- meta: flush_handlers diff --git a/rpc_deployment/roles/lxc_common/tasks/lxc_install.yml b/rpc_deployment/roles/lxc_common/tasks/lxc_install.yml new file mode 100644 index 0000000000..30e2f02a79 --- /dev/null +++ b/rpc_deployment/roles/lxc_common/tasks/lxc_install.yml @@ -0,0 +1,34 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Add LXC repos + apt_repository: > + repo="{{ item.repo }}" + state="{{ item.state }}" + with_items: apt_lxc_common_repos + when: "ansible_distribution_version in ['12.04', '13.04', '13.10']" + +- name: Ensure common LXC Packages are Installed + apt: + pkg: "{{ item }}" + state: latest + update_cache: yes + cache_valid_time: 600 + with_items: + - python3-lxc + - lxc-templates + - liblxc1 + - libssl-dev + - libffi-dev diff --git a/rpc_deployment/roles/lxc_common/tasks/main.yml b/rpc_deployment/roles/lxc_common/tasks/main.yml new file mode 100644 index 0000000000..5203942572 --- /dev/null +++ b/rpc_deployment/roles/lxc_common/tasks/main.yml @@ -0,0 +1,18 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: lxc_install.yml +- include: lxc_host_setup.yml +- include: lxc_container_cache.yml diff --git a/rpc_deployment/roles/lxc_common/templates/lxc-rpc b/rpc_deployment/roles/lxc_common/templates/lxc-rpc new file mode 100644 index 0000000000..41c4a1252a --- /dev/null +++ b/rpc_deployment/roles/lxc_common/templates/lxc-rpc @@ -0,0 +1,816 @@ +#!/bin/bash + +# +# template script for generating ubuntu container for LXC +# +# This script consolidates and extends the existing lxc ubuntu scripts +# + +# This is a modified version of the base ubuntu template that will allow +# for the installation of packages that the Rackspace private cloud uses +# within LXC containers. + +# Copyright © 2014 Kevin Carter +# Copyright © 2011 Serge Hallyn +# Copyright © 2010 Wilhelm Meier +# Author: Wilhelm Meier +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# This library 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 +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +# Detect use under userns (unsupported) +for arg in "$@"; do + [ "$arg" = "--" ] && break + if [ "$arg" = "--mapped-uid" -o "$arg" = "--mapped-gid" ]; then + echo "This template can't be used for unprivileged containers." 1>&2 + echo "You may want to try the \"download\" template instead." 1>&2 + exit 1 + fi +done + +# Make sure the usual locations are in PATH +export PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin + +set -e + +LOCALSTATEDIR="/var" +LXC_TEMPLATE_CONFIG="/usr/share/lxc/config" + +if [ -r /etc/default/lxc ]; then + . /etc/default/lxc +fi + +configure_ubuntu() +{ + rootfs=$1 + hostname=$2 + release=$3 + user=$4 + password=$5 + + # configure the network using the dhcp + cat < $rootfs/etc/network/interfaces +# This file describes the network interfaces available on your system +# and how to activate them. For more information, see interfaces(5). + +# The loopback network interface +auto lo +iface lo inet loopback + +auto eth0 +iface eth0 inet dhcp +EOF + + # set the hostname + cat < $rootfs/etc/hostname +$hostname +EOF + # set minimal hosts + cat < $rootfs/etc/hosts +127.0.0.1 localhost +127.0.1.1 $hostname + +# The following lines are desirable for IPv6 capable hosts +::1 ip6-localhost ip6-loopback +fe00::0 ip6-localnet +ff00::0 ip6-mcastprefix +ff02::1 ip6-allnodes +ff02::2 ip6-allrouters +EOF + + if [ ! -f $rootfs/etc/init/container-detect.conf ]; then + # suppress log level output for udev + sed -i "s/=\"err\"/=0/" $rootfs/etc/udev/udev.conf + + # remove jobs for consoles 5 and 6 since we only create 4 consoles in + # this template + rm -f $rootfs/etc/init/tty{5,6}.conf + fi + + if [ -z "$bindhome" ]; then + chroot $rootfs useradd --create-home -s /bin/bash $user + echo "$user:$password" | chroot $rootfs chpasswd + fi + + # make sure we have the current locale defined in the container + if [ -z "$LANG" ] || echo $LANG | grep -E -q "^C(\..+)*$"; then + chroot $rootfs locale-gen en_US.UTF-8 || true + chroot $rootfs update-locale LANG=en_US.UTF-8 || true + else + chroot $rootfs locale-gen $LANG || true + chroot $rootfs update-locale LANG=$LANG || true + fi + + # generate new SSH keys + if [ -x $rootfs/var/lib/dpkg/info/openssh-server.postinst ]; then + cat > $rootfs/usr/sbin/policy-rc.d << EOF +#!/bin/sh +exit 101 +EOF + chmod +x $rootfs/usr/sbin/policy-rc.d + + rm -f $rootfs/etc/ssh/ssh_host_*key* + mv $rootfs/etc/init/ssh.conf $rootfs/etc/init/ssh.conf.disabled + DPKG_MAINTSCRIPT_PACKAGE=openssh DPKG_MAINTSCRIPT_NAME=postinst chroot $rootfs /var/lib/dpkg/info/openssh-server.postinst configure + mv $rootfs/etc/init/ssh.conf.disabled $rootfs/etc/init/ssh.conf + + sed -i "s/root@$(hostname)/root@$hostname/g" $rootfs/etc/ssh/ssh_host_*.pub + + rm -f $rootfs/usr/sbin/policy-rc.d + fi + + return 0 +} + +# finish setting up the user in the container by injecting ssh key and +# adding sudo group membership. +# passed-in user is either 'ubuntu' or the user to bind in from host. +finalize_user() +{ + user=$1 + + sudo_version=$(chroot $rootfs dpkg-query -W -f='${Version}' sudo) + + if chroot $rootfs dpkg --compare-versions $sudo_version gt "1.8.3p1-1"; then + groups="sudo" + else + groups="sudo admin" + fi + + for group in $groups; do + chroot $rootfs groupadd --system $group >/dev/null 2>&1 || true + chroot $rootfs adduser ${user} $group >/dev/null 2>&1 || true + done + + if [ -n "$auth_key" -a -f "$auth_key" ]; then + u_path="/home/${user}/.ssh" + root_u_path="$rootfs/$u_path" + mkdir -p $root_u_path + cp $auth_key "$root_u_path/authorized_keys" + chroot $rootfs chown -R ${user}: "$u_path" + + echo "Inserted SSH public key from $auth_key into /home/${user}/.ssh/authorized_keys" + fi + return 0 +} + +# A function to try and autodetect squid-deb-proxy servers on the local network +# if either the squid-deb-proxy-client package is installed on the host or +# a parent container set the 50squid-deb-proxy-client file. +squid_deb_proxy_autodetect() +{ + local apt_discover=/usr/share/squid-deb-proxy-client/apt-avahi-discover + local proxy_file=/etc/apt/apt.conf.d/50squid-deb-proxy-client + squid_proxy_line= # That's a global :/ + + # Maybe the host is aware of a squid-deb-proxy? + if [ -f $apt_discover ]; then + echo -n "Discovering squid-deb-proxy..." + squid_proxy_line=$($apt_discover) + if [ -n "$squid_proxy_line" ]; then + echo "found squid-deb-proxy: $squid_proxy_line" + else + echo "no squid-deb-proxy found" + fi + fi + + # Are we in a nested container, and the parent already knows of a proxy? + if [ -f $proxy_file ]; then + # Extract the squid URL from the file (whatever is between "") + squid_proxy_line=`cat $proxy_file | sed "s/.*\"\(.*\)\".*/\1/"` + fi +} + +# +# Choose proxies for container +# http_proxy will be used by debootstrap on the host. +# APT_PROXY will be used to set /etc/apt/apt.conf.d/70proxy in the container. +# +choose_container_proxy() +{ + local rootfs=$1 + local arch=$2 + + if [ -z "$HTTP_PROXY" ]; then + HTTP_PROXY="none" + fi + case "$HTTP_PROXY" in + none) + squid_deb_proxy_autodetect + if [ -n "$squid_proxy_line" ]; then + APT_PROXY=$squid_proxy_line + export http_proxy=$squid_proxy_line + else + APT_PROXY= + fi + ;; + apt) + RES=`apt-config shell APT_PROXY Acquire::http::Proxy` + eval $RES + [ -z "$APT_PROXY" ] || export http_proxy=$APT_PROXY + ;; + *) + APT_PROXY=$HTTP_PROXY + export http_proxy=$HTTP_PROXY + ;; + esac +} + +write_sourceslist() +{ + # $1 => path to the rootfs + # $2 => architecture we want to add + # $3 => whether to use the multi-arch syntax or not + + if [ -n "$APT_PROXY" ]; then + mkdir -p $rootfs/etc/apt/apt.conf.d + cat > $rootfs/etc/apt/apt.conf.d/70proxy << EOF +Acquire::http::Proxy "$APT_PROXY" ; +EOF + fi + + case $2 in + amd64|i386) + MIRROR=${MIRROR:-http://archive.ubuntu.com/ubuntu} + SECURITY_MIRROR=${SECURITY_MIRROR:-http://security.ubuntu.com/ubuntu} + ;; + *) + MIRROR=${MIRROR:-http://ports.ubuntu.com/ubuntu-ports} + SECURITY_MIRROR=${SECURITY_MIRROR:-http://ports.ubuntu.com/ubuntu-ports} + ;; + esac + if [ -n "$3" ]; then + cat >> "$1/etc/apt/sources.list" << EOF +deb [arch=$2] $MIRROR ${release} main restricted universe multiverse +deb [arch=$2] $MIRROR ${release}-updates main restricted universe multiverse +deb [arch=$2] $SECURITY_MIRROR ${release}-security main restricted universe multiverse +EOF + else + cat >> "$1/etc/apt/sources.list" << EOF +deb $MIRROR ${release} main restricted universe multiverse +deb $MIRROR ${release}-updates main restricted universe multiverse +deb $SECURITY_MIRROR ${release}-security main restricted universe multiverse +EOF + fi +} + +install_packages() +{ + local rootfs="$1" + shift + local packages="$*" + if [ -z $update ] + then + chroot $rootfs apt-get update + update=true + fi + if [ -n "${packages}" ] + then + chroot $rootfs apt-get install --force-yes -y --no-install-recommends ${packages} + fi +} + +cleanup() +{ + rm -rf $cache/partial-$arch + rm -rf $cache/rootfs-$arch +} + +suggest_flush() +{ + echo "Container upgrade failed. The container cache may be out of date," + echo "in which case flushing the cache (see -F in the help output) may help." +} + +download_ubuntu() +{ + cache=$1 + arch=$2 + release=$3 + + packages_template=${packages_template:-"ssh,vim,"} + packages_template+="libxslt1-dev,libxml2-dev,libffi-dev,sshpass,iptables,sqlite3,python-software-properties," + packages_template+="bridge-utils,libssl-dev,lvm2,rsyslog,git-core,build-essential,python-dev,libpq-dev," + packages_template+="curl,wget,time,rsync,cgroup-lite,cgmanager-utils,libcgmanager-dev,debconf-utils," + packages_template+="software-properties-common,libxslt1.1,openssl,debhelper,dh-apparmor," + + # Try to guess a list of langpacks to install + langpacks="language-pack-en" + + if which dpkg >/dev/null 2>&1; then + langpacks=`(echo $langpacks && + dpkg -l | grep -E "^ii language-pack-[a-z]* " | + cut -d ' ' -f3) | sort -u` + fi + packages_template="${packages_template},$(echo $langpacks | sed 's/ /,/g')" + + + echo "Installing packages in template: ${packages_template}" + + trap cleanup EXIT SIGHUP SIGINT SIGTERM + # check the mini ubuntu was not already downloaded + mkdir -p "$cache/partial-$arch" + if [ $? -ne 0 ]; then + echo "Failed to create '$cache/partial-$arch' directory" + return 1 + fi + + choose_container_proxy $cache/partial-$arch/ $arch + # download a mini ubuntu into a cache + echo "Downloading ubuntu $release minimal ..." + if [ -n "$(which qemu-debootstrap)" ]; then + qemu-debootstrap --verbose --components=main,universe --arch=$arch --include=${packages_template} $release $cache/partial-$arch $MIRROR + else + debootstrap --verbose --components=main,universe --arch=$arch --include=${packages_template} $release $cache/partial-$arch $MIRROR + fi + + if [ $? -ne 0 ]; then + echo "Failed to download the rootfs, aborting." + return 1 + fi + + # Serge isn't sure whether we should avoid doing this when + # $release == `distro-info -d` + echo "Installing updates" + > $cache/partial-$arch/etc/apt/sources.list + write_sourceslist $cache/partial-$arch/ $arch + + chroot "$1/partial-${arch}" apt-get update + if [ $? -ne 0 ]; then + echo "Failed to update the apt cache" + return 1 + fi + cat > "$1/partial-${arch}"/usr/sbin/policy-rc.d << EOF +#!/bin/sh +exit 101 +EOF + chmod +x "$1/partial-${arch}"/usr/sbin/policy-rc.d + + lxc-unshare -s MOUNT -- chroot "$1/partial-${arch}" apt-get dist-upgrade -y || { suggest_flush; false; } + rm -f "$1/partial-${arch}"/usr/sbin/policy-rc.d + + chroot "$1/partial-${arch}" apt-get clean + + mv "$1/partial-$arch" "$1/rootfs-$arch" + trap EXIT + trap SIGINT + trap SIGTERM + trap SIGHUP + echo "Download complete" + return 0 +} + +copy_ubuntu() +{ + cache=$1 + arch=$2 + rootfs=$3 + + # make a local copy of the miniubuntu + echo "Copying rootfs to $rootfs ..." + mkdir -p $rootfs + rsync -Ha $cache/rootfs-$arch/ $rootfs/ || return 1 + return 0 +} + +install_ubuntu() +{ + rootfs=$1 + release=$2 + flushcache=$3 + cache="$LOCALSTATEDIR/cache/lxc/$release" + mkdir -p $LOCALSTATEDIR/lock/subsys/ + + ( + flock -x 9 + if [ $? -ne 0 ]; then + echo "Cache repository is busy." + return 1 + fi + + + if [ $flushcache -eq 1 ]; then + echo "Flushing cache..." + rm -rf "$cache/partial-$arch" + rm -rf "$cache/rootfs-$arch" + fi + + echo "Checking cache download in $cache/rootfs-$arch ... " + if [ ! -e "$cache/rootfs-$arch" ]; then + download_ubuntu $cache $arch $release + if [ $? -ne 0 ]; then + echo "Failed to download 'ubuntu $release base'" + return 1 + fi + fi + + echo "Copy $cache/rootfs-$arch to $rootfs ... " + copy_ubuntu $cache $arch $rootfs + if [ $? -ne 0 ]; then + echo "Failed to copy rootfs" + return 1 + fi + + return 0 + + ) 9>$LOCALSTATEDIR/lock/subsys/lxc-ubuntu$release + + return $? +} + +copy_configuration() +{ + path=$1 + rootfs=$2 + name=$3 + arch=$4 + release=$5 + + if [ $arch = "i386" ]; then + arch="i686" + fi + + # if there is exactly one veth network entry, make sure it has an + # associated hwaddr. + nics=`grep -e '^lxc\.network\.type[ \t]*=[ \t]*veth' $path/config | wc -l` + if [ $nics -eq 1 ]; then + grep -q "^lxc.network.hwaddr" $path/config || sed -i -e "/^lxc\.network\.type[ \t]*=[ \t]*veth/a lxc.network.hwaddr = 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')" $path/config + fi + + # Generate the configuration file + ## Create the fstab (empty by default) + touch $path/fstab + + ## Relocate all the network config entries + sed -i -e "/lxc.network/{w ${path}/config-network" -e "d}" $path/config + + ## Relocate any other config entries + sed -i -e "/lxc./{w ${path}/config-auto" -e "d}" $path/config + + ## Add all the includes + echo "" >> $path/config + echo "# Common configuration" >> $path/config + if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu.common.conf" ]; then + echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu.common.conf" >> $path/config + fi + if [ -e "${LXC_TEMPLATE_CONFIG}/ubuntu.${release}.conf" ]; then + echo "lxc.include = ${LXC_TEMPLATE_CONFIG}/ubuntu.${release}.conf" >> $path/config + fi + + ## Add the container-specific config + echo "" >> $path/config + echo "# Container specific configuration" >> $path/config + [ -e "$path/config-auto" ] && cat $path/config-auto >> $path/config && rm $path/config-auto + grep -q "^lxc.rootfs" $path/config 2>/dev/null || echo "lxc.rootfs = $rootfs" >> $path/config + cat <> $path/config +lxc.mount = $path/fstab +lxc.utsname = $name +lxc.arch = $arch +EOF + + ## Re-add the previously removed network config + echo "" >> $path/config + echo "# Network configuration" >> $path/config + cat $path/config-network >> $path/config + rm $path/config-network + + if [ $? -ne 0 ]; then + echo "Failed to add configuration" + return 1 + fi + + return 0 +} + +post_process() +{ + rootfs=$1 + release=$2 + packages=$3 + + # Disable service startup + cat > $rootfs/usr/sbin/policy-rc.d << EOF +#!/bin/sh +exit 101 +EOF + chmod +x $rootfs/usr/sbin/policy-rc.d + + if [ ! -f $rootfs/etc/init/container-detect.conf ]; then + # Make sure we have a working resolv.conf + cresolvonf="${rootfs}/etc/resolv.conf" + mv $cresolvonf ${cresolvonf}.lxcbak + cat /etc/resolv.conf > ${cresolvonf} + + # for lucid, if not trimming, then add the ubuntu-virt + # ppa and install lxcguest + if [ $release = "lucid" ]; then + chroot $rootfs apt-get update + install_packages $rootfs "python-software-properties" + chroot $rootfs add-apt-repository ppa:ubuntu-virt/ppa + fi + + chroot $rootfs apt-get update + chroot $rootfs apt-get install --force-yes -y lxcguest + + # Restore old resolv.conf + rm -f ${cresolvonf} + mv ${cresolvonf}.lxcbak ${cresolvonf} + fi + + # If the container isn't running a native architecture, setup multiarch + if [ -x "$(ls -1 ${rootfs}/usr/bin/qemu-*-static 2>/dev/null)" ]; then + dpkg_version=$(chroot $rootfs dpkg-query -W -f='${Version}' dpkg) + if chroot $rootfs dpkg --compare-versions $dpkg_version ge "1.16.2"; then + chroot $rootfs dpkg --add-architecture ${hostarch} + else + mkdir -p ${rootfs}/etc/dpkg/dpkg.cfg.d + echo "foreign-architecture ${hostarch}" > ${rootfs}/etc/dpkg/dpkg.cfg.d/lxc-multiarch + fi + + # Save existing value of MIRROR and SECURITY_MIRROR + DEFAULT_MIRROR=$MIRROR + DEFAULT_SECURITY_MIRROR=$SECURITY_MIRROR + + # Write a new sources.list containing both native and multiarch entries + > ${rootfs}/etc/apt/sources.list + write_sourceslist $rootfs $arch "native" + + MIRROR=$DEFAULT_MIRROR + SECURITY_MIRROR=$DEFAULT_SECURITY_MIRROR + write_sourceslist $rootfs $hostarch "multiarch" + + # Finally update the lists and install upstart using the host architecture + HOST_PACKAGES="upstart:${hostarch} mountall:${hostarch} isc-dhcp-client:${hostarch}" + chroot $rootfs apt-get update + if chroot $rootfs dpkg -l iproute2 | grep -q ^ii; then + HOST_PACKAGES="$HOST_PACKAGES iproute2:${hostarch}" + else + HOST_PACKAGES="$HOST_PACKAGES iproute:${hostarch}" + fi + install_packages $rootfs $HOST_PACKAGES + fi + + # Install Packages in container + if [ -n "$packages" ] + then + local packages="`echo $packages | sed 's/,/ /g'`" + echo "Installing packages: ${packages}" + install_packages $rootfs $packages + fi + + # Set initial timezone as on host + if [ -f /etc/timezone ]; then + cat /etc/timezone > $rootfs/etc/timezone + chroot $rootfs dpkg-reconfigure -f noninteractive tzdata + elif [ -f /etc/sysconfig/clock ]; then + . /etc/sysconfig/clock + echo $ZONE > $rootfs/etc/timezone + chroot $rootfs dpkg-reconfigure -f noninteractive tzdata + else + echo "Timezone in container is not configured. Adjust it manually." + fi + + # rmdir /dev/shm for containers that have /run/shm + # I'm afraid of doing rm -rf $rootfs/dev/shm, in case it did + # get bind mounted to the host's /run/shm. So try to rmdir + # it, and in case that fails move it out of the way. + # NOTE: This can only be removed once 12.04 goes out of support + if [ ! -L $rootfs/dev/shm ] && [ -d $rootfs/run/shm ] && [ -e $rootfs/dev/shm ]; then + rmdir $rootfs/dev/shm 2>/dev/null || mv $rootfs/dev/shm $rootfs/dev/shm.bak + ln -s /run/shm $rootfs/dev/shm + fi + + # Re-enable service startup + rm $rootfs/usr/sbin/policy-rc.d +} + +do_bindhome() +{ + rootfs=$1 + user=$2 + + # copy /etc/passwd, /etc/shadow, and /etc/group entries into container + pwd=`getent passwd $user` || { echo "Failed to copy password entry for $user"; false; } + echo $pwd >> $rootfs/etc/passwd + + # make sure user's shell exists in the container + shell=`echo $pwd | cut -d: -f 7` + if [ ! -x $rootfs/$shell ]; then + echo "shell $shell for user $user was not found in the container." + pkg=`dpkg -S $(readlink -m $shell) | cut -d ':' -f1` + echo "Installing $pkg" + install_packages $rootfs $pkg + fi + + shad=`getent shadow $user` + echo "$shad" >> $rootfs/etc/shadow + + # bind-mount the user's path into the container's /home + h=`getent passwd $user | cut -d: -f 6` + mkdir -p $rootfs/$h + + # use relative path in container + h2=${h#/} + while [ ${h2:0:1} = "/" ]; do + h2=${h2#/} + done + echo "$h $h2 none bind 0 0" >> $path/fstab + + # Make sure the group exists in container + grp=`echo $pwd | cut -d: -f 4` # group number for $user + grpe=`getent group $grp` || return 0 # if host doesn't define grp, ignore in container + chroot $rootfs getent group "$grpe" || echo "$grpe" >> $rootfs/etc/group +} + +usage() +{ + cat <] [-d|--debug] + [-F | --flush-cache] [-r|--release ] [ -S | --auth-key ] + [--rootfs ] [--packages ] [-u|--user ] [--password ] +release: the ubuntu release (e.g. precise): defaults to host release on ubuntu, otherwise uses latest LTS +bindhome: bind 's home into the container + The ubuntu user will not be created, and will have + sudo access. +arch: the container architecture (e.g. amd64): defaults to host arch +auth-key: SSH Public key file to inject into container +packages: list of packages to add comma separated +EOF + return 0 +} + +options=$(getopt -o a:b:hp:r:n:FS:du: -l arch:,bindhome:,help,path:,release:,name:,flush-cache,auth-key:,debug,rootfs:,packages:,user:,password:,mirror:,security-mirror: -- "$@") +if [ $? -ne 0 ]; then + usage $(basename $0) + exit 1 +fi +eval set -- "$options" + +release=precise # Default to the last Ubuntu LTS release for non-Ubuntu systems +if [ -f /etc/lsb-release ]; then + . /etc/lsb-release + if [ "$DISTRIB_ID" = "Ubuntu" ]; then + release=$DISTRIB_CODENAME + fi +fi + +bindhome= + +# Code taken from debootstrap +if [ -x /usr/bin/dpkg ] && /usr/bin/dpkg --print-architecture >/dev/null 2>&1; then + arch=`/usr/bin/dpkg --print-architecture` +elif which udpkg >/dev/null 2>&1 && udpkg --print-architecture >/dev/null 2>&1; then + arch=`/usr/bin/udpkg --print-architecture` +else + arch=$(uname -m) + if [ "$arch" = "i686" ]; then + arch="i386" + elif [ "$arch" = "x86_64" ]; then + arch="amd64" + elif [ "$arch" = "armv7l" ]; then + arch="armhf" + elif [ "$arch" = "aarch64" ]; then + arch="arm64" + elif [ "$arch" = "ppc64le" ]; then + arch="ppc64el" + fi +fi + +debug=0 +hostarch=$arch +flushcache=0 +packages="" +user="ubuntu" +password="ubuntu" +while true +do + case "$1" in + -h|--help) usage $0 && exit 0;; + --rootfs) rootfs=$2; shift 2;; + -p|--path) path=$2; shift 2;; + -n|--name) name=$2; shift 2;; + -u|--user) user=$2; shift 2;; + --password) password=$2; shift 2;; + -F|--flush-cache) flushcache=1; shift 1;; + -r|--release) release=$2; shift 2;; + --packages) packages=$2; shift 2;; + -b|--bindhome) bindhome=$2; shift 2;; + -a|--arch) arch=$2; shift 2;; + -S|--auth-key) auth_key=$2; shift 2;; + -d|--debug) debug=1; shift 1;; + --mirror) MIRROR=$2; shift 2;; + --security-mirror) SECURITY_MIRROR=$2; shift 2;; + --) shift 1; break ;; + *) break ;; + esac +done + +if [ $debug -eq 1 ]; then + set -x +fi + +if [ -n "$bindhome" ]; then + pwd=`getent passwd $bindhome` + if [ $? -ne 0 ]; then + echo "Error: no password entry found for $bindhome" + exit 1 + fi +fi + + +if [ "$arch" = "i686" ]; then + arch=i386 +fi + +if [ $hostarch = "i386" -a $arch = "amd64" ]; then + echo "can't create $arch container on $hostarch" + exit 1 +fi + +if [ $hostarch = "armhf" -o $hostarch = "armel" -o $hostarch = "arm64" ] && \ + [ $arch != "armhf" -a $arch != "armel" -a $arch != "arm64" ]; then + echo "can't create $arch container on $hostarch" + exit 1 +fi + +if [ $arch = "arm64" ] && [ $hostarch != "arm64" ]; then + echo "can't create $arch container on $hostarch" + exit 1 +fi + +if [ $hostarch = "powerpc" -a $arch != "powerpc" ]; then + echo "can't create $arch container on $hostarch" + exit 1 +fi + +which debootstrap >/dev/null 2>&1 || { echo "'debootstrap' command is missing" >&2; false; } + +if [ -z "$path" ]; then + echo "'path' parameter is required" + exit 1 +fi + +if [ "$(id -u)" != "0" ]; then + echo "This script should be run as 'root'" + exit 1 +fi + +# detect rootfs +config="$path/config" +# if $rootfs exists here, it was passed in with --rootfs +if [ -z "$rootfs" ]; then + if grep -q '^lxc.rootfs' $config 2>/dev/null ; then + rootfs=$(awk -F= '/^lxc.rootfs =/{ print $2 }' $config) + else + rootfs=$path/rootfs + fi +fi + +install_ubuntu $rootfs $release $flushcache +if [ $? -ne 0 ]; then + echo "failed to install ubuntu $release" + exit 1 +fi + +configure_ubuntu $rootfs $name $release $user $password +if [ $? -ne 0 ]; then + echo "failed to configure ubuntu $release for a container" + exit 1 +fi + +copy_configuration $path $rootfs $name $arch $release +if [ $? -ne 0 ]; then + echo "failed write configuration file" + exit 1 +fi + +post_process $rootfs $release $trim_container $packages + +if [ -n "$bindhome" ]; then + do_bindhome $rootfs $bindhome + finalize_user $bindhome +else + finalize_user $user +fi + +echo "" +echo "##" +if [ -n "$bindhome" ]; then + echo "# Log in as user $bindhome" +else + echo "# The default user is '$user' with password '$password'!" + echo "# Use the 'sudo' command to run tasks as root in the container." +fi +echo "##" +echo "" \ No newline at end of file diff --git a/rpc_deployment/roles/lxc_common/templates/lxc-rpc.conf b/rpc_deployment/roles/lxc_common/templates/lxc-rpc.conf new file mode 100644 index 0000000000..7dc61f02fc --- /dev/null +++ b/rpc_deployment/roles/lxc_common/templates/lxc-rpc.conf @@ -0,0 +1,22 @@ +lxc.start.auto = 1 +lxc.start.delay = 15 +lxc.group = onboot +lxc.group = rpc + +# Default LXC network +lxc.network.type = veth +lxc.network.name = eth0 +lxc.network.link = lxcbr0 +lxc.network.flags = up +lxc.network.hwaddr = 00:16:3e:xx:xx:xx + +# Create a veth pair within the container +lxc.network.type = veth +# Network device within the container +lxc.network.name = eth1 +# Host link to attach to, this should be a bridge +lxc.network.link = {{ management_bridge }} +# Hardware Address +lxc.network.hwaddr = 00:16:3e:xx:xx:xx +# enable the device on boot +lxc.network.flags = up diff --git a/rpc_deployment/roles/maas_dell_hardware/tasks/main.yml b/rpc_deployment/roles/maas_dell_hardware/tasks/main.yml new file mode 100644 index 0000000000..bd8e6fe2b8 --- /dev/null +++ b/rpc_deployment/roles/maas_dell_hardware/tasks/main.yml @@ -0,0 +1,45 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Get entity ID for physical_host + shell: raxmon-entities-list | grep "label={{ inventory_hostname|quote }} " | sed -e 's/^.* id=\(.*\) label=.*$/\1/g' + register: entity_id + +- name: Validate if check exists + shell: raxmon-checks-list --entity-id {{ entity_id.stdout|quote }} | grep "label={{ check_name|quote }}--{{ inventory_hostname|quote }}" + register: check_exists + ignore_errors: True + +- name: Create check if it does not exist + command: raxmon-checks-create --entity-id {{ entity_id.stdout }} --type agent.plugin --label {{ check_name }}--{{ inventory_hostname }} --details {{ check_details }} --period {{ check_period }} --timeout {{ check_timeout }} + when: check_exists|failed + +- name: Get check ID for newly created check + shell: raxmon-checks-list --entity-id {{ entity_id.stdout|quote }} | grep "label={{ check_name|quote }}--{{ inventory_hostname|quote }}" | sed -e 's/^.* id=\(.*\) label=.*$/\1/g' + register: check_id + +- name: Validate if alarm exists + shell: raxmon-alarms-list --entity-id {{ entity_id.stdout|quote }} | grep "label={{ item.name|quote }}--{{ inventory_hostname|quote }}" + register: alarm_exists + ignore_errors: True + when: alarms is defined + with_items: alarms + +- name: Create alarm if it does not exist + shell: raxmon-alarms-create --entity-id {{ entity_id.stdout|quote }} --check-id {{ check_id.stdout|quote }} --notification-plan {{ maas_notification_plan }} --label {{ item[1].name|quote }}--{{ inventory_hostname|quote }} --criteria {{ item[1].criteria|quote }} + when: item[0]|failed and alarms is defined + with_together: + - alarm_exists.results + - alarms diff --git a/rpc_deployment/roles/maas_local/tasks/main.yml b/rpc_deployment/roles/maas_local/tasks/main.yml new file mode 100644 index 0000000000..ebd3965a4b --- /dev/null +++ b/rpc_deployment/roles/maas_local/tasks/main.yml @@ -0,0 +1,51 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Get entity ID for physical_host + shell: raxmon-entities-list | grep "label={{ physical_host|quote }} " | sed -e 's/^.* id=\(.*\) label=.*$/\1/g' + register: entity_id + delegate_to: "{{ physical_host }}" + +- name: Validate if check exists + shell: raxmon-checks-list --entity-id {{ entity_id.stdout|quote }} | grep "label={{ check_name|quote }}--{{ ansible_hostname|quote }}" + register: check_exists + ignore_errors: True + delegate_to: "{{ physical_host }}" + +- name: Create check if it does not exist + command: raxmon-checks-create --entity-id {{ entity_id.stdout }} --type agent.plugin --label {{ check_name }}--{{ ansible_hostname }} --details {{ check_details }} --period {{ check_period }} --timeout {{ check_timeout }} + when: check_exists|failed + delegate_to: "{{ physical_host }}" + +- name: Get check ID for newly created check + shell: raxmon-checks-list --entity-id {{ entity_id.stdout|quote }} | grep "label={{ check_name|quote }}--{{ ansible_hostname|quote }}" | sed -e 's/^.* id=\(.*\) label=.*$/\1/g' + register: check_id + delegate_to: "{{ physical_host }}" + +- name: Validate if alarm exists + shell: raxmon-alarms-list --entity-id {{ entity_id.stdout|quote }} | grep "label={{ item.name|quote }}--{{ ansible_hostname|quote }}" + register: alarm_exists + ignore_errors: True + delegate_to: "{{ physical_host }}" + when: alarms is defined + with_items: alarms + +- name: Create alarm if it does not exist + shell: raxmon-alarms-create --entity-id {{ entity_id.stdout|quote }} --check-id {{ check_id.stdout|quote }} --notification-plan {{ maas_notification_plan }} --label {{ item[1].name|quote }}--{{ ansible_hostname|quote }} --criteria {{ item[1].criteria|quote }} + delegate_to: "{{ physical_host }}" + when: item[0]|failed and alarms is defined + with_together: + - alarm_exists.results + - alarms diff --git a/rpc_deployment/roles/maas_remote/tasks/main.yml b/rpc_deployment/roles/maas_remote/tasks/main.yml new file mode 100644 index 0000000000..6ea2efd531 --- /dev/null +++ b/rpc_deployment/roles/maas_remote/tasks/main.yml @@ -0,0 +1,64 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Entity {{ entity_name }} count + shell: "raxmon-entities-list | grep ' label={{ entity_name }} provider=Rackspace Monitoring ...>$' | wc -l" + register: entity_count + delegate_to: "{{ physical_host }}" + +- name: At most one {{ entity_name }} entity exists + fail: + msg: "Entity count of {{ entity_count.stdout }} != 1 for entity with the label {{ entity_name }}" + when: entity_count.stdout|int != 1 + +- name: Get entity {{ entity_name }} + shell: "raxmon-entities-list | grep ' label={{ entity_name }} provider=Rackspace Monitoring ...>$' | awk '{print $2}' | cut -d= -f2" + register: entity + delegate_to: "{{ physical_host }}" + +- name: Check {{ check_name }} count + shell: "raxmon-checks-list --entity-id {{ entity.stdout }} | grep ' label={{ check_name }}...>$' | wc -l" + register: check_count + delegate_to: "{{ physical_host }}" + +- name: At most one {{ check_name }} check exists + fail: + msg: "Please make sure there is only one check for the entity {{ entity.stdout }} with the name {{ check_name }}" + when: check_count.stdout|int > 1 + +- name: Create check {{ check_name }} + shell: raxmon-checks-create --entity-id {{ entity.stdout }} --label {{ check_name }} --type {{ check_type }} --details url={{ url }} --monitoring-zones "{{ monitoring_zones|join(',') }}" --target-alias {{ target_alias }} --period {{ check_period }} --timeout {{ check_timeout }} + when: check_count.stdout|int == 0 + delegate_to: "{{ physical_host }}" + +- name: Get check {{ check_name }} + shell: "raxmon-checks-list --entity-id {{ entity.stdout }} | grep ' label={{ check_name }}...>$' | awk '{print $2}' | cut -d= -f2" + register: check + delegate_to: "{{ physical_host }}" + +- name: Alarm {{ alarm_name }} count + shell: "raxmon-alarms-list --entity-id {{ entity.stdout }} | grep ' label={{ alarm_name }} ...>' | wc -l" + register: alarm_count + delegate_to: "{{ physical_host }}" + +- name: At most one {{ alarm_name }} alarm exists + fail: + msg: "Please make sure there is only one alarm for the check {{ check.stdout }} with the name {{ alarm_name }} on entity {{ entity.stdout }}" + when: alarm_count.stdout|int > 1 + +- name: Create alarm {{ alarm_name }} + shell: "raxmon-alarms-create --entity-id {{ entity.stdout }} --label {{ alarm_name }} --check-id {{ check.stdout }} --notification-plan-id {{ notification_plan }} --criteria {{ criteria|quote }}" + when: alarm_count.stdout|int == 0 + delegate_to: "{{ physical_host }}" diff --git a/rpc_deployment/roles/memcached/handlers/main.yml b/rpc_deployment/roles/memcached/handlers/main.yml new file mode 100644 index 0000000000..91efab23e7 --- /dev/null +++ b/rpc_deployment/roles/memcached/handlers/main.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Restart memcached + service: name=memcached state=restarted pattern=memcached diff --git a/rpc_deployment/roles/memcached/tasks/main.yml b/rpc_deployment/roles/memcached/tasks/main.yml new file mode 100644 index 0000000000..da94acbe71 --- /dev/null +++ b/rpc_deployment/roles/memcached/tasks/main.yml @@ -0,0 +1,30 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Install memcached + apt: + pkg: memcached + state: latest + update_cache: yes + cache_valid_time: 600 + +- name: Drop memcached config + template: > + src="memcached.conf" + dest="/etc/memcached.conf" + owner=root + group=root + mode=0644 + notify: Restart memcached diff --git a/rpc_deployment/roles/memcached/templates/memcached.conf b/rpc_deployment/roles/memcached/templates/memcached.conf new file mode 100644 index 0000000000..8390c9aed8 --- /dev/null +++ b/rpc_deployment/roles/memcached/templates/memcached.conf @@ -0,0 +1,6 @@ +-d +logfile /var/log/memcached.log +-m {{ memcached_memory|default('4096') }} +-p {{ memcached_port|default('11211') }} +-u {{ memcached_user|default('memcache') }} +-l {{ memcached_listen|default('127.0.0.1') }} diff --git a/rpc_deployment/roles/neutron_add_network_interfaces/tasks/main.yml b/rpc_deployment/roles/neutron_add_network_interfaces/tasks/main.yml new file mode 100644 index 0000000000..2a1cc4ecd8 --- /dev/null +++ b/rpc_deployment/roles/neutron_add_network_interfaces/tasks/main.yml @@ -0,0 +1,41 @@ +--- +- name: Drop additional lxc network interfaces + template: + src=host_container_interface.j2 + dest=/var/lib/lxc/{{ container_name }}/add_neutron_network_interface.conf + register: host_container_interface + delegate_to: "{{ physical_host }}" + when: provider_networks is defined and tunnel_address is defined and is_metal != true + +- name: Update container config + lineinfile: + dest: /var/lib/lxc/{{ container_name }}/config + line: "lxc.include = /var/lib/lxc/{{ container_name }}/add_neutron_network_interface.conf" + state: present + register: container_net_include + when: host_container_interface|changed and is_metal != true + delegate_to: "{{ physical_host }}" + +- name: Drop additional container network interfaces file(s) + template: + src=container_interface_file.j2 + dest="/etc/network/interfaces.d/provider_networks.cfg" + register: container_interface + when: provider_networks is defined and tunnel_address is defined and is_metal != true + +- name: Restart container + lxc: > + command=restart + name="{{ container_name }}" + register: restarted_container + when: container_net_include|changed or host_container_interface|changed or container_interface|changed and is_metal != true + delegate_to: "{{ physical_host }}" + +- name: Wait for container networking + wait_for: > + port=22 + timeout=60 + search_regex=OpenSSH + host={{ container_address }} + when: restarted_container|changed and is_metal != true + delegate_to: "{{ physical_host }}" diff --git a/rpc_deployment/roles/neutron_add_network_interfaces/templates/container_interface_file.j2 b/rpc_deployment/roles/neutron_add_network_interfaces/templates/container_interface_file.j2 new file mode 100644 index 0000000000..80cd829d86 --- /dev/null +++ b/rpc_deployment/roles/neutron_add_network_interfaces/templates/container_interface_file.j2 @@ -0,0 +1,26 @@ +{% set tunnel_interfaces = [] %} +{% for net in provider_networks %} +{% if net.network.container_interface not in tunnel_interfaces %} + {% if net.network.type == 'vxlan' %} + {% if tunnel_interfaces.append(net.network.container_interface) %}{% endif %} + {% endif %} +{% endif %} +{% endfor %} + +# Found Tunnel interfaces which have been assigned the tunnel_address +# Devices: {{ tunnel_interfaces }} +{% set used_interfaces = [] %} +{% for net in provider_networks %} +{% if net.network.container_interface not in used_interfaces %} + {% if used_interfaces.append(net.network.container_interface) %}{% endif %} + +auto {{ net.network.container_interface }} +{% if net.network.container_interface in tunnel_interfaces %} +iface {{ net.network.container_interface }} inet static + address {{ tunnel_address }} + netmask {{ net.network.subnetmask|default('255.255.255.0') }} +{% else %} +iface {{ net.network.container_interface }} inet manual +{% endif %} +{% endif %} +{% endfor %} diff --git a/rpc_deployment/roles/neutron_add_network_interfaces/templates/host_container_interface.j2 b/rpc_deployment/roles/neutron_add_network_interfaces/templates/host_container_interface.j2 new file mode 100644 index 0000000000..d82cc1d74e --- /dev/null +++ b/rpc_deployment/roles/neutron_add_network_interfaces/templates/host_container_interface.j2 @@ -0,0 +1,21 @@ +{% set used_interfaces = [] %} +{% for net in provider_networks %} +{% if net.network.container_interface not in used_interfaces %} + {% if used_interfaces.append(net.network.container_interface) %}{% endif %} + +# Create a veth pair within the container +lxc.network.type = veth +# Network device within the container +lxc.network.name = {{ net.network.container_interface }} +# Host link to attach to, this should be a bridge +lxc.network.link = {{ net.network.container_bridge }} +# Hardware Address +lxc.network.hwaddr = 00:16:3e:xx:xx:xx +# enable the device on boot +lxc.network.flags = up + +{% endif %} +{% endfor %} + +# All used IP addresses built from the provider_networks array +# Devices: {{ used_interfaces }} diff --git a/rpc_deployment/roles/neutron_common/tasks/main.yml b/rpc_deployment/roles/neutron_common/tasks/main.yml new file mode 100644 index 0000000000..e8d8c16b1b --- /dev/null +++ b/rpc_deployment/roles/neutron_common/tasks/main.yml @@ -0,0 +1,83 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Ensure service tenant + keystone: > + command=ensure_tenant + token="{{ auth_admin_token }}" + endpoint="{{ auth_admin_uri }}" + tenant_name=service + description="Service Tenant" + tags: + - neutron_config + +- name: Get nova admin endpoint + shell: | + . /root/openrc + SERVICE_ID="$(keystone service-list | grep -w 'compute' | awk '{print $2}')" + keystone endpoint-list | grep -w "${SERVICE_ID}" | awk '{print $10}' + register: novaendpoint + changed_when: false + failed_when: novaendpoint.rc != 0 + tags: + - neutron_config + +- name: Get nova admin user + shell: | + . /root/openrc + keystone service-list | grep -w compute | awk '{print $4}' + register: novauser + changed_when: false + failed_when: novauser.rc != 0 + tags: + - neutron_config + +- name: Set variable data + set_fact: + nova_admin_username: "{{ novauser.stdout }}" + nova_admin_tenant_id: "{{ keystone_facts['id'] }}" + nova_service_adminurl: "{{ novaendpoint.stdout|replace('/$(tenant_id)s', '') }}" + nova_admin_password: "{{ nova_service_password }}" + nova_admin_auth_url: "{{ auth_identity_uri }}" + tags: + - neutron_config + +- name: Setup Neutron Config + template: > + src={{ item }} + dest=/etc/neutron/{{ item }} + owner={{ system_group }} + group={{ system_user }} + with_items: + - neutron.conf + - metadata_agent.ini + - l3_agent.ini + - dhcp_agent.ini + - api-paste.ini + - policy.json + - plugins/ml2/ml2_conf.ini + - rootwrap.d/debug.filters + - rootwrap.d/dhcp.filters + - rootwrap.d/iptables-firewall.filters + - rootwrap.d/l3.filters + - rootwrap.d/lbaas-haproxy.filters + - rootwrap.d/linuxbridge-plugin.filters + - rootwrap.d/nec-plugin.filters + - rootwrap.d/openvswitch-plugin.filters + - rootwrap.d/ryu-plugin.filters + - rootwrap.d/vpnaas.filters + notify: Restart os service + tags: + - neutron_config diff --git a/rpc_deployment/roles/neutron_common/templates/api-paste.ini b/rpc_deployment/roles/neutron_common/templates/api-paste.ini new file mode 100644 index 0000000000..bbcd41527d --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/api-paste.ini @@ -0,0 +1,30 @@ +[composite:neutron] +use = egg:Paste#urlmap +/: neutronversions +/v2.0: neutronapi_v2_0 + +[composite:neutronapi_v2_0] +use = call:neutron.auth:pipeline_factory +noauth = request_id catch_errors extensions neutronapiapp_v2_0 +keystone = request_id catch_errors authtoken keystonecontext extensions neutronapiapp_v2_0 + +[filter:request_id] +paste.filter_factory = neutron.openstack.common.middleware.request_id:RequestIdMiddleware.factory + +[filter:catch_errors] +paste.filter_factory = neutron.openstack.common.middleware.catch_errors:CatchErrorsMiddleware.factory + +[filter:keystonecontext] +paste.filter_factory = neutron.auth:NeutronKeystoneContext.factory + +[filter:authtoken] +paste.filter_factory = keystonemiddleware.auth_token:filter_factory + +[filter:extensions] +paste.filter_factory = neutron.api.extensions:plugin_aware_extension_middleware_factory + +[app:neutronversions] +paste.app_factory = neutron.api.versions:Versions.factory + +[app:neutronapiapp_v2_0] +paste.app_factory = neutron.api.v2.router:APIRouter.factory diff --git a/rpc_deployment/roles/neutron_common/templates/dhcp_agent.ini b/rpc_deployment/roles/neutron_common/templates/dhcp_agent.ini new file mode 100644 index 0000000000..12338860c0 --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/dhcp_agent.ini @@ -0,0 +1,5 @@ +[DEFAULT] +interface_driver = {{ interface_driver }} +dhcp_driver = {{ dhcp_driver }} +use_namespaces = True +enable_isolated_metadata = True diff --git a/rpc_deployment/roles/neutron_common/templates/l3_agent.ini b/rpc_deployment/roles/neutron_common/templates/l3_agent.ini new file mode 100644 index 0000000000..46c10dca1f --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/l3_agent.ini @@ -0,0 +1,5 @@ +[DEFAULT] +interface_driver = {{ interface_driver }} +handle_internal_only_routers = True +use_namespaces = True +external_network_bridge = diff --git a/rpc_deployment/roles/neutron_common/templates/metadata_agent.ini b/rpc_deployment/roles/neutron_common/templates/metadata_agent.ini new file mode 100644 index 0000000000..ad09722d40 --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/metadata_agent.ini @@ -0,0 +1,9 @@ +[DEFAULT] +auth_url = {{ auth_identity_uri }} +auth_region = {{ service_region }} +admin_tenant_name = {{ service_admin_tenant_name }} +admin_user = {{ service_admin_username }} +admin_password = {{ service_admin_password }} +nova_metadata_ip = {{ hostvars[groups['nova_all'][0]]['nova_metadata_ip'] }} +metadata_proxy_shared_secret = {{ hostvars[groups['nova_all'][0]]['nova_metadata_proxy_shared_secret'] }} +metadata_workers = 10 diff --git a/rpc_deployment/roles/neutron_common/templates/metering_agent.ini b/rpc_deployment/roles/neutron_common/templates/metering_agent.ini new file mode 100644 index 0000000000..00312e67e1 --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/metering_agent.ini @@ -0,0 +1,9 @@ +[DEFAULT] +debug = True +driver = {{ metering_driver }} +interface_driver = {{ interface_driver }} +measure_interval = 30 +use_namespaces = True + +[AGENT] +report_interval = 30 diff --git a/rpc_deployment/roles/neutron_common/templates/neutron.conf b/rpc_deployment/roles/neutron_common/templates/neutron.conf new file mode 100644 index 0000000000..3598844bf0 --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/neutron.conf @@ -0,0 +1,110 @@ +[DEFAULT] +verbose = True +debug = False +use_syslog = False + +log_file = /var/log/neutron/neutron.log +auth_strategy = keystone +lock_path = /var/lock/neutron + +# Sets qdhcp and qrouter tap interfaces to 1450 for VXLAN compatibility +network_device_mtu = {{ neutron_network_device_mtu|default('1450') }} + + +## Schedulers +router_distributed = True +agent_down_time = {{ neutron_agent_down_time }} +network_scheduler_driver = neutron.scheduler.dhcp_agent_scheduler.ChanceScheduler +router_scheduler_driver = neutron.scheduler.l3_agent_scheduler.LeastRoutersScheduler +loadbalancer_pool_scheduler_driver = neutron.services.loadbalancer.agent_scheduler.ChanceScheduler +network_auto_schedule = True +router_auto_schedule = True + + +## API +bind_port = 9696 +bind_host = 0.0.0.0 + + +## Workers +api_workers = 10 +rpc_workers = 5 + + +## Plugins +allow_overlapping_ips = True +core_plugin = {{ core_plugin }} + +service_plugins = {% for plugin in service_plugins %}{{ plugin }}{% if not loop.last %},{% endif %}{% endfor %} + + +## MAC Address +base_mac = fa:16:3e:00:00:00 +mac_generation_retries = 16 + + +## DHCP +dhcp_lease_duration = 86400 +dhcp_agent_notification = True + + +## RabbitMQ +rabbit_hosts = {{ rabbit_hosts }} +rabbit_port = {{ rabbit_port }} +rabbit_userid = {{ rabbit_userid }} +rabbit_password = {{ rabbit_password }} + + +## Notifications +notification_driver = neutron.openstack.common.notifier.rpc_notifier +notify_nova_on_port_status_changes = True +notify_nova_on_port_data_changes = True +send_events_interval = 2 + + +## Nova +nova_url = {{ nova_service_adminurl }} +nova_admin_username = {{ nova_admin_username }} +nova_admin_tenant_id = {{ nova_admin_tenant_id }} +nova_admin_password = {{ nova_admin_password }} +nova_admin_auth_url = {{ nova_admin_auth_url }} + + +[quotas] +quota_driver = neutron.db.quota_db.DbQuotaDriver +quota_items = network,subnet,port + + +[agent] +polling_interval = {{ neutron_agent_polling_interval|default(5) }} +report_interval = {{ neutron_report_interval|int }} +root_helper = sudo /usr/local/bin/neutron-rootwrap /etc/neutron/rootwrap.conf + + +[keystone_authtoken] +signing_dir = /var/cache/neutron +identity_uri = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }} +auth_uri = {{ auth_identity_uri }} +admin_tenant_name = {{ service_admin_tenant_name }} +admin_user = {{ service_admin_username }} +admin_password = {{ service_admin_password }} + +memcached_servers = {{ internal_vip_address }}:{{ memcached_port }} +token_cache_time = 300 +revocation_cache_time = 60 + +# if your memcached server is shared, use these settings to avoid cache poisoning +memcache_security_strategy = ENCRYPT +memcache_secret_key = {{ memcached_secret_key }} + +# if your keystone deployment uses PKI, and you value security over performance: +check_revocations_for_cached = {{ hostvars[groups['keystone_all'][0]]['keystone_use_pki'] }} + + +[database] +connection = mysql://{{ container_mysql_user }}:{{ container_mysql_password }}@{{ mysql_address }}/{{ container_database }}?charset=utf8 + + +[service_providers] +service_provider=LOADBALANCER:Haproxy:neutron.services.loadbalancer.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default +service_provider=VPN:openswan:neutron.services.vpn.service_drivers.ipsec.IPsecVPNDriver:default diff --git a/rpc_deployment/roles/neutron_common/templates/plugins/ml2/ml2_conf.ini b/rpc_deployment/roles/neutron_common/templates/plugins/ml2/ml2_conf.ini new file mode 100644 index 0000000000..7ab50ba7f0 --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/plugins/ml2/ml2_conf.ini @@ -0,0 +1,112 @@ +{%- set network_vlan_ranges = [] %} +{%- set network_vxlan_ranges = [] %} +{%- set network_flat_networks = [] %} +{%- set network_mappings = [] %} +{%- set network_types = [] %} +{%- set used_interfaces = [] %} +{%- for net in provider_networks %} + {%- if net.network.type == "vlan" %} + {%- if "vlan" not in network_types %} + {%- if network_types.append("vlan") %}{%- endif %} + {%- endif %} + {%- set vlan_pair = [] %} + {%- if vlan_pair.append(net.network.net_name) %}{%- endif %} + {%- if vlan_pair.append(net.network.range) %}{%- endif %} + {%- if vlan_pair|join(':') not in network_vlan_ranges%} + {%- if network_vlan_ranges.append(vlan_pair|join(':')) %}{%- endif %} + {%- endif %} + {%- elif net.network.type == "vxlan" %} + {%- if "vxlan" not in network_types %} + {%- if network_types.append("vxlan") %}{%- endif %} + {%- endif %} + {%- if net.network.range not in network_vxlan_ranges %} + {%- if network_vxlan_ranges.append(net.network.range) %}{%- endif %} + {%- endif %} + {%- elif net.network.type == "flat" %} + {%- if "flat" not in network_types %} + {%- if network_types.append("flat") %}{%- endif %} + {%- endif %} + {%- if net.network.net_name not in network_flat_networks %} + {%- if network_flat_networks.append(net.network.net_name) %}{%- endif %} + {%- endif %} + {%- endif %} + {% if net.network.type != 'raw' %} + {%- set map_pair = [] %} + {%- if 'net_name' in net.network %} + {%- if map_pair.append(net.network.net_name) %}{%- endif %} + {%- endif %} + {%- if is_metal == true %} + {%- if map_pair.append(net.network.container_bridge) %}{%- endif %} + {%- else %} + {%- if map_pair.append(net.network.container_interface) %}{%- endif %} + {%- endif %} + {%- if map_pair|join(':') not in network_mappings %} + {%- if network_mappings.append(map_pair|join(':')) %}{%- endif %} + {%- endif %} + {%- endif %} +{%- endfor %} + +[ml2] +type_drivers = flat,vlan,vxlan,local +tenant_network_types = {{ network_types|join(',') }} +mechanism_drivers = linuxbridge,l2population + + +{% if network_flat_networks %} +[ml2_type_flat] +flat_networks = {{ network_flat_networks|join(',') }} +{% endif %} + + +{% if network_vlan_ranges %} +[ml2_type_vlan] +network_vlan_ranges = {{ network_vlan_ranges|join(',') }} + +[vlans] +tenant_network_type = vlan +network_vlan_ranges = {{ network_vlan_ranges|join(',') }} +{% endif %} + + +{% if network_vxlan_ranges %} +[ml2_type_vxlan] +vxlan_group = {{ neutron_vxlan_group|default('') }} +vni_ranges = {{ network_vxlan_ranges|join(',') }} + + +{% if tunnel_address is defined %} +[vxlan] +enable_vxlan = True +vxlan_group = {{ neutron_vxlan_group|default('') }} +{% if is_metal == true %} +{% set on_metal_tunnel_bridge = 'ansible_' + tunnel_bridge|replace('-', '_') %} +local_ip = {{ hostvars[inventory_hostname][on_metal_tunnel_bridge]['ipv4']['address'] }} +{% else %} +local_ip = {{ tunnel_address }} +{% endif %} +l2_population = True +{% endif %} +{% endif %} + + +[agent] +tunnel_types = vxlan +## VXLAN udp port +# This is set for the vxlan port and while this +# is being set here it's ignored because +# the port is assigned by the kernel +vxlan_udp_port = 4789 + + +{% if network_mappings is defined %} +[linux_bridge] +physical_interface_mappings = {{ network_mappings|join(',') }} +{% endif %} + + +[l2pop] +agent_boot_time = 180 + +[securitygroup] +enable_security_group = True +firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver diff --git a/rpc_deployment/roles/neutron_common/templates/policy.json b/rpc_deployment/roles/neutron_common/templates/policy.json new file mode 100644 index 0000000000..f2dfa0f4b4 --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/policy.json @@ -0,0 +1,140 @@ +{ + "context_is_admin": "role:admin", + "admin_or_owner": "rule:context_is_admin or tenant_id:%(tenant_id)s", + "admin_or_network_owner": "rule:context_is_admin or tenant_id:%(network:tenant_id)s", + "admin_only": "rule:context_is_admin", + "regular_user": "", + "shared": "field:networks:shared=True", + "shared_firewalls": "field:firewalls:shared=True", + "external": "field:networks:router:external=True", + "default": "rule:admin_or_owner", + + "subnets:private:read": "rule:admin_or_owner", + "subnets:private:write": "rule:admin_or_owner", + "subnets:shared:read": "rule:regular_user", + "subnets:shared:write": "rule:admin_only", + + "create_subnet": "rule:admin_or_network_owner", + "get_subnet": "rule:admin_or_owner or rule:shared", + "update_subnet": "rule:admin_or_network_owner", + "delete_subnet": "rule:admin_or_network_owner", + + "create_network": "", + "get_network": "rule:admin_or_owner or rule:shared or rule:external", + "get_network:router:external": "rule:regular_user", + "get_network:segments": "rule:admin_only", + "get_network:provider:network_type": "rule:admin_only", + "get_network:provider:physical_network": "rule:admin_only", + "get_network:provider:segmentation_id": "rule:admin_only", + "get_network:queue_id": "rule:admin_only", + "create_network:shared": "rule:admin_only", + "create_network:router:external": "rule:admin_only", + "create_network:segments": "rule:admin_only", + "create_network:provider:network_type": "rule:admin_only", + "create_network:provider:physical_network": "rule:admin_only", + "create_network:provider:segmentation_id": "rule:admin_only", + "update_network": "rule:admin_or_owner", + "update_network:segments": "rule:admin_only", + "update_network:shared": "rule:admin_only", + "update_network:provider:network_type": "rule:admin_only", + "update_network:provider:physical_network": "rule:admin_only", + "update_network:provider:segmentation_id": "rule:admin_only", + "delete_network": "rule:admin_or_owner", + + "create_port": "", + "create_port:mac_address": "rule:admin_or_network_owner", + "create_port:fixed_ips": "rule:admin_or_network_owner", + "create_port:port_security_enabled": "rule:admin_or_network_owner", + "create_port:binding:host_id": "rule:admin_only", + "create_port:binding:profile": "rule:admin_only", + "create_port:binding:vnic_type": "rule:admin_or_owner", + "create_port:mac_learning_enabled": "rule:admin_or_network_owner", + "get_port": "rule:admin_or_owner", + "get_port:queue_id": "rule:admin_only", + "get_port:binding:vif_type": "rule:admin_only", + "get_port:binding:vif_details": "rule:admin_only", + "get_port:binding:host_id": "rule:admin_only", + "get_port:binding:profile": "rule:admin_only", + "get_port:binding:vnic_type": "rule:admin_or_owner", + "update_port": "rule:admin_or_owner", + "update_port:fixed_ips": "rule:admin_or_network_owner", + "update_port:port_security_enabled": "rule:admin_or_network_owner", + "update_port:binding:host_id": "rule:admin_only", + "update_port:binding:profile": "rule:admin_only", + "update_port:binding:vnic_type": "rule:admin_or_owner", + "update_port:mac_learning_enabled": "rule:admin_or_network_owner", + "delete_port": "rule:admin_or_owner", + + "create_router:external_gateway_info:enable_snat": "rule:admin_only", + "update_router:external_gateway_info:enable_snat": "rule:admin_only", + + "create_firewall": "", + "get_firewall": "rule:admin_or_owner", + "create_firewall:shared": "rule:admin_only", + "get_firewall:shared": "rule:admin_only", + "update_firewall": "rule:admin_or_owner", + "delete_firewall": "rule:admin_or_owner", + + "create_firewall_policy": "", + "get_firewall_policy": "rule:admin_or_owner or rule:shared_firewalls", + "create_firewall_policy:shared": "rule:admin_or_owner", + "update_firewall_policy": "rule:admin_or_owner", + "delete_firewall_policy": "rule:admin_or_owner", + + "create_firewall_rule": "", + "get_firewall_rule": "rule:admin_or_owner or rule:shared_firewalls", + "create_firewall_rule:shared": "rule:admin_or_owner", + "get_firewall_rule:shared": "rule:admin_or_owner", + "update_firewall_rule": "rule:admin_or_owner", + "delete_firewall_rule": "rule:admin_or_owner", + + "create_qos_queue": "rule:admin_only", + "get_qos_queue": "rule:admin_only", + + "update_agent": "rule:admin_only", + "delete_agent": "rule:admin_only", + "get_agent": "rule:admin_only", + + "create_dhcp-network": "rule:admin_only", + "delete_dhcp-network": "rule:admin_only", + "get_dhcp-networks": "rule:admin_only", + "create_l3-router": "rule:admin_only", + "delete_l3-router": "rule:admin_only", + "get_l3-routers": "rule:admin_only", + "get_dhcp-agents": "rule:admin_only", + "get_l3-agents": "rule:admin_only", + "get_loadbalancer-agent": "rule:admin_only", + "get_loadbalancer-pools": "rule:admin_only", + + "create_router": "rule:regular_user", + "get_router": "rule:admin_or_owner", + "update_router:add_router_interface": "rule:admin_or_owner", + "update_router:remove_router_interface": "rule:admin_or_owner", + "delete_router": "rule:admin_or_owner", + + "create_floatingip": "rule:regular_user", + "update_floatingip": "rule:admin_or_owner", + "delete_floatingip": "rule:admin_or_owner", + "get_floatingip": "rule:admin_or_owner", + + "create_network_profile": "rule:admin_only", + "update_network_profile": "rule:admin_only", + "delete_network_profile": "rule:admin_only", + "get_network_profiles": "", + "get_network_profile": "", + "update_policy_profiles": "rule:admin_only", + "get_policy_profiles": "", + "get_policy_profile": "", + + "create_metering_label": "rule:admin_only", + "delete_metering_label": "rule:admin_only", + "get_metering_label": "rule:admin_only", + + "create_metering_label_rule": "rule:admin_only", + "delete_metering_label_rule": "rule:admin_only", + "get_metering_label_rule": "rule:admin_only", + + "get_service_provider": "rule:regular_user", + "get_lsn": "rule:admin_only", + "create_lsn": "rule:admin_only" +} diff --git a/rpc_deployment/roles/neutron_common/templates/rootwrap.d/debug.filters b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/debug.filters new file mode 100644 index 0000000000..b61d960178 --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/debug.filters @@ -0,0 +1,14 @@ +# neutron-rootwrap command filters for nodes on which neutron is +# expected to control network +# +# This file should be owned by (and only-writeable by) the root user + +# format seems to be +# cmd-name: filter-name, raw-command, user, args + +[Filters] + +# This is needed because we should ping +# from inside a namespace which requires root +ping: RegExpFilter, ping, root, ping, -w, \d+, -c, \d+, [0-9\.]+ +ping6: RegExpFilter, ping6, root, ping6, -w, \d+, -c, \d+, [0-9A-Fa-f:]+ diff --git a/rpc_deployment/roles/neutron_common/templates/rootwrap.d/dhcp.filters b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/dhcp.filters new file mode 100644 index 0000000000..88d61e8e30 --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/dhcp.filters @@ -0,0 +1,38 @@ +# neutron-rootwrap command filters for nodes on which neutron is +# expected to control network +# +# This file should be owned by (and only-writeable by) the root user + +# format seems to be +# cmd-name: filter-name, raw-command, user, args + +[Filters] + +# dhcp-agent +dnsmasq: EnvFilter, dnsmasq, root, NEUTRON_NETWORK_ID= +# dhcp-agent uses kill as well, that's handled by the generic KillFilter +# it looks like these are the only signals needed, per +# neutron/agent/linux/dhcp.py +kill_dnsmasq: KillFilter, root, /sbin/dnsmasq, -9, -HUP +kill_dnsmasq_usr: KillFilter, root, /usr/sbin/dnsmasq, -9, -HUP + +ovs-vsctl: CommandFilter, ovs-vsctl, root +ivs-ctl: CommandFilter, ivs-ctl, root +mm-ctl: CommandFilter, mm-ctl, root +dhcp_release: CommandFilter, dhcp_release, root + +# metadata proxy +metadata_proxy: CommandFilter, neutron-ns-metadata-proxy, root +metadata_proxy_quantum: CommandFilter, quantum-ns-metadata-proxy, root +# If installed from source (say, by devstack), the prefix will be +# /usr/local instead of /usr/bin. +metadata_proxy_local: CommandFilter, /usr/local/bin/neutron-ns-metadata-proxy, root +metadata_proxy_local_quantum: CommandFilter, /usr/local/bin/quantum-ns-metadata-proxy, root +# RHEL invocation of the metadata proxy will report /usr/bin/python +kill_metadata: KillFilter, root, /usr/bin/python, -9 +kill_metadata7: KillFilter, root, /usr/bin/python2.7, -9 +kill_metadata6: KillFilter, root, /usr/bin/python2.6, -9 + +# ip_lib +ip: IpFilter, ip, root +ip_exec: IpNetnsExecFilter, ip, root diff --git a/rpc_deployment/roles/neutron_common/templates/rootwrap.d/iptables-firewall.filters b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/iptables-firewall.filters new file mode 100644 index 0000000000..b8a6ab5b3b --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/iptables-firewall.filters @@ -0,0 +1,21 @@ +# neutron-rootwrap command filters for nodes on which neutron is +# expected to control network +# +# This file should be owned by (and only-writeable by) the root user + +# format seems to be +# cmd-name: filter-name, raw-command, user, args + +[Filters] + +# neutron/agent/linux/iptables_manager.py +# "iptables-save", ... +iptables-save: CommandFilter, iptables-save, root +iptables-restore: CommandFilter, iptables-restore, root +ip6tables-save: CommandFilter, ip6tables-save, root +ip6tables-restore: CommandFilter, ip6tables-restore, root + +# neutron/agent/linux/iptables_manager.py +# "iptables", "-A", ... +iptables: CommandFilter, iptables, root +ip6tables: CommandFilter, ip6tables, root diff --git a/rpc_deployment/roles/neutron_common/templates/rootwrap.d/l3.filters b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/l3.filters new file mode 100644 index 0000000000..2031d779ec --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/l3.filters @@ -0,0 +1,41 @@ +# neutron-rootwrap command filters for nodes on which neutron is +# expected to control network +# +# This file should be owned by (and only-writeable by) the root user + +# format seems to be +# cmd-name: filter-name, raw-command, user, args + +[Filters] + +# arping +arping: CommandFilter, arping, root + +# l3_agent +sysctl: CommandFilter, sysctl, root +route: CommandFilter, route, root + +# metadata proxy +metadata_proxy: CommandFilter, neutron-ns-metadata-proxy, root +metadata_proxy_quantum: CommandFilter, quantum-ns-metadata-proxy, root +# If installed from source (say, by devstack), the prefix will be +# /usr/local instead of /usr/bin. +metadata_proxy_local: CommandFilter, /usr/local/bin/neutron-ns-metadata-proxy, root +metadata_proxy_local_quantum: CommandFilter, /usr/local/bin/quantum-ns-metadata-proxy, root +# RHEL invocation of the metadata proxy will report /usr/bin/python +kill_metadata: KillFilter, root, /usr/bin/python, -9 +kill_metadata7: KillFilter, root, /usr/bin/python2.7, -9 +kill_metadata6: KillFilter, root, /usr/bin/python2.6, -9 + +# ip_lib +ip: IpFilter, ip, root +ip_exec: IpNetnsExecFilter, ip, root + +# ovs_lib (if OVSInterfaceDriver is used) +ovs-vsctl: CommandFilter, ovs-vsctl, root + +# iptables_manager +iptables-save: CommandFilter, iptables-save, root +iptables-restore: CommandFilter, iptables-restore, root +ip6tables-save: CommandFilter, ip6tables-save, root +ip6tables-restore: CommandFilter, ip6tables-restore, root diff --git a/rpc_deployment/roles/neutron_common/templates/rootwrap.d/lbaas-haproxy.filters b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/lbaas-haproxy.filters new file mode 100644 index 0000000000..a4134a4198 --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/lbaas-haproxy.filters @@ -0,0 +1,23 @@ +# neutron-rootwrap command filters for nodes on which neutron is +# expected to control network +# +# This file should be owned by (and only-writeable by) the root user + +# format seems to be +# cmd-name: filter-name, raw-command, user, args + +[Filters] + +# haproxy +haproxy: CommandFilter, haproxy, root + +# lbaas-agent uses kill as well, that's handled by the generic KillFilter +kill_haproxy_usr: KillFilter, root, /usr/sbin/haproxy, -9, -HUP + +ovs-vsctl: CommandFilter, ovs-vsctl, root +mm-ctl: CommandFilter, mm-ctl, root + +# ip_lib +ip: IpFilter, ip, root +ip_exec: IpNetnsExecFilter, ip, root +route: CommandFilter, route, root diff --git a/rpc_deployment/roles/neutron_common/templates/rootwrap.d/linuxbridge-plugin.filters b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/linuxbridge-plugin.filters new file mode 100644 index 0000000000..03df39592c --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/linuxbridge-plugin.filters @@ -0,0 +1,19 @@ +# neutron-rootwrap command filters for nodes on which neutron is +# expected to control network +# +# This file should be owned by (and only-writeable by) the root user + +# format seems to be +# cmd-name: filter-name, raw-command, user, args + +[Filters] + +# linuxbridge-agent +# unclear whether both variants are necessary, but I'm transliterating +# from the old mechanism +brctl: CommandFilter, brctl, root +bridge: CommandFilter, bridge, root + +# ip_lib +ip: IpFilter, ip, root +ip_exec: IpNetnsExecFilter, ip, root diff --git a/rpc_deployment/roles/neutron_common/templates/rootwrap.d/nec-plugin.filters b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/nec-plugin.filters new file mode 100644 index 0000000000..89c4cfe355 --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/nec-plugin.filters @@ -0,0 +1,12 @@ +# neutron-rootwrap command filters for nodes on which neutron is +# expected to control network +# +# This file should be owned by (and only-writeable by) the root user + +# format seems to be +# cmd-name: filter-name, raw-command, user, args + +[Filters] + +# nec_neutron_agent +ovs-vsctl: CommandFilter, ovs-vsctl, root diff --git a/rpc_deployment/roles/neutron_common/templates/rootwrap.d/openvswitch-plugin.filters b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/openvswitch-plugin.filters new file mode 100644 index 0000000000..b63a83b943 --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/openvswitch-plugin.filters @@ -0,0 +1,22 @@ +# neutron-rootwrap command filters for nodes on which neutron is +# expected to control network +# +# This file should be owned by (and only-writeable by) the root user + +# format seems to be +# cmd-name: filter-name, raw-command, user, args + +[Filters] + +# openvswitch-agent +# unclear whether both variants are necessary, but I'm transliterating +# from the old mechanism +ovs-vsctl: CommandFilter, ovs-vsctl, root +ovs-ofctl: CommandFilter, ovs-ofctl, root +kill_ovsdb_client: KillFilter, root, /usr/bin/ovsdb-client, -9 +ovsdb-client: CommandFilter, ovsdb-client, root +xe: CommandFilter, xe, root + +# ip_lib +ip: IpFilter, ip, root +ip_exec: IpNetnsExecFilter, ip, root diff --git a/rpc_deployment/roles/neutron_common/templates/rootwrap.d/ryu-plugin.filters b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/ryu-plugin.filters new file mode 100644 index 0000000000..0a70b8bc95 --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/ryu-plugin.filters @@ -0,0 +1,21 @@ +# neutron-rootwrap command filters for nodes on which neutron is +# expected to control network +# +# This file should be owned by (and only-writeable by) the root user + +# format seems to be +# cmd-name: filter-name, raw-command, user, args + +[Filters] + +# ryu-agent +# unclear whether both variants are necessary, but I'm transliterating +# from the old mechanism + +# neutron/plugins/ryu/agent/ryu_neutron_agent.py: +# "ovs-vsctl", "--timeout=2", ... +ovs-vsctl: CommandFilter, ovs-vsctl, root + +# neutron/plugins/ryu/agent/ryu_neutron_agent.py: +# "xe", "vif-param-get", ... +xe: CommandFilter, xe, root diff --git a/rpc_deployment/roles/neutron_common/templates/rootwrap.d/vpnaas.filters b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/vpnaas.filters new file mode 100644 index 0000000000..7848136b9f --- /dev/null +++ b/rpc_deployment/roles/neutron_common/templates/rootwrap.d/vpnaas.filters @@ -0,0 +1,13 @@ +# neutron-rootwrap command filters for nodes on which neutron is +# expected to control network +# +# This file should be owned by (and only-writeable by) the root user + +# format seems to be +# cmd-name: filter-name, raw-command, user, args + +[Filters] + +ip: IpFilter, ip, root +ip_exec: IpNetnsExecFilter, ip, root +openswan: CommandFilter, ipsec, root diff --git a/rpc_deployment/roles/neutron_l3_ha/files/neutron-ha-tool.py b/rpc_deployment/roles/neutron_l3_ha/files/neutron-ha-tool.py new file mode 100644 index 0000000000..c1da04649b --- /dev/null +++ b/rpc_deployment/roles/neutron_l3_ha/files/neutron-ha-tool.py @@ -0,0 +1,549 @@ +#! /usr/bin/env python + +# Copyright 2013 AT&T Services, Inc. +# All Rights Reserved. +# +# 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 logging +import os +import sys +import argparse +import random +import time +from logging.handlers import SysLogHandler +from collections import OrderedDict +from neutronclient.neutron import client + + +LOG = logging.getLogger('neutron-ha-tool') +LOG_FORMAT = '%(asctime)s %(name)-12s %(levelname)-8s %(message)s' +LOG_DATE = '%m-%d %H:%M' +DESCRIPTION = "neutron High Availability Tool" +TAKEOVER_DELAY = int(random.random()*30+30) + + +def parse_args(): + + # ensure environment has necessary items to authenticate + for key in ['OS_TENANT_NAME', 'OS_USERNAME', 'OS_PASSWORD', + 'OS_AUTH_URL']: + if key not in os.environ.keys(): + LOG.exception("Your environment is missing '%s'") + + ap = argparse.ArgumentParser(description=DESCRIPTION) + ap.add_argument('-d', '--debug', action='store_true', + default=False, help='Show debugging output') + ap.add_argument('-q', '--quiet', action='store_true', default=False, + help='Only show error and warning messages') + ap.add_argument('-n', '--noop', action='store_true', default=False, + help='Do not do any modifying operations (dry-run)') + ap.add_argument('--l3-agent-check', action='store_true', default=False, + help='Show routers associated with offline l3 agents') + ap.add_argument('--l3-agent-migrate', action='store_true', default=False, + help='Migrate routers away from offline l3 agents') + ap.add_argument('--l3-agent-rebalance', action='store_true', default=False, + help='Rebalance router count on all l3 agents') + ap.add_argument('--replicate-dhcp', action='store_true', default=False, + help='Replicate DHCP configuration to all agents') + ap.add_argument('--now', action='store_true', default=False, + help='Migrate Routers immediately without a delay.') + ap.add_argument('--insecure', action='store_true', default=False, + help='Explicitly allow neutron-ha-tool to perform ' + '"insecure" SSL (https) requests. The server\'s ' + 'certificate will not be verified against any ' + 'certificate authorities. This option should be used ' + 'with caution.') + return ap.parse_args() + + +def setup_logging(args): + level = logging.INFO + if args.quiet: + level = logging.WARN + if args.debug: + level = logging.DEBUG + logging.basicConfig(level=level, format=LOG_FORMAT, date_fmt=LOG_DATE) + handler = SysLogHandler(address='/dev/log') + syslog_formatter = logging.Formatter('%(name)s: %(levelname)s %(message)s') + handler.setFormatter(syslog_formatter) + LOG.addHandler(handler) + + +def run(args): + try: + ca = os.environ['OS_CACERT'] + except KeyError: + ca = None + + # instantiate client + qclient = client.Client('2.0', auth_url=os.environ['OS_AUTH_URL'], + username=os.environ['OS_USERNAME'], + tenant_name=os.environ['OS_TENANT_NAME'], + password=os.environ['OS_PASSWORD'], + endpoint_type='internalURL', + insecure=args.insecure, + ca_cert=ca) + + # set json return type + qclient.format = 'json' + + if args.l3_agent_check: + LOG.info("Performing L3 Agent Health Check") + l3_agent_check(qclient) + + if args.l3_agent_migrate: + LOG.info("Performing L3 Agent Migration for Offline L3 Agents") + l3_agent_migrate(qclient, args.noop, args.now) + + if args.l3_agent_rebalance: + LOG.info("Rebalancing L3 Agent Router Count") + l3_agent_rebalance(qclient, args.noop) + + if args.replicate_dhcp: + LOG.info("Performing DHCP Replication of Networks to Agents") + replicate_dhcp(qclient, args.noop) + + +def l3_agent_rebalance(qclient, noop=False): + """ + Rebalance l3 agent router count across agents. The number of routers + on each l3 agent will be as close as possible which should help + distribute load as new l3 agents come online. + + :param qclient: A neutronclient + :param noop: Optional noop flag + """ + + # {u'binary': u'neutron-l3-agent', + # u'description': None, + # u'admin_state_up': True, + # u'heartbeat_timestamp': u'2013-07-02 22:20:23', + # u'alive': True, + # u'topic': u'l3_agent', + # u'host': u'o3r3.int.san3.attcompute.com', + # u'agent_type': u'L3 agent', + # u'created_at': u'2013-07-02 14:50:58', + # u'started_at': u'2013-07-02 18:00:55', + # u'id': u'6efe494a-616c-41ea-9c8f-2c592f4d46ff', + # u'configurations': { + # u'router_id': u'', + # u'gateway_external_network_id': u'', + # u'handle_internal_only_routers': True, + # u'use_namespaces': True, + # u'routers': 5, + # u'interfaces': 3, + # u'floating_ips': 9, + # u'interface_driver': + # u'neutron.agent.linux.interface.OVSInterfaceDriver', + # u'ex_gw_ports': 3} + # } + + l3_agent_dict = {} + agents = list_agents(qclient, agent_type='L3 agent') + num_agents = len(agents) + if num_agents <= 1: + LOG.info("No rebalancing required for 1 or fewer agents") + return + + for l3_agent in agents: + l3_agent_dict[l3_agent['id']] = \ + list_routers_on_l3_agent(qclient, l3_agent['id']) + + ordered_l3_agent_dict = OrderedDict(sorted(l3_agent_dict.items(), + key=lambda t: len(t[0]))) + ordered_l3_agent_list = list(ordered_l3_agent_dict) + num_agents = len(ordered_l3_agent_list) + LOG.info("Agent list: %s", ordered_l3_agent_list[0:(num_agents-1/2)+1]) + i = 0 + for agent in ordered_l3_agent_list[0:num_agents-1/2]: + low_agent_id = ordered_l3_agent_list[i] + hgh_agent_id = ordered_l3_agent_list[-(i+1)] + + # do nothing if we end up comparing the same router + if low_agent_id == hgh_agent_id: + continue + + LOG.info("Examining low_agent=%s, high_agent=%s", + low_agent_id, hgh_agent_id) + + low_agent_router_count = len(l3_agent_dict[low_agent_id]) + hgh_agent_router_count = len(l3_agent_dict[hgh_agent_id]) + + LOG.info("Low Count=%s, High Count=%s", + low_agent_router_count, hgh_agent_router_count) + + for router_id in l3_agent_dict[hgh_agent_id]: + if low_agent_router_count >= hgh_agent_router_count: + break + else: + LOG.info("Migrating router=%s from agent=%s to agent=%s", + router_id, hgh_agent_id, low_agent_id) + try: + if not noop: + migrate_router(qclient, router_id, hgh_agent_id, + low_agent_id) + low_agent_router_count += 1 + hgh_agent_router_count -= 1 + except: + LOG.exception("Failed to migrate router=%s from agent=%s " + "to agent=%s", router_id, hgh_agent_id, + low_agent_id) + continue + i += 1 + + +def l3_agent_check(qclient): + """ + Walk the l3 agents searching for agents that are offline. Show routers + that are offline and where we would migrate them to. + + :param qclient: A neutronclient + + """ + + migration_count = 0 + agent_list = list_agents(qclient) + agent_dead_list = agent_dead_id_list(agent_list, 'L3 agent') + agent_alive_list = agent_alive_id_list(agent_list, 'L3 agent') + LOG.info("There are %s offline L3 agents and %s online L3 agents", + len(agent_dead_list), len(agent_alive_list)) + + if len(agent_dead_list) > 0: + for agent_id in agent_dead_list: + LOG.info("Querying agent_id=%s for routers to migrate", agent_id) + router_id_list = list_routers_on_l3_agent(qclient, agent_id) + + for router_id in router_id_list: + try: + target_id = random.choice(agent_alive_list) + except IndexError: + LOG.warn("There are no l3 agents alive we could " + "migrate routers onto.") + target_id = None + + migration_count += 1 + LOG.warn("Would like to migrate router=%s to agent=%s", + router_id, target_id) + + if migration_count > 0: + sys.exit(2) + + +def l3_agent_migrate(qclient, noop=False, now=False): + """ + Walk the l3 agents searching for agents that are offline. For those that + are offline, we will retrieve a list of routers on them and migrate them to + a random l3 agent that is online. + + :param qclient: A neutronclient + :param noop: Optional noop flag + :param now: Optional. If false (the default), we'll wait for a random + amount of time (between 30 and 60 seconds) before migration. If + true, routers are migrated immediately. + + """ + + migration_count = 0 + agent_list = list_agents(qclient) + agent_dead_list = agent_dead_id_list(agent_list, 'L3 agent') + agent_alive_list = agent_alive_id_list(agent_list, 'L3 agent') + LOG.info("There are %s offline L3 agents and %s online L3 agents", + len(agent_dead_list), len(agent_alive_list)) + + if len(agent_dead_list) > 0: + if len(agent_alive_list) < 1: + LOG.exception("There are no l3 agents alive to migrate " + "routers onto") + + timeout = 0 + if not now: + while timeout < TAKEOVER_DELAY: + + agent_list_new = list_agents(qclient) + agent_dead_list_new = agent_dead_id_list(agent_list_new, + 'L3 agent') + if len(agent_dead_list_new) < len(agent_dead_list): + LOG.info("Skipping router failover since an agent came " + "online while ensuring agents offline for %s " + "seconds", TAKEOVER_DELAY) + sys.exit(0) + + LOG.info("Agent found offline for seconds=%s but waiting " + "seconds=%s before migration", + timeout, TAKEOVER_DELAY) + timeout += 1 + time.sleep(1) + + for agent_id in agent_dead_list: + LOG.info("Querying agent_id=%s for routers to migrate", agent_id) + router_id_list = list_routers_on_l3_agent(qclient, agent_id) + + for router_id in router_id_list: + + target_id = random.choice(agent_alive_list) + LOG.info("Migrating router=%s to agent=%s", + router_id, target_id) + + try: + if not noop: + migrate_router(qclient, router_id, agent_id, target_id) + migration_count += 1 + except: + LOG.exception("There was an error migrating a router") + continue + + LOG.info("%s routers required migration from offline L3 agents", + migration_count) + + +def replicate_dhcp(qclient, noop=False): + """ + Retrieve a network list and then probe each DHCP agent to ensure + they have that network assigned. + + :param qclient: A neutronclient + :param noop: Optional noop flag + + """ + + added = 0 + networks = list_networks(qclient) + network_id_list = [n['id'] for n in networks] + agents = list_agents(qclient, agent_type='DHCP agent') + LOG.info("Replicating %s networks to %s DHCP agents", len(networks), + len(agents)) + for dhcp_agent_id in [a['id'] for a in agents]: + networks_on_agent = \ + qclient.list_networks_on_dhcp_agent(dhcp_agent_id)['networks'] + network_id_on_agent = [n['id'] for n in networks_on_agent] + for network_id in network_id_list: + if network_id not in network_id_on_agent: + try: + dhcp_body = {'network_id': network_id} + if not noop: + qclient.add_network_to_dhcp_agent(dhcp_agent_id, + dhcp_body) + LOG.info("Added missing network=%s to dhcp agent=%s", + network_id, dhcp_agent_id) + added += 1 + except: + LOG.exception("Failed to add network_id=%s to" + "dhcp_agent=%s", network_id, dhcp_agent_id) + continue + + LOG.info("Added %s networks to DHCP agents", added) + + +def migrate_router(qclient, router_id, agent_id, target_id): + """ + Returns nothing, and raises on exception + + :param qclient: A neutronclient + :param router_id: The id of the router to migrate + :param agent_id: The id of the l3 agent to migrate from + :param target_id: The id of the l3 agent to migrate to + """ + + # N.B. The neutron API will return "success" even when there is a + # subsequent failure during the add or remove process so we must check to + # ensure the router has been added or removed + + # remove the router from the dead agent + qclient.remove_router_from_l3_agent(agent_id, router_id) + + # ensure it is removed or log an error + if router_id in list_routers_on_l3_agent(qclient, agent_id): + LOG.exception("Failed to remove router_id=%s from agent_id=%s", + router_id, agent_id) + + # add the router id to a live agent + router_body = {'router_id': router_id} + qclient.add_router_to_l3_agent(target_id, router_body) + + # ensure it is removed or log an error + if router_id not in list_routers_on_l3_agent(qclient, target_id): + LOG.exception("Failed to add router_id=%s from agent_id=%s", + router_id, agent_id) + + +def list_networks(qclient): + """ + Return a list of network objects + + :param qclient: A neutronclient + """ + + resp = qclient.list_networks() + LOG.debug("list_networks: %s", resp) + return resp['networks'] + + +def list_dhcp_agent_networks(qclient, agent_id): + """ + Return a list of network ids assigned to a particular DHCP agent + + :param qclient: A neutronclient + :param agent_id: A DHCP agent id + """ + + resp = qclient.list_networks_on_dhcp_agent(agent_id) + LOG.debug("list_networks_on_dhcp_agent: %s", resp) + return [s['id'] for s in resp['networks']] + + +def list_routers(qclient): + """ + Return a list of router objects + + :param qclient: A neutronclient + + # {'routers': [ + # {u'status': u'ACTIVE', + # u'external_gateway_info': + # {u'network_id': u'b970297c-d80e-4527-86d7-e49d2da9fdef'}, + # u'name': u'router1', + # u'admin_state_up': True, + # u'tenant_id': u'5603b97ee7f047ea999e25492c7fcb23', + # u'routes': [], + # u'id': u'0a122e5c-1623-412e-8c53-a1e21d1daff8'} + # ]} + + """ + + resp = qclient.list_routers() + LOG.debug("list_routers: %s", resp) + return resp['routers'] + + +def list_routers_on_l3_agent(qclient, agent_id): + """ + Return a list of router ids on an agent + + :param qclient: A neutronclient + """ + + resp = qclient.list_routers_on_l3_agent(agent_id) + LOG.debug("list_routers_on_l3_agent: %s", resp) + return [r['id'] for r in resp['routers']] + + +def list_agents(qclient, agent_type=None): + """Return a list of agent objects + + :param qclient: A neutronclient + + + # {u'agents': [ + + # {u'binary': u'neutron-openvswitch-agent', + # u'description': None, + # u'admin_state_up': True, + # u'heartbeat_timestamp': u'2013-07-02 22:20:25', + # u'alive': True, + # u'topic': u'N/A', + # u'host': u'o3r3.int.san3.attcompute.com', + # u'agent_type': u'Open vSwitch agent', + # u'created_at': u'2013-07-02 14:50:57', + # u'started_at': u'2013-07-02 14:50:57', + # u'id': u'3a577f1d-d86e-4f1a-a395-8d4c8e4df1e2', + # u'configurations': {u'devices': 10}}, + + # {u'binary': u'neutron-dhcp-agent', + # u'description': None, + # u'admin_state_up': True, + # u'heartbeat_timestamp': u'2013-07-02 22:20:23', + # u'alive': True, + # u'topic': u'dhcp_agent', + # u'host': u'o5r4.int.san3.attcompute.com', + # u'agent_type': u'DHCP agent', + # u'created_at': u'2013-06-26 16:21:02', + # u'started_at': u'2013-06-28 13:32:52', + # u'id': u'3e8be28e-05a0-472b-9288-a59f8d8d2271', + # u'configurations': { + # u'subnets': 4, + # u'use_namespaces': True, + # u'dhcp_driver': u'neutron.agent.linux.dhcp.Dnsmasq', + # u'networks': 4, + # u'dhcp_lease_time': 120, + # u'ports': 38}}, + + + # {u'binary': u'neutron-l3-agent', + # u'description': None, + # u'admin_state_up': True, + # u'heartbeat_timestamp': u'2013-07-02 22:20:23', + # u'alive': True, + # u'topic': u'l3_agent', + # u'host': u'o3r3.int.san3.attcompute.com', + # u'agent_type': u'L3 agent', + # u'created_at': u'2013-07-02 14:50:58', + # u'started_at': u'2013-07-02 18:00:55', + # u'id': u'6efe494a-616c-41ea-9c8f-2c592f4d46ff', + # u'configurations': { + # u'router_id': u'', + # u'gateway_external_network_id': u'', + # u'handle_internal_only_routers': True, + # u'use_namespaces': True, + # u'routers': 5, + # u'interfaces': 3, + # u'floating_ips': 9, + # u'interface_driver': + # u'neutron.agent.linux.interface.OVSInterfaceDriver', + # u'ex_gw_ports': 3}}, + + """ + + resp = qclient.list_agents() + LOG.debug("list_agents: %s", resp) + if agent_type: + return [agent for agent in resp['agents'] + if agent['agent_type'] == agent_type] + return resp['agents'] + + +def agent_alive_id_list(agent_list, agent_type): + """ + Return a list of agents that are alive from an API list of agents + + :param agent_list: API response for list_agents() + + """ + return [agent['id'] for agent in agent_list + if agent['agent_type'] == agent_type and agent['alive'] is True] + + +def agent_dead_id_list(agent_list, agent_type): + """ + Return a list of agents that are dead from an API list of agents + + :param agent_list: API response for list_agents() + + """ + return [agent['id'] for agent in agent_list + if agent['agent_type'] == agent_type and agent['alive'] is False] + + +if __name__ == '__main__': + args = parse_args() + setup_logging(args) + + try: + run(args) + sys.exit(0) + except Exception as err: + LOG.error(err) + sys.exit(1) + except KeyboardInterrupt: + sys.exit(1) diff --git a/rpc_deployment/roles/neutron_l3_ha/tasks/main.yml b/rpc_deployment/roles/neutron_l3_ha/tasks/main.yml new file mode 100644 index 0000000000..a5465b9385 --- /dev/null +++ b/rpc_deployment/roles/neutron_l3_ha/tasks/main.yml @@ -0,0 +1,42 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Drop AT&T neutron ha tool + copy: + src: "neutron-ha-tool.py" + dest: "/opt/neutron-ha-tool.py" + owner: "root" + group: "root" + mode: "0755" + +- name: Convert the hostname to an int + name2int: + name: "{{ inventory_hostname }}" + register: hashed_name + +- name: Create Neutron HA + cron: + name: "{{ item.name }}" + minute: "*/1" + day: "*" + hour: "*" + month: "*" + state: present + job: "sleep {{ hashed_name.int_value }} && . /root/openrc && /opt/neutron-ha-tool.py {{ item.command }}" + user: root + cron_file: "{{ item.name }}" + with_items: + - { name: "l3_agent_migrate", command: "--l3-agent-migrate" } + - { name: "replicate_dhcp", command: "--replicate-dhcp" } diff --git a/rpc_deployment/roles/neutron_setup/tasks/main.yml b/rpc_deployment/roles/neutron_setup/tasks/main.yml new file mode 100644 index 0000000000..804396634c --- /dev/null +++ b/rpc_deployment/roles/neutron_setup/tasks/main.yml @@ -0,0 +1,38 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Perform a Neutron DB Upgrade + command: > + neutron-db-manage --config-file {{ neutron_config }} + --config-file {{ neutron_plugin }} + upgrade {{ neutron_revision }} + tags: + - neutron_upgrade + +- name: Check for DB revision + shell: "neutron-db-manage history | grep -w 'Revision ID: {{ neutron_revision }}'" + register: neutron_dbmanage + ignore_errors: True + tags: + - neutron_stamp + +- name: Perform a Neutron DB Stamp + command: > + neutron-db-manage --config-file {{ neutron_config }} + --config-file {{ neutron_plugin }} + stamp {{ neutron_revision }} + when: neutron_dbmanage.rc != 0 + tags: + - neutron_stamp diff --git a/rpc_deployment/roles/nova_common/tasks/main.yml b/rpc_deployment/roles/nova_common/tasks/main.yml new file mode 100644 index 0000000000..64dc335e5e --- /dev/null +++ b/rpc_deployment/roles/nova_common/tasks/main.yml @@ -0,0 +1,48 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Get glance admin endpoint + shell: > + . /root/openrc && keystone endpoint-list | grep "$(keystone service-list | awk '/image/ {print $2}')" | awk '{print $10}' + register: glanceendpoint + +- name: Get neutron admin endpoint + shell: > + . /root/openrc && keystone endpoint-list | grep "$(keystone service-list | awk '/network/ {print $2}')" | awk '{print $10}' + register: neutronendpoint + +- name: Set variable data + set_fact: + neutron_service_adminurl: "{{ neutronendpoint.stdout }}" + glance_service_adminurl: "{{ glanceendpoint.stdout }}" + +- name: Setup nova config + template: > + src={{ item }} + dest=/etc/nova/{{ item }} + owner={{ system_user }} + group={{ system_group }} + with_items: + - nova.conf + - rootwrap.conf + - rootwrap.d/api-metadata.filters + - rootwrap.d/baremetal-compute-ipmi.filters + - rootwrap.d/baremetal-deploy-helper.filters + - rootwrap.d/compute.filters + - rootwrap.d/network.filters + - policy.json + - cells.json + - api-paste.ini + notify: Restart os service diff --git a/rpc_deployment/roles/nova_common/templates/api-paste.ini b/rpc_deployment/roles/nova_common/templates/api-paste.ini new file mode 100644 index 0000000000..0e6244a1eb --- /dev/null +++ b/rpc_deployment/roles/nova_common/templates/api-paste.ini @@ -0,0 +1,112 @@ +############ +# Metadata # +############ +[composite:metadata] +use = egg:Paste#urlmap +/: meta + +[pipeline:meta] +pipeline = ec2faultwrap logrequest metaapp + +[app:metaapp] +paste.app_factory = nova.api.metadata.handler:MetadataRequestHandler.factory + +####### +# EC2 # +####### + +[composite:ec2] +use = egg:Paste#urlmap +/services/Cloud: ec2cloud + +[composite:ec2cloud] +use = call:nova.api.auth:pipeline_factory +noauth = ec2faultwrap logrequest ec2noauth cloudrequest validator ec2executor +keystone = ec2faultwrap logrequest ec2keystoneauth cloudrequest validator ec2executor + +[filter:ec2faultwrap] +paste.filter_factory = nova.api.ec2:FaultWrapper.factory + +[filter:logrequest] +paste.filter_factory = nova.api.ec2:RequestLogging.factory + +[filter:ec2lockout] +paste.filter_factory = nova.api.ec2:Lockout.factory + +[filter:ec2keystoneauth] +paste.filter_factory = nova.api.ec2:EC2KeystoneAuth.factory + +[filter:ec2noauth] +paste.filter_factory = nova.api.ec2:NoAuth.factory + +[filter:cloudrequest] +controller = nova.api.ec2.cloud.CloudController +paste.filter_factory = nova.api.ec2:Requestify.factory + +[filter:authorizer] +paste.filter_factory = nova.api.ec2:Authorizer.factory + +[filter:validator] +paste.filter_factory = nova.api.ec2:Validator.factory + +[app:ec2executor] +paste.app_factory = nova.api.ec2:Executor.factory + +############# +# OpenStack # +############# + +[composite:osapi_compute] +use = call:nova.api.openstack.urlmap:urlmap_factory +/: oscomputeversions +/v1.1: openstack_compute_api_v2 +/v2: openstack_compute_api_v2 +/v3: openstack_compute_api_v3 + +[composite:openstack_compute_api_v2] +use = call:nova.api.auth:pipeline_factory +noauth = faultwrap sizelimit noauth ratelimit osapi_compute_app_v2 +keystone = faultwrap sizelimit authtoken keystonecontext ratelimit osapi_compute_app_v2 +keystone_nolimit = faultwrap sizelimit authtoken keystonecontext osapi_compute_app_v2 + +[composite:openstack_compute_api_v3] +use = call:nova.api.auth:pipeline_factory_v3 +noauth = faultwrap sizelimit noauth_v3 osapi_compute_app_v3 +keystone = faultwrap sizelimit authtoken keystonecontext osapi_compute_app_v3 + +[filter:faultwrap] +paste.filter_factory = nova.api.openstack:FaultWrapper.factory + +[filter:noauth] +paste.filter_factory = nova.api.openstack.auth:NoAuthMiddleware.factory + +[filter:noauth_v3] +paste.filter_factory = nova.api.openstack.auth:NoAuthMiddlewareV3.factory + +[filter:ratelimit] +paste.filter_factory = nova.api.openstack.compute.limits:RateLimitingMiddleware.factory + +[filter:sizelimit] +paste.filter_factory = nova.api.sizelimit:RequestBodySizeLimiter.factory + +[app:osapi_compute_app_v2] +paste.app_factory = nova.api.openstack.compute:APIRouter.factory + +[app:osapi_compute_app_v3] +paste.app_factory = nova.api.openstack.compute:APIRouterV3.factory + +[pipeline:oscomputeversions] +pipeline = faultwrap oscomputeversionapp + +[app:oscomputeversionapp] +paste.app_factory = nova.api.openstack.compute.versions:Versions.factory + +########## +# Shared # +########## + +[filter:keystonecontext] +paste.filter_factory = nova.api.auth:NovaKeystoneContext.factory + +[filter:authtoken] +paste.filter_factory = keystonemiddleware.auth_token:filter_factory diff --git a/rpc_deployment/roles/nova_common/templates/cells.json b/rpc_deployment/roles/nova_common/templates/cells.json new file mode 100644 index 0000000000..cc74930d4d --- /dev/null +++ b/rpc_deployment/roles/nova_common/templates/cells.json @@ -0,0 +1,26 @@ +{ + "parent": { + "name": "parent", + "api_url": "http://api.example.com:8774", + "transport_url": "rabbit://rabbit.example.com", + "weight_offset": 0.0, + "weight_scale": 1.0, + "is_parent": true + }, + "cell1": { + "name": "cell1", + "api_url": "http://api.example.com:8774", + "transport_url": "rabbit://rabbit1.example.com", + "weight_offset": 0.0, + "weight_scale": 1.0, + "is_parent": false + }, + "cell2": { + "name": "cell2", + "api_url": "http://api.example.com:8774", + "transport_url": "rabbit://rabbit2.example.com", + "weight_offset": 0.0, + "weight_scale": 1.0, + "is_parent": false + } +} diff --git a/rpc_deployment/roles/nova_common/templates/nova.conf b/rpc_deployment/roles/nova_common/templates/nova.conf new file mode 100644 index 0000000000..e304dafea8 --- /dev/null +++ b/rpc_deployment/roles/nova_common/templates/nova.conf @@ -0,0 +1,133 @@ +[DEFAULT] +debug = {{ debug }} +verbose = {{ verbose }} + +log_dir=/var/log/nova + +## VIF +linuxnet_interface_driver={{ nova_linuxnet_interface_driver }} +libvirt_vif_driver={{ nova_libvirt_vif_driver }} +libvirt_vif_type=ethernet +vif_plugging_timeout = 10 +vif_plugging_is_fatal = False + +default_ephemeral_format = ext4 +service_neutron_metadata_proxy = True + +auth_strategy = keystone +security_group_api = neutron + +neutron_url = {{ neutron_service_adminurl }} +neutron_region_name = {{ service_region }} +neutron_admin_tenant_name = {{ hostvars[groups['neutron_all'][0]]['service_admin_tenant_name'] }} +neutron_auth_strategy = keystone +neutron_admin_auth_url = {{ auth_admin_uri }} +neutron_admin_password = {{ neutron_service_password }} +neutron_admin_username = {{ hostvars[groups['neutron_all'][0]]['service_admin_username'] }} +neutron_metadata_proxy_shared_secret = {{ nova_metadata_proxy_shared_secret }} + +network_api_class = nova.network.neutronv2.api.API + +firewall_driver = {{ nova_firewall_driver }} +compute_driver = {{ nova_compute_driver }} + +cinder_catalog_info = volume:cinder:internalURL +glance_api_servers={{ glance_service_adminurl }} + + +## Rabbit / RPC +amqp_auto_delete = False +rabbit_port={{ rabbit_port }} +rabbit_userid={{ rabbit_userid }} +rabbit_password={{ rabbit_password }} +rpc_backend={{ rpc_backend }} +rabbit_hosts = {{ rabbit_hosts }} + + +## VNC +# disabled, see spice section +vnc_enabled = False + + +force_config_drive = always +instances_path = /var/lib/nova/instances +lock_path=/var/lock/nova +state_path=/var/lib/nova +enabled_apis = osapi_compute,metadata,ec2 +instance_name_template = instance-%08x + + + +my_ip = {{ container_address }} +s3_port = 3333 +s3_host = {{ ansible_ssh_host }} +ec2_dmz_host = {{ external_vip_address }} + + +default_floating_pool = public +force_dhcp_release = True +dhcpbridge_flagfile = /etc/nova/nova.conf + + +scheduler_driver = nova.scheduler.filter_scheduler.FilterScheduler +rootwrap_config = /etc/nova/rootwrap.conf +api_paste_config = /etc/nova/api-paste.ini + + +allow_resize_to_same_host = False + +# Fix for regression pr-376 +max_age = {{ nova_max_age }} + +{% if nova_html5proxy_base_url is defined%} +[spice] +agent_enabled = {{ nova_console_agent_enabled|default('True') }} +enabled = {{ nova_console_agent_enabled|default('True') }} +keymap = {{ nova_console_keymap|default('en-us') }} +# Console Url and binds +html5proxy_base_url = {{ nova_html5proxy_base_url }} +server_listen = {{ container_address }} +server_proxyclient_address = {{ container_address }} +{% endif %} + + +[conductor] +use_local=false +topic=conductor +manager=nova.conductor.manager.ConductorManager + + +[database] +connection = mysql://{{ container_mysql_user }}:{{ container_mysql_password }}@{{ mysql_address }}/{{ container_database }}?charset=utf8 + + +[osapi_v3] +enabled = True + + +[keystone_authtoken] +signing_dir = /var/lib/nova/cache/api +identity_uri = {{ auth_protocol }}://{{ auth_host }}:{{ auth_port }} +admin_password = {{ service_admin_password }} +admin_user = {{ service_admin_username }} +admin_tenant_name = {{ service_admin_tenant_name }} + +memcached_servers = {{ internal_vip_address }}:{{ memcached_port }} +token_cache_time = 300 +revocation_cache_time = 60 + +# if your memcached server is shared, use these settings to avoid cache poisoning +memcache_security_strategy = ENCRYPT +memcache_secret_key = {{ memcached_secret_key }} + +# if your keystone deployment uses PKI, and you value security over performance: +check_revocations_for_cached = {{ hostvars[groups['keystone_all'][0]]['keystone_use_pki'] }} + + +[libvirt] +vif_driver = {{ nova_libvirt_vif_driver }} +inject_partition = -2 +use_usb_tablet = False +use_virtio_for_bridges=True +cpu_mode = {{ nova_cpu_mode }} +virt_type = {{ virt_type }} diff --git a/rpc_deployment/roles/nova_common/templates/policy.json b/rpc_deployment/roles/nova_common/templates/policy.json new file mode 100644 index 0000000000..61aed1ba8c --- /dev/null +++ b/rpc_deployment/roles/nova_common/templates/policy.json @@ -0,0 +1,324 @@ +{ + "context_is_admin": "role:admin", + "admin_or_owner": "is_admin:True or project_id:%(project_id)s", + "default": "rule:admin_or_owner", + + "cells_scheduler_filter:TargetCellFilter": "is_admin:True", + + "compute:create": "", + "compute:create:attach_network": "", + "compute:create:attach_volume": "", + "compute:create:forced_host": "is_admin:True", + "compute:get_all": "", + "compute:get_all_tenants": "", + "compute:start": "rule:admin_or_owner", + "compute:stop": "rule:admin_or_owner", + "compute:unlock_override": "rule:admin_api", + + "compute:shelve": "", + "compute:shelve_offload": "", + "compute:unshelve": "", + + "compute:volume_snapshot_create": "", + "compute:volume_snapshot_delete": "", + + "admin_api": "is_admin:True", + "compute:v3:servers:start": "rule:admin_or_owner", + "compute:v3:servers:stop": "rule:admin_or_owner", + "compute_extension:v3:os-access-ips:discoverable": "", + "compute_extension:v3:os-access-ips": "", + "compute_extension:accounts": "rule:admin_api", + "compute_extension:admin_actions": "rule:admin_api", + "compute_extension:admin_actions:pause": "rule:admin_or_owner", + "compute_extension:admin_actions:unpause": "rule:admin_or_owner", + "compute_extension:admin_actions:suspend": "rule:admin_or_owner", + "compute_extension:admin_actions:resume": "rule:admin_or_owner", + "compute_extension:admin_actions:lock": "rule:admin_or_owner", + "compute_extension:admin_actions:unlock": "rule:admin_or_owner", + "compute_extension:admin_actions:resetNetwork": "rule:admin_api", + "compute_extension:admin_actions:injectNetworkInfo": "rule:admin_api", + "compute_extension:admin_actions:createBackup": "rule:admin_or_owner", + "compute_extension:admin_actions:migrateLive": "rule:admin_api", + "compute_extension:admin_actions:resetState": "rule:admin_api", + "compute_extension:admin_actions:migrate": "rule:admin_api", + "compute_extension:v3:os-admin-actions": "rule:admin_api", + "compute_extension:v3:os-admin-actions:discoverable": "", + "compute_extension:v3:os-admin-actions:reset_network": "rule:admin_api", + "compute_extension:v3:os-admin-actions:inject_network_info": "rule:admin_api", + "compute_extension:v3:os-admin-actions:reset_state": "rule:admin_api", + "compute_extension:v3:os-admin-password": "", + "compute_extension:v3:os-admin-password:discoverable": "", + "compute_extension:aggregates": "rule:admin_api", + "compute_extension:v3:os-aggregates:discoverable": "", + "compute_extension:v3:os-aggregates:index": "rule:admin_api", + "compute_extension:v3:os-aggregates:create": "rule:admin_api", + "compute_extension:v3:os-aggregates:show": "rule:admin_api", + "compute_extension:v3:os-aggregates:update": "rule:admin_api", + "compute_extension:v3:os-aggregates:delete": "rule:admin_api", + "compute_extension:v3:os-aggregates:add_host": "rule:admin_api", + "compute_extension:v3:os-aggregates:remove_host": "rule:admin_api", + "compute_extension:v3:os-aggregates:set_metadata": "rule:admin_api", + "compute_extension:agents": "rule:admin_api", + "compute_extension:v3:os-agents": "rule:admin_api", + "compute_extension:v3:os-agents:discoverable": "", + "compute_extension:attach_interfaces": "", + "compute_extension:v3:os-attach-interfaces": "", + "compute_extension:v3:os-attach-interfaces:discoverable": "", + "compute_extension:baremetal_nodes": "rule:admin_api", + "compute_extension:cells": "rule:admin_api", + "compute_extension:v3:os-cells": "rule:admin_api", + "compute_extension:v3:os-cells:discoverable": "", + "compute_extension:certificates": "", + "compute_extension:v3:os-certificates:create": "", + "compute_extension:v3:os-certificates:show": "", + "compute_extension:v3:os-certificates:discoverable": "", + "compute_extension:cloudpipe": "rule:admin_api", + "compute_extension:cloudpipe_update": "rule:admin_api", + "compute_extension:console_output": "", + "compute_extension:v3:consoles:discoverable": "", + "compute_extension:v3:os-console-output:discoverable": "", + "compute_extension:v3:os-console-output": "", + "compute_extension:consoles": "", + "compute_extension:v3:os-remote-consoles": "", + "compute_extension:v3:os-remote-consoles:discoverable": "", + "compute_extension:createserverext": "", + "compute_extension:v3:os-create-backup:discoverable": "", + "compute_extension:v3:os-create-backup": "rule:admin_or_owner", + "compute_extension:deferred_delete": "", + "compute_extension:v3:os-deferred-delete": "", + "compute_extension:v3:os-deferred-delete:discoverable": "", + "compute_extension:disk_config": "", + "compute_extension:evacuate": "rule:admin_api", + "compute_extension:v3:os-evacuate": "rule:admin_api", + "compute_extension:v3:os-evacuate:discoverable": "", + "compute_extension:extended_server_attributes": "rule:admin_api", + "compute_extension:v3:os-extended-server-attributes": "rule:admin_api", + "compute_extension:v3:os-extended-server-attributes:discoverable": "", + "compute_extension:extended_status": "", + "compute_extension:v3:os-extended-status": "", + "compute_extension:v3:os-extended-status:discoverable": "", + "compute_extension:extended_availability_zone": "", + "compute_extension:v3:os-extended-availability-zone": "", + "compute_extension:v3:os-extended-availability-zone:discoverable": "", + "compute_extension:extended_ips": "", + "compute_extension:extended_ips_mac": "", + "compute_extension:extended_vif_net": "", + "compute_extension:v3:extension_info:discoverable": "", + "compute_extension:extended_volumes": "", + "compute_extension:v3:os-extended-volumes": "", + "compute_extension:v3:os-extended-volumes:swap": "", + "compute_extension:v3:os-extended-volumes:discoverable": "", + "compute_extension:v3:os-extended-volumes:attach": "", + "compute_extension:v3:os-extended-volumes:detach": "", + "compute_extension:fixed_ips": "rule:admin_api", + "compute_extension:flavor_access": "", + "compute_extension:flavor_access:addTenantAccess": "rule:admin_api", + "compute_extension:flavor_access:removeTenantAccess": "rule:admin_api", + "compute_extension:v3:flavor-access": "", + "compute_extension:v3:flavor-access:discoverable": "", + "compute_extension:v3:flavor-access:remove_tenant_access": "rule:admin_api", + "compute_extension:v3:flavor-access:add_tenant_access": "rule:admin_api", + "compute_extension:flavor_disabled": "", + "compute_extension:flavor_rxtx": "", + "compute_extension:v3:os-flavor-rxtx": "", + "compute_extension:v3:os-flavor-rxtx:discoverable": "", + "compute_extension:flavor_swap": "", + "compute_extension:flavorextradata": "", + "compute_extension:flavorextraspecs:index": "", + "compute_extension:flavorextraspecs:show": "", + "compute_extension:flavorextraspecs:create": "rule:admin_api", + "compute_extension:flavorextraspecs:update": "rule:admin_api", + "compute_extension:flavorextraspecs:delete": "rule:admin_api", + "compute_extension:v3:flavors:discoverable": "", + "compute_extension:v3:flavor-extra-specs:discoverable": "", + "compute_extension:v3:flavor-extra-specs:index": "", + "compute_extension:v3:flavor-extra-specs:show": "", + "compute_extension:v3:flavor-extra-specs:create": "rule:admin_api", + "compute_extension:v3:flavor-extra-specs:update": "rule:admin_api", + "compute_extension:v3:flavor-extra-specs:delete": "rule:admin_api", + "compute_extension:flavormanage": "rule:admin_api", + "compute_extension:v3:flavor-manage": "rule:admin_api", + "compute_extension:floating_ip_dns": "", + "compute_extension:floating_ip_pools": "", + "compute_extension:floating_ips": "", + "compute_extension:floating_ips_bulk": "rule:admin_api", + "compute_extension:fping": "", + "compute_extension:fping:all_tenants": "rule:admin_api", + "compute_extension:hide_server_addresses": "is_admin:False", + "compute_extension:v3:os-hide-server-addresses": "is_admin:False", + "compute_extension:v3:os-hide-server-addresses:discoverable": "", + "compute_extension:hosts": "rule:admin_api", + "compute_extension:v3:os-hosts": "rule:admin_api", + "compute_extension:v3:os-hosts:discoverable": "", + "compute_extension:hypervisors": "rule:admin_api", + "compute_extension:v3:os-hypervisors": "rule:admin_api", + "compute_extension:v3:os-hypervisors:discoverable": "", + "compute_extension:image_size": "", + "compute_extension:instance_actions": "", + "compute_extension:v3:os-instance-actions": "", + "compute_extension:v3:os-instance-actions:discoverable": "", + "compute_extension:instance_actions:events": "rule:admin_api", + "compute_extension:v3:os-instance-actions:events": "rule:admin_api", + "compute_extension:instance_usage_audit_log": "rule:admin_api", + "compute_extension:v3:ips:discoverable": "", + "compute_extension:keypairs": "", + "compute_extension:keypairs:index": "", + "compute_extension:keypairs:show": "", + "compute_extension:keypairs:create": "", + "compute_extension:keypairs:delete": "", + "compute_extension:v3:keypairs:discoverable": "", + "compute_extension:v3:keypairs": "", + "compute_extension:v3:keypairs:index": "", + "compute_extension:v3:keypairs:show": "", + "compute_extension:v3:keypairs:create": "", + "compute_extension:v3:keypairs:delete": "", + "compute_extension:v3:os-lock-server:discoverable": "", + "compute_extension:v3:os-lock-server:lock": "rule:admin_or_owner", + "compute_extension:v3:os-lock-server:unlock": "rule:admin_or_owner", + "compute_extension:v3:os-migrate-server:discoverable": "", + "compute_extension:v3:os-migrate-server:migrate": "rule:admin_api", + "compute_extension:v3:os-migrate-server:migrate_live": "rule:admin_api", + "compute_extension:multinic": "", + "compute_extension:v3:os-multinic": "", + "compute_extension:v3:os-multinic:discoverable": "", + "compute_extension:networks": "rule:admin_api", + "compute_extension:networks:view": "", + "compute_extension:networks_associate": "rule:admin_api", + "compute_extension:v3:os-pause-server:discoverable": "", + "compute_extension:v3:os-pause-server:pause": "rule:admin_or_owner", + "compute_extension:v3:os-pause-server:unpause": "rule:admin_or_owner", + "compute_extension:v3:os-pci:pci_servers": "", + "compute_extension:v3:os-pci:discoverable": "", + "compute_extension:v3:os-pci:index": "rule:admin_api", + "compute_extension:v3:os-pci:detail": "rule:admin_api", + "compute_extension:v3:os-pci:show": "rule:admin_api", + "compute_extension:quotas:show": "", + "compute_extension:quotas:update": "rule:admin_api", + "compute_extension:quotas:delete": "rule:admin_api", + "compute_extension:v3:os-quota-sets:discoverable": "", + "compute_extension:v3:os-quota-sets:show": "", + "compute_extension:v3:os-quota-sets:update": "rule:admin_api", + "compute_extension:v3:os-quota-sets:delete": "rule:admin_api", + "compute_extension:v3:os-quota-sets:detail": "rule:admin_api", + "compute_extension:quota_classes": "", + "compute_extension:rescue": "", + "compute_extension:v3:os-rescue": "", + "compute_extension:v3:os-rescue:discoverable": "", + "compute_extension:v3:os-scheduler-hints:discoverable": "", + "compute_extension:security_group_default_rules": "rule:admin_api", + "compute_extension:security_groups": "", + "compute_extension:v3:os-security-groups": "", + "compute_extension:v3:os-security-groups:discoverable": "", + "compute_extension:server_diagnostics": "rule:admin_api", + "compute_extension:v3:os-server-diagnostics": "rule:admin_api", + "compute_extension:v3:os-server-diagnostics:discoverable": "", + "compute_extension:server_groups": "", + "compute_extension:server_password": "", + "compute_extension:v3:os-server-password": "", + "compute_extension:v3:os-server-password:discoverable": "", + "compute_extension:server_usage": "", + "compute_extension:v3:os-server-usage": "", + "compute_extension:v3:os-server-usage:discoverable": "", + "compute_extension:services": "rule:admin_api", + "compute_extension:v3:os-services": "rule:admin_api", + "compute_extension:v3:os-services:discoverable": "", + "compute_extension:v3:server-metadata:discoverable": "", + "compute_extension:v3:servers:discoverable": "", + "compute_extension:shelve": "", + "compute_extension:shelveOffload": "rule:admin_api", + "compute_extension:v3:os-shelve:shelve": "", + "compute_extension:v3:os-shelve:shelve:discoverable": "", + "compute_extension:v3:os-shelve:shelve_offload": "rule:admin_api", + "compute_extension:simple_tenant_usage:show": "rule:admin_or_owner", + "compute_extension:v3:os-suspend-server:discoverable": "", + "compute_extension:v3:os-suspend-server:suspend": "rule:admin_or_owner", + "compute_extension:v3:os-suspend-server:resume": "rule:admin_or_owner", + "compute_extension:simple_tenant_usage:list": "rule:admin_api", + "compute_extension:unshelve": "", + "compute_extension:v3:os-shelve:unshelve": "", + "compute_extension:users": "rule:admin_api", + "compute_extension:v3:os-user-data:discoverable": "", + "compute_extension:virtual_interfaces": "", + "compute_extension:virtual_storage_arrays": "", + "compute_extension:volumes": "", + "compute_extension:volume_attachments:index": "", + "compute_extension:volume_attachments:show": "", + "compute_extension:volume_attachments:create": "", + "compute_extension:volume_attachments:update": "", + "compute_extension:volume_attachments:delete": "", + "compute_extension:volumetypes": "", + "compute_extension:availability_zone:list": "", + "compute_extension:v3:os-availability-zone:list": "", + "compute_extension:v3:os-availability-zone:discoverable": "", + "compute_extension:availability_zone:detail": "rule:admin_api", + "compute_extension:v3:os-availability-zone:detail": "rule:admin_api", + "compute_extension:used_limits_for_admin": "rule:admin_api", + "compute_extension:migrations:index": "rule:admin_api", + "compute_extension:v3:os-migrations:index": "rule:admin_api", + "compute_extension:v3:os-migrations:discoverable": "", + "compute_extension:os-assisted-volume-snapshots:create": "rule:admin_api", + "compute_extension:os-assisted-volume-snapshots:delete": "rule:admin_api", + "compute_extension:console_auth_tokens": "rule:admin_api", + "compute_extension:v3:os-console-auth-tokens": "rule:admin_api", + "compute_extension:os-server-external-events:create": "rule:admin_api", + "compute_extension:v3:os-server-external-events:create": "rule:admin_api", + + "volume:create": "", + "volume:get_all": "", + "volume:get_volume_metadata": "", + "volume:get_snapshot": "", + "volume:get_all_snapshots": "", + + + "volume_extension:types_manage": "rule:admin_api", + "volume_extension:types_extra_specs": "rule:admin_api", + "volume_extension:volume_admin_actions:reset_status": "rule:admin_api", + "volume_extension:snapshot_admin_actions:reset_status": "rule:admin_api", + "volume_extension:volume_admin_actions:force_delete": "rule:admin_api", + + + "network:get_all": "", + "network:get": "", + "network:create": "", + "network:delete": "", + "network:associate": "", + "network:disassociate": "", + "network:get_vifs_by_instance": "", + "network:allocate_for_instance": "", + "network:deallocate_for_instance": "", + "network:validate_networks": "", + "network:get_instance_uuids_by_ip_filter": "", + "network:get_instance_id_by_floating_address": "", + "network:setup_networks_on_host": "", + "network:get_backdoor_port": "", + + "network:get_floating_ip": "", + "network:get_floating_ip_pools": "", + "network:get_floating_ip_by_address": "", + "network:get_floating_ips_by_project": "", + "network:get_floating_ips_by_fixed_address": "", + "network:allocate_floating_ip": "", + "network:deallocate_floating_ip": "", + "network:associate_floating_ip": "", + "network:disassociate_floating_ip": "", + "network:release_floating_ip": "", + "network:migrate_instance_start": "", + "network:migrate_instance_finish": "", + + "network:get_fixed_ip": "", + "network:get_fixed_ip_by_address": "", + "network:add_fixed_ip_to_instance": "", + "network:remove_fixed_ip_from_instance": "", + "network:add_network_to_project": "", + "network:get_instance_nw_info": "", + + "network:get_dns_domains": "", + "network:add_dns_entry": "", + "network:modify_dns_entry": "", + "network:delete_dns_entry": "", + "network:get_dns_entries_by_address": "", + "network:get_dns_entries_by_name": "", + "network:create_private_dns_domain": "", + "network:create_public_dns_domain": "", + "network:delete_dns_domain": "" +} diff --git a/rpc_deployment/roles/nova_common/templates/rootwrap.conf b/rpc_deployment/roles/nova_common/templates/rootwrap.conf new file mode 100644 index 0000000000..fb2997abdb --- /dev/null +++ b/rpc_deployment/roles/nova_common/templates/rootwrap.conf @@ -0,0 +1,27 @@ +# Configuration for nova-rootwrap +# This file should be owned by (and only-writeable by) the root user + +[DEFAULT] +# List of directories to load filter definitions from (separated by ','). +# These directories MUST all be only writeable by root ! +filters_path=/etc/nova/rootwrap.d,/usr/share/nova/rootwrap + +# List of directories to search executables in, in case filters do not +# explicitely specify a full path (separated by ',') +# If not specified, defaults to system PATH environment variable. +# These directories MUST all be only writeable by root ! +exec_dirs=/sbin,/usr/sbin,/bin,/usr/bin + +# Enable logging to syslog +# Default value is False +use_syslog=False + +# Which syslog facility to use. +# Valid values include auth, authpriv, syslog, user0, user1... +# Default value is 'syslog' +syslog_log_facility=syslog + +# Which messages to log. +# INFO means log all usage +# ERROR means only log unsuccessful attempts +syslog_log_level=ERROR diff --git a/rpc_deployment/roles/nova_common/templates/rootwrap.d/api-metadata.filters b/rpc_deployment/roles/nova_common/templates/rootwrap.d/api-metadata.filters new file mode 100644 index 0000000000..1aa6f83e68 --- /dev/null +++ b/rpc_deployment/roles/nova_common/templates/rootwrap.d/api-metadata.filters @@ -0,0 +1,13 @@ +# nova-rootwrap command filters for api-metadata nodes +# This is needed on nova-api hosts running with "metadata" in enabled_apis +# or when running nova-api-metadata +# This file should be owned by (and only-writeable by) the root user + +[Filters] +# nova/network/linux_net.py: 'ip[6]tables-save' % (cmd, '-t', ... +iptables-save: CommandFilter, iptables-save, root +ip6tables-save: CommandFilter, ip6tables-save, root + +# nova/network/linux_net.py: 'ip[6]tables-restore' % (cmd,) +iptables-restore: CommandFilter, iptables-restore, root +ip6tables-restore: CommandFilter, ip6tables-restore, root diff --git a/rpc_deployment/roles/nova_common/templates/rootwrap.d/baremetal-compute-ipmi.filters b/rpc_deployment/roles/nova_common/templates/rootwrap.d/baremetal-compute-ipmi.filters new file mode 100644 index 0000000000..4132a99964 --- /dev/null +++ b/rpc_deployment/roles/nova_common/templates/rootwrap.d/baremetal-compute-ipmi.filters @@ -0,0 +1,9 @@ +# nova-rootwrap command filters for compute nodes +# This file should be owned by (and only-writeable by) the root user + +[Filters] +# nova/virt/baremetal/ipmi.py: 'ipmitool', .. +ipmitool: CommandFilter, ipmitool, root + +# nova/virt/baremetal/ipmi.py: 'kill', '-TERM', str(console_pid) +kill_shellinaboxd: KillFilter, root, /usr/local/bin/shellinaboxd, -15, -TERM diff --git a/rpc_deployment/roles/nova_common/templates/rootwrap.d/baremetal-deploy-helper.filters b/rpc_deployment/roles/nova_common/templates/rootwrap.d/baremetal-deploy-helper.filters new file mode 100644 index 0000000000..6d14b5d9fc --- /dev/null +++ b/rpc_deployment/roles/nova_common/templates/rootwrap.d/baremetal-deploy-helper.filters @@ -0,0 +1,11 @@ +# nova-rootwrap command filters for nova-baremetal-deploy-helper +# This file should be owned by (and only-writeable by) the root user + +[Filters] +# nova-baremetal-deploy-helper +iscsiadm: CommandFilter, iscsiadm, root +sfdisk: CommandFilter, sfdisk, root +dd: CommandFilter, dd, root +mkswap: CommandFilter, mkswap, root +blkid: CommandFilter, blkid, root +mkfs: CommandFilter, mkfs, root diff --git a/rpc_deployment/roles/nova_common/templates/rootwrap.d/compute.filters b/rpc_deployment/roles/nova_common/templates/rootwrap.d/compute.filters new file mode 100644 index 0000000000..3e9b7f547c --- /dev/null +++ b/rpc_deployment/roles/nova_common/templates/rootwrap.d/compute.filters @@ -0,0 +1,228 @@ +# nova-rootwrap command filters for compute nodes +# This file should be owned by (and only-writeable by) the root user + +[Filters] +# nova/virt/disk/mount/api.py: 'kpartx', '-a', device +# nova/virt/disk/mount/api.py: 'kpartx', '-d', device +kpartx: CommandFilter, kpartx, root + +# nova/virt/xenapi/vm_utils.py: tune2fs, -O ^has_journal, part_path +# nova/virt/xenapi/vm_utils.py: tune2fs, -j, partition_path +tune2fs: CommandFilter, tune2fs, root + +# nova/virt/disk/mount/api.py: 'mount', mapped_device +# nova/virt/disk/api.py: 'mount', '-o', 'bind', src, target +# nova/virt/xenapi/vm_utils.py: 'mount', '-t', 'ext2,ext3,ext4,reiserfs'.. +# nova/virt/configdrive.py: 'mount', device, mountdir +# nova/virt/libvirt/volume.py: 'mount', '-t', 'sofs' ... +mount: CommandFilter, mount, root + +# nova/virt/disk/mount/api.py: 'umount', mapped_device +# nova/virt/disk/api.py: 'umount' target +# nova/virt/xenapi/vm_utils.py: 'umount', dev_path +# nova/virt/configdrive.py: 'umount', mountdir +umount: CommandFilter, umount, root + +# nova/virt/disk/mount/nbd.py: 'qemu-nbd', '-c', device, image +# nova/virt/disk/mount/nbd.py: 'qemu-nbd', '-d', device +qemu-nbd: CommandFilter, qemu-nbd, root + +# nova/virt/disk/mount/loop.py: 'losetup', '--find', '--show', image +# nova/virt/disk/mount/loop.py: 'losetup', '--detach', device +losetup: CommandFilter, losetup, root + +# nova/virt/libvirt/utils.py: 'blockdev', '--getsize64', path +# nova/virt/disk/mount/nbd.py: 'blockdev', '--flushbufs', device +blockdev: RegExpFilter, blockdev, root, blockdev, (--getsize64|--flushbufs), /dev/.* + +# nova/virt/disk/vfs/localfs.py: 'tee', canonpath +tee: CommandFilter, tee, root + +# nova/virt/disk/vfs/localfs.py: 'mkdir', canonpath +mkdir: CommandFilter, mkdir, root + +# nova/virt/disk/vfs/localfs.py: 'chown' +# nova/virt/libvirt/connection.py: 'chown', os.getuid( console_log +# nova/virt/libvirt/connection.py: 'chown', os.getuid( console_log +# nova/virt/libvirt/connection.py: 'chown', 'root', basepath('disk') +# nova/utils.py: 'chown', owner_uid, path +chown: CommandFilter, chown, root + +# nova/virt/disk/vfs/localfs.py: 'chmod' +chmod: CommandFilter, chmod, root + +# nova/virt/libvirt/vif.py: 'ip', 'tuntap', 'add', dev, 'mode', 'tap' +# nova/virt/libvirt/vif.py: 'ip', 'link', 'set', dev, 'up' +# nova/virt/libvirt/vif.py: 'ip', 'link', 'delete', dev +# nova/network/linux_net.py: 'ip', 'addr', 'add', str(floating_ip)+'/32'i.. +# nova/network/linux_net.py: 'ip', 'addr', 'del', str(floating_ip)+'/32'.. +# nova/network/linux_net.py: 'ip', 'addr', 'add', '169.254.169.254/32',.. +# nova/network/linux_net.py: 'ip', 'addr', 'show', 'dev', dev, 'scope',.. +# nova/network/linux_net.py: 'ip', 'addr', 'del/add', ip_params, dev) +# nova/network/linux_net.py: 'ip', 'addr', 'del', params, fields[-1] +# nova/network/linux_net.py: 'ip', 'addr', 'add', params, bridge +# nova/network/linux_net.py: 'ip', '-f', 'inet6', 'addr', 'change', .. +# nova/network/linux_net.py: 'ip', 'link', 'set', 'dev', dev, 'promisc',.. +# nova/network/linux_net.py: 'ip', 'link', 'add', 'link', bridge_if ... +# nova/network/linux_net.py: 'ip', 'link', 'set', interface, address,.. +# nova/network/linux_net.py: 'ip', 'link', 'set', interface, 'up' +# nova/network/linux_net.py: 'ip', 'link', 'set', bridge, 'up' +# nova/network/linux_net.py: 'ip', 'addr', 'show', 'dev', interface, .. +# nova/network/linux_net.py: 'ip', 'link', 'set', dev, address, .. +# nova/network/linux_net.py: 'ip', 'link', 'set', dev, 'up' +# nova/network/linux_net.py: 'ip', 'route', 'add', .. +# nova/network/linux_net.py: 'ip', 'route', 'del', . +# nova/network/linux_net.py: 'ip', 'route', 'show', 'dev', dev +ip: CommandFilter, ip, root + +# nova/virt/libvirt/vif.py: 'tunctl', '-b', '-t', dev +# nova/network/linux_net.py: 'tunctl', '-b', '-t', dev +tunctl: CommandFilter, tunctl, root + +# nova/virt/libvirt/vif.py: 'ovs-vsctl', ... +# nova/virt/libvirt/vif.py: 'ovs-vsctl', 'del-port', ... +# nova/network/linux_net.py: 'ovs-vsctl', .... +ovs-vsctl: CommandFilter, ovs-vsctl, root + +# nova/network/linux_net.py: 'ovs-ofctl', .... +ovs-ofctl: CommandFilter, ovs-ofctl, root + +# nova/virt/libvirt/connection.py: 'dd', if=%s % virsh_output, ... +dd: CommandFilter, dd, root + +# nova/virt/xenapi/volume_utils.py: 'iscsiadm', '-m', ... +iscsiadm: CommandFilter, iscsiadm, root + +# nova/virt/libvirt/volume.py: 'aoe-revalidate', aoedev +# nova/virt/libvirt/volume.py: 'aoe-discover' +aoe-revalidate: CommandFilter, aoe-revalidate, root +aoe-discover: CommandFilter, aoe-discover, root + +# nova/virt/xenapi/vm_utils.py: parted, --script, ... +# nova/virt/xenapi/vm_utils.py: 'parted', '--script', dev_path, ..*. +parted: CommandFilter, parted, root + +# nova/virt/xenapi/vm_utils.py: 'pygrub', '-qn', dev_path +pygrub: CommandFilter, pygrub, root + +# nova/virt/xenapi/vm_utils.py: fdisk %(dev_path)s +fdisk: CommandFilter, fdisk, root + +# nova/virt/xenapi/vm_utils.py: e2fsck, -f, -p, partition_path +# nova/virt/disk/api.py: e2fsck, -f, -p, image +e2fsck: CommandFilter, e2fsck, root + +# nova/virt/xenapi/vm_utils.py: resize2fs, partition_path +# nova/virt/disk/api.py: resize2fs, image +resize2fs: CommandFilter, resize2fs, root + +# nova/network/linux_net.py: 'ip[6]tables-save' % (cmd, '-t', ... +iptables-save: CommandFilter, iptables-save, root +ip6tables-save: CommandFilter, ip6tables-save, root + +# nova/network/linux_net.py: 'ip[6]tables-restore' % (cmd,) +iptables-restore: CommandFilter, iptables-restore, root +ip6tables-restore: CommandFilter, ip6tables-restore, root + +# nova/network/linux_net.py: 'arping', '-U', floating_ip, '-A', '-I', ... +# nova/network/linux_net.py: 'arping', '-U', network_ref['dhcp_server'],.. +arping: CommandFilter, arping, root + +# nova/network/linux_net.py: 'dhcp_release', dev, address, mac_address +dhcp_release: CommandFilter, dhcp_release, root + +# nova/network/linux_net.py: 'kill', '-9', pid +# nova/network/linux_net.py: 'kill', '-HUP', pid +kill_dnsmasq: KillFilter, root, /usr/sbin/dnsmasq, -9, -HUP + +# nova/network/linux_net.py: 'kill', pid +kill_radvd: KillFilter, root, /usr/sbin/radvd + +# nova/network/linux_net.py: dnsmasq call +dnsmasq: EnvFilter, env, root, CONFIG_FILE=, NETWORK_ID=, dnsmasq + +# nova/network/linux_net.py: 'radvd', '-C', '%s' % _ra_file(dev, 'conf'.. +radvd: CommandFilter, radvd, root + +# nova/network/linux_net.py: 'brctl', 'addbr', bridge +# nova/network/linux_net.py: 'brctl', 'setfd', bridge, 0 +# nova/network/linux_net.py: 'brctl', 'stp', bridge, 'off' +# nova/network/linux_net.py: 'brctl', 'addif', bridge, interface +brctl: CommandFilter, brctl, root + +# nova/virt/libvirt/utils.py: 'mkswap' +# nova/virt/xenapi/vm_utils.py: 'mkswap' +mkswap: CommandFilter, mkswap, root + +# nova/virt/xenapi/vm_utils.py: 'mkfs' +# nova/utils.py: 'mkfs', fs, path, label +mkfs: CommandFilter, mkfs, root + +# nova/virt/libvirt/utils.py: 'qemu-img' +qemu-img: CommandFilter, qemu-img, root + +# nova/virt/disk/vfs/localfs.py: 'readlink', '-e' +readlink: CommandFilter, readlink, root + +# nova/virt/disk/api.py: 'touch', target +touch: CommandFilter, touch, root + +# nova/virt/disk/api.py: +mkfs.ext3: CommandFilter, mkfs.ext3, root +mkfs.ntfs: CommandFilter, mkfs.ntfs, root + +# nova/virt/libvirt/connection.py: +read_initiator: ReadFileFilter, /etc/iscsi/initiatorname.iscsi + +# nova/virt/libvirt/connection.py: +lvremove: CommandFilter, lvremove, root + +# nova/virt/libvirt/utils.py: +lvcreate: CommandFilter, lvcreate, root + +# nova/virt/libvirt/utils.py: +lvs: CommandFilter, lvs, root + +# nova/virt/libvirt/utils.py: +vgs: CommandFilter, vgs, root + +# nova/virt/baremetal/volume_driver.py: 'tgtadm', '--lld', 'iscsi', ... +tgtadm: CommandFilter, tgtadm, root + +# nova/utils.py:read_file_as_root: 'cat', file_path +# (called from nova/virt/disk/vfs/localfs.py:VFSLocalFS.read_file) +read_passwd: RegExpFilter, cat, root, cat, (/var|/usr)?/tmp/openstack-vfs-localfs[^/]+/etc/passwd +read_shadow: RegExpFilter, cat, root, cat, (/var|/usr)?/tmp/openstack-vfs-localfs[^/]+/etc/shadow + +# nova/virt/libvirt/volume.py: 'multipath' '-R' +multipath: CommandFilter, multipath, root + +# nova/virt/libvirt/utils.py: +systool: CommandFilter, systool, root + +# nova/virt/libvirt/volume.py: +sginfo: CommandFilter, sginfo, root +sg_scan: CommandFilter, sg_scan, root +ln: RegExpFilter, ln, root, ln, --symbolic, --force, /dev/mapper/ip-.*-iscsi-iqn.2010-10.org.openstack:volume-.*, /dev/disk/by-path/ip-.*-iscsi-iqn.2010-10.org.openstack:volume-.* + +# nova/volume/encryptors.py: +# nova/virt/libvirt/dmcrypt.py: +cryptsetup: CommandFilter, cryptsetup, root + +# nova/virt/xenapi/vm_utils.py: +xenstore-read: CommandFilter, xenstore-read, root + +# nova/virt/baremetal/tilera.py: 'rpc.mountd' +rpc.mountd: CommandFilter, rpc.mountd, root + +# nova/virt/libvirt/utils.py: +rbd: CommandFilter, rbd, root + +# nova/virt/libvirt/utils.py: 'shred', '-n3', '-s%d' % volume_size, path +shred: CommandFilter, shred, root + +# nova/virt/libvirt/volume.py: 'cp', '/dev/stdin', delete_control.. +cp: CommandFilter, cp, root + +# nova/virt/xenapi/vm_utils.py: +sync: CommandFilter, sync, root diff --git a/rpc_deployment/roles/nova_common/templates/rootwrap.d/network.filters b/rpc_deployment/roles/nova_common/templates/rootwrap.d/network.filters new file mode 100644 index 0000000000..568e8d493c --- /dev/null +++ b/rpc_deployment/roles/nova_common/templates/rootwrap.d/network.filters @@ -0,0 +1,94 @@ +# nova-rootwrap command filters for network nodes +# This file should be owned by (and only-writeable by) the root user + +[Filters] +# nova/virt/libvirt/vif.py: 'ip', 'tuntap', 'add', dev, 'mode', 'tap' +# nova/virt/libvirt/vif.py: 'ip', 'link', 'set', dev, 'up' +# nova/virt/libvirt/vif.py: 'ip', 'link', 'delete', dev +# nova/network/linux_net.py: 'ip', 'addr', 'add', str(floating_ip)+'/32'i.. +# nova/network/linux_net.py: 'ip', 'addr', 'del', str(floating_ip)+'/32'.. +# nova/network/linux_net.py: 'ip', 'addr', 'add', '169.254.169.254/32',.. +# nova/network/linux_net.py: 'ip', 'addr', 'show', 'dev', dev, 'scope',.. +# nova/network/linux_net.py: 'ip', 'addr', 'del/add', ip_params, dev) +# nova/network/linux_net.py: 'ip', 'addr', 'del', params, fields[-1] +# nova/network/linux_net.py: 'ip', 'addr', 'add', params, bridge +# nova/network/linux_net.py: 'ip', '-f', 'inet6', 'addr', 'change', .. +# nova/network/linux_net.py: 'ip', 'link', 'set', 'dev', dev, 'promisc',.. +# nova/network/linux_net.py: 'ip', 'link', 'add', 'link', bridge_if ... +# nova/network/linux_net.py: 'ip', 'link', 'set', interface, address,.. +# nova/network/linux_net.py: 'ip', 'link', 'set', interface, 'up' +# nova/network/linux_net.py: 'ip', 'link', 'set', bridge, 'up' +# nova/network/linux_net.py: 'ip', 'addr', 'show', 'dev', interface, .. +# nova/network/linux_net.py: 'ip', 'link', 'set', dev, address, .. +# nova/network/linux_net.py: 'ip', 'link', 'set', dev, 'up' +# nova/network/linux_net.py: 'ip', 'route', 'add', .. +# nova/network/linux_net.py: 'ip', 'route', 'del', . +# nova/network/linux_net.py: 'ip', 'route', 'show', 'dev', dev +ip: CommandFilter, ip, root + +# nova/virt/libvirt/vif.py: 'ovs-vsctl', ... +# nova/virt/libvirt/vif.py: 'ovs-vsctl', 'del-port', ... +# nova/network/linux_net.py: 'ovs-vsctl', .... +ovs-vsctl: CommandFilter, ovs-vsctl, root + +# nova/network/linux_net.py: 'ovs-ofctl', .... +ovs-ofctl: CommandFilter, ovs-ofctl, root + +# nova/virt/libvirt/vif.py: 'ivs-ctl', ... +# nova/virt/libvirt/vif.py: 'ivs-ctl', 'del-port', ... +# nova/network/linux_net.py: 'ivs-ctl', .... +ivs-ctl: CommandFilter, ivs-ctl, root + +# nova/virt/libvirt/vif.py: 'ifc_ctl', ... +ifc_ctl: CommandFilter, /opt/pg/bin/ifc_ctl, root + +# nova/virt/libvirt/vif.py: 'ebrctl', ... +ebrctl: CommandFilter, ebrctl, root + +# nova/virt/libvirt/vif.py: 'mm-ctl', ... +mm-ctl: CommandFilter, mm-ctl, root + +# nova/network/linux_net.py: 'ebtables', '-D' ... +# nova/network/linux_net.py: 'ebtables', '-I' ... +ebtables: CommandFilter, ebtables, root +ebtables_usr: CommandFilter, ebtables, root + +# nova/network/linux_net.py: 'ip[6]tables-save' % (cmd, '-t', ... +iptables-save: CommandFilter, iptables-save, root +ip6tables-save: CommandFilter, ip6tables-save, root + +# nova/network/linux_net.py: 'ip[6]tables-restore' % (cmd,) +iptables-restore: CommandFilter, iptables-restore, root +ip6tables-restore: CommandFilter, ip6tables-restore, root + +# nova/network/linux_net.py: 'arping', '-U', floating_ip, '-A', '-I', ... +# nova/network/linux_net.py: 'arping', '-U', network_ref['dhcp_server'],.. +arping: CommandFilter, arping, root + +# nova/network/linux_net.py: 'dhcp_release', dev, address, mac_address +dhcp_release: CommandFilter, dhcp_release, root + +# nova/network/linux_net.py: 'kill', '-9', pid +# nova/network/linux_net.py: 'kill', '-HUP', pid +kill_dnsmasq: KillFilter, root, /usr/sbin/dnsmasq, -9, -HUP + +# nova/network/linux_net.py: 'kill', pid +kill_radvd: KillFilter, root, /usr/sbin/radvd + +# nova/network/linux_net.py: dnsmasq call +dnsmasq: EnvFilter, env, root, CONFIG_FILE=, NETWORK_ID=, dnsmasq + +# nova/network/linux_net.py: 'radvd', '-C', '%s' % _ra_file(dev, 'conf'.. +radvd: CommandFilter, radvd, root + +# nova/network/linux_net.py: 'brctl', 'addbr', bridge +# nova/network/linux_net.py: 'brctl', 'setfd', bridge, 0 +# nova/network/linux_net.py: 'brctl', 'stp', bridge, 'off' +# nova/network/linux_net.py: 'brctl', 'addif', bridge, interface +brctl: CommandFilter, brctl, root + +# nova/network/linux_net.py: 'sysctl', .... +sysctl: CommandFilter, sysctl, root + +# nova/network/linux_net.py: 'conntrack' +conntrack: CommandFilter, conntrack, root diff --git a/rpc_deployment/roles/nova_compute_devices/tasks/main.yml b/rpc_deployment/roles/nova_compute_devices/tasks/main.yml new file mode 100644 index 0000000000..15bec3e8a9 --- /dev/null +++ b/rpc_deployment/roles/nova_compute_devices/tasks/main.yml @@ -0,0 +1,52 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Ensure container is running + lxc: > + name={{ container_name }} + command=start + delegate_to: "{{ physical_host }}" + when: is_metal != true + +- name: Add nbd devices to the compute + shell: > + for i in /dev/nbd*; do lxc-device -n {{ container_name }} add $i $i; done; + delegate_to: "{{ physical_host }}" + when: is_metal != true + +- name: Add net/tun device to the compute + shell: > + lxc-device -n {{ container_name }} add /dev/net/tun /dev/net/tun + delegate_to: "{{ physical_host }}" + when: is_metal != true + +- name: Add kvm device to the compute + shell: > + lxc-device -n {{ container_name }} add /dev/kvm /dev/kvm + delegate_to: "{{ physical_host }}" + when: nova_virt_type == 'kvm' and is_metal != true + +- name: Ensure kvm permissions + shell: > + udevadm trigger + when: nova_virt_type == 'kvm' + +- name: Create log aggregation links + file: + src: "/var/log/nova" + dest: "/openstack/log/nova" + state: "link" + when: is_metal == true + diff --git a/rpc_deployment/roles/nova_libvirt/files/libvirt-bin.conf b/rpc_deployment/roles/nova_libvirt/files/libvirt-bin.conf new file mode 100644 index 0000000000..e4a8fc3402 --- /dev/null +++ b/rpc_deployment/roles/nova_libvirt/files/libvirt-bin.conf @@ -0,0 +1,88 @@ +description "libvirt daemon" +author "Dustin Kirkland " + +start on runlevel [2345] +stop on starting rc RUNLEVEL=[016] + +expect daemon +respawn + +# daemonize +env libvirtd_opts="-d -l" +# whether libvirtd should run at boot/shutdown +env start_libvirtd="yes" +# by default wait 30 seconds for vms to shut down +env libvirtd_shutdown_timeout=30 +# uris for which to shut down vms +env libvirt_uris='qemu:///system lxc:///' + +pre-start script + [ -r /etc/default/libvirt-bin ] && . /etc/default/libvirt-bin + [ ! "x$start_libvirtd" = "xyes" ] && { stop; exit 0; } + mkdir -p /var/run/libvirt + # Clean up a pidfile that might be left around + rm -f /var/run/libvirtd.pid +end script + +pre-stop script + [ -r /etc/default/libvirt-bin ] && . /etc/default/libvirt-bin + + log_msg() + { + logf="/var/log/libvirt/shutdownlog.log" + logger -p daemon.debug -s -t libvirt -- "$@" >> $logf 2>&1 + } + + run_virsh() + { + # We parse the output for things like domain state; + # make sure the output is in the language we expect. + LANG=C virsh "$@" + } + + if [ -z "$RUNLEVEL" ]; then + exit 0 + fi + + if [ "$RUNLEVEL" -ne 0 ] && [ "$RUNLEVEL" -ne 1 ] && [ "$RUNLEVEL" -ne 6 ]; then + exit 0 + fi + log_msg "libvirt-bin: entering pre-stop at $(date)" + + for uri in $libvirt_uris; do + for domain in $(run_virsh -c "$uri" list | awk '$3 == "running" {print $2}'); do + log_msg "libvirt-bin: attempting clean shutdown of $domain at $(date)" + run_virsh -c "$uri" shutdown "$domain" >/dev/null + done + done + + delay=$libvirtd_shutdown_timeout + while [ $delay -gt 0 ]; do + for uri in $libvirt_uris; do + if ! run_virsh -c "$uri" list | awk '$3 == "running" {exit 1}'; then + # VMs at this URI are still running. Wait, then + # start at the beginning looking for running VMs. + sleep 1 + delay=$(($delay - 1)) + continue 2 + fi + done + break + done + + for uri in $libvirt_uris; do + for domain in $(run_virsh -c "$uri" list | awk '$3 == "running" {print $2}'); do + log_msg "destroying $domain" + run_virsh -c "$uri" destroy "$domain" >/dev/null + done + done + log_msg "libvirt-bin: exiting pre-stop at $(date)" +end script + +# /etc/default/libvirt-bin will be deprecated soon. +# If you used to set $libvirtd_opts in /etc/default/libvirt-bin, +# change the 'exec' line here instead. +script + [ -r /etc/default/libvirt-bin ] && . /etc/default/libvirt-bin + exec /usr/sbin/libvirtd $libvirtd_opts +end script diff --git a/rpc_deployment/roles/nova_libvirt/handlers/main.yml b/rpc_deployment/roles/nova_libvirt/handlers/main.yml new file mode 100644 index 0000000000..829ab2435c --- /dev/null +++ b/rpc_deployment/roles/nova_libvirt/handlers/main.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Restart libvirt-bin + service: name=libvirt-bin state=restarted pattern=libvirt-bin diff --git a/rpc_deployment/roles/nova_libvirt/tasks/main.yml b/rpc_deployment/roles/nova_libvirt/tasks/main.yml new file mode 100644 index 0000000000..d533716c1b --- /dev/null +++ b/rpc_deployment/roles/nova_libvirt/tasks/main.yml @@ -0,0 +1,48 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Ensure libvirt packages are installed + apt: + pkg: "{{ item }}" + state: present + update_cache: yes + cache_valid_time: 600 + with_items: apt_libvirt_packages + +- name: Set libvirtd config + template: > + src=libvirtd.conf + dest=/etc/libvirt/libvirtd.conf + owner="root" + group="root" + mode=0644 + notify: Restart libvirt-bin + +- name: Set libvirt-bin upstart script + copy: > + src=libvirt-bin.conf + dest=/etc/init/libvirt-bin.conf + owner="root" + group="root" + mode=0644 + notify: Restart libvirt-bin + +- name: Add nova user to libvirtd group + user: > + name="{{ system_user }}" + groups=libvirtd + append=yes + +- include: virsh_net_remove.yml diff --git a/rpc_deployment/roles/nova_libvirt/tasks/virsh_net_remove.yml b/rpc_deployment/roles/nova_libvirt/tasks/virsh_net_remove.yml new file mode 100644 index 0000000000..771d0a936b --- /dev/null +++ b/rpc_deployment/roles/nova_libvirt/tasks/virsh_net_remove.yml @@ -0,0 +1,29 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Check for libvirt default network + shell: > + virsh net-list | awk '/default/' + register: default_net + +- name: Disable libvirt default network + shell: > + virsh net-autostart default --disable + when: default_net.stdout|search('default') + +- name: Destroy libvirt default network + shell: > + virsh net-destroy default + when: default_net.stdout|search('default') diff --git a/rpc_deployment/roles/nova_libvirt/templates/libvirtd.conf b/rpc_deployment/roles/nova_libvirt/templates/libvirtd.conf new file mode 100644 index 0000000000..0c2f91a6ba --- /dev/null +++ b/rpc_deployment/roles/nova_libvirt/templates/libvirtd.conf @@ -0,0 +1,10 @@ +# Managed by ansible + +listen_tls = 0 +listen_tcp = 1 +unix_sock_group = "libvirtd" +unix_sock_ro_perms = "0777" +unix_sock_rw_perms = "0770" +auth_unix_ro = "none" +auth_unix_rw = "none" +auth_tcp = "none" diff --git a/rpc_deployment/roles/nova_setup/tasks/main.yml b/rpc_deployment/roles/nova_setup/tasks/main.yml new file mode 100644 index 0000000000..f7ce3e68eb --- /dev/null +++ b/rpc_deployment/roles/nova_setup/tasks/main.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Perform a Nova DB sync + command: nova-manage db sync diff --git a/rpc_deployment/roles/openssl_pem_request/tasks/main.yml b/rpc_deployment/roles/openssl_pem_request/tasks/main.yml new file mode 100644 index 0000000000..6f434556c2 --- /dev/null +++ b/rpc_deployment/roles/openssl_pem_request/tasks/main.yml @@ -0,0 +1,57 @@ +# Copyright 2014, Rackspace US, Inc. +# +# 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: Set openssl facts + set_facts: + working_dir: "{{ work_dir|default('/tmp/openssl')|expanduser }}" + uid: "{{ owner|default('root') }}" + gid: "{{ group|default('root') }}" + + +- name: Ensure working directory exists + file: > + path="{{ working_dir }}" + owner="{{ uid }}" + group="{{ gid }}" + state=directory + recurse=yes + mode=0700 + +- name: Drop cert request config + template: > + src=cert_req.conf + dest="{{ working_dir }}/cert_req.conf" + owner="{{ uid }}" + group="{{ gid }}" + mode=0600 + +- name: + command: > + openssl req -newkey rsa:2048 + -keyout signing_key.pem + -keyform PEM + -out signing_cert_req.pem + -outform PEM + -config cert_req.conf + -nodes + args: + chdir: "{{ working_dir }}" + creates: "{{ working_dir }}/signing_cert_req.pem" + +- name: Set directory permissions + file: > + path="{{ working_dir }}/signing_cert_req.pem" + owner="{{ uid }}" + group="{{ gid }}" + mode=0600 diff --git a/rpc_deployment/roles/openssl_pem_request/templates/cert_req.conf b/rpc_deployment/roles/openssl_pem_request/templates/cert_req.conf new file mode 100644 index 0000000000..7833383416 --- /dev/null +++ b/rpc_deployment/roles/openssl_pem_request/templates/cert_req.conf @@ -0,0 +1,16 @@ +[ req ] +default_bits = 2048 +default_keyfile = keystonekey.pem +default_md = default + +prompt = no +distinguished_name = distinguished_name + +[ distinguished_name ] +countryName = {{ openssl_contry|default('US') }} +stateOrProvinceName = {{ openssl_state|default('TX') }} +localityName = {{ openssl_locality|default('San Antonio') }} +organizationName = {{ openssl_organization|default('OpenStack') }} +organizationalUnitName = {{ openssl_organization_unit|default('SuperUser') }} +commonName = {{ openssl_common|default('SuperUser Signing') }} +emailAddress = {{ openssl_email|default('NotAnAddress@NotADomainIHope.org') diff --git a/rpc_deployment/roles/openstack_common/tasks/install_git_source.yml b/rpc_deployment/roles/openstack_common/tasks/install_git_source.yml new file mode 100644 index 0000000000..9d341b2824 --- /dev/null +++ b/rpc_deployment/roles/openstack_common/tasks/install_git_source.yml @@ -0,0 +1,34 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Get package from git + git: > + repo={{ git_repo }} + dest="/opt/{{ service_name }}_{{ git_install_branch | replace('/', '_') }}" + version={{ git_install_branch }} + register: git_clone + ignore_errors: yes + until: git_clone|success + retries: 5 + +- name: Get package from fallback git repo + git: > + repo={{ git_fallback_repo }} + dest="/opt/{{ service_name }}_{{ git_install_branch | replace('/', '_') }}" + version={{ git_install_branch }} + register: git_fallback_clone + when: git_clone|failed + until: git_fallback_clone|success + retries: 5 diff --git a/rpc_deployment/roles/openstack_common/tasks/main.yml b/rpc_deployment/roles/openstack_common/tasks/main.yml new file mode 100644 index 0000000000..010db6839f --- /dev/null +++ b/rpc_deployment/roles/openstack_common/tasks/main.yml @@ -0,0 +1,24 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: install_git_source.yml +- include: pip_install.yml + +# TODO(kevin) This should go away sooner than later +- name: Laydown the example files + shell: > + chdir="/opt/{{ service_name }}_{{ git_install_branch | replace('/', '_') }}/{{ git_etc_example }}" + for i in *; do if [ ! -f "/etc/{{ service_name }}/$i" ]; then cp -R $i /etc/{{ service_name }}/; fi; done; + when: git_etc_example is defined diff --git a/rpc_deployment/roles/openstack_common/tasks/pip_install.yml b/rpc_deployment/roles/openstack_common/tasks/pip_install.yml new file mode 100644 index 0000000000..648e14b877 --- /dev/null +++ b/rpc_deployment/roles/openstack_common/tasks/pip_install.yml @@ -0,0 +1,24 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Install service source + pip: > + name="/opt/{{ service_name }}_{{ git_install_branch | replace('/', '_') }}" + extra_args="{{ pip_install_options|default('') }} --allow-all-external" + register: pip_install + until: pip_install|success + retries: 3 + async: 1800 + poll: 5 diff --git a/rpc_deployment/roles/openstack_openrc/tasks/main.yml b/rpc_deployment/roles/openstack_openrc/tasks/main.yml new file mode 100644 index 0000000000..d27c3b733c --- /dev/null +++ b/rpc_deployment/roles/openstack_openrc/tasks/main.yml @@ -0,0 +1,22 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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 openrc file + template: > + src=openrc + dest=/root/openrc + owner=root + group=root + mode=0600 diff --git a/rpc_deployment/roles/openstack_openrc/templates/openrc b/rpc_deployment/roles/openstack_openrc/templates/openrc new file mode 100644 index 0000000000..def00638f4 --- /dev/null +++ b/rpc_deployment/roles/openstack_openrc/templates/openrc @@ -0,0 +1,15 @@ +# Do not edit, changes will be overwritten + +# COMMON CINDER ENVS +export CINDER_ENDPOINT_TYPE=internalURL + +# COMMON NOVA ENVS +export NOVA_ENDPOINT_TYPE=internalURL + +# COMMON OPENSTACK ENVS +export OS_ENDPOINT_TYPE=internalURL +export OS_USERNAME={{ auth_admin_username }} +export OS_PASSWORD={{ auth_admin_password }} +export OS_TENANT_NAME={{ auth_admin_tenant }} +export OS_AUTH_URL={{ auth_identity_uri }} +export OS_NO_CACHE=1 diff --git a/rpc_deployment/roles/rabbit_common/tasks/main.yml b/rpc_deployment/roles/rabbit_common/tasks/main.yml new file mode 100644 index 0000000000..13259455a9 --- /dev/null +++ b/rpc_deployment/roles/rabbit_common/tasks/main.yml @@ -0,0 +1,94 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Add apt key for rabbit + apt_key: + url: "{{ item }}" + state: present + with_items: rabbitmq_key + tags: + - package_install + - rabbit_install + +- name: Configure rabbit repo + apt_repository: + repo: "{{ item.repo }}" + state: "{{ item.state }}" + with_items: rabbit_repos + tags: + - package_install + - rabbit_install + +- name: Install rabbit packages + apt: + pkg: "{{ item }}" + state: latest + update_cache: yes + cache_valid_time: 600 + with_items: + - rabbitmq-server + tags: + - package_install + - rabbit_install + +- name: Fix /etc/hosts + lineinfile: + dest: /etc/hosts + state: present + line: "{{ hostvars[item]['container_address'] }} {{ hostvars[item]['container_name'] }} {{ hostvars[item]['container_name'].split('.')[0] }}" + with_items: groups['rabbit'] + tags: + - hosts + - rabbit_config + +- include: restart_rabbit.yml + +- name: Read rabbit cookie + shell: | + cat /var/lib/rabbitmq/.erlang.cookie + register: tmp_rabbit_cookie + tags: + - rabbit_config + +- include: set_cookie.yml + when: tmp_rabbit_cookie.stdout != rabbit_cookie + +- name: Create rabbitmq config + template: + src: rabbitmq.config + dest: /etc/rabbitmq/rabbitmq.config + tags: + - rabbit_config + +- name: Enable management plugin + rabbitmq_plugin: + names: rabbitmq_management + state: enabled + when: enable_management_plugin + tags: + - rabbit_config + +- include: restart_rabbit.yml + +- name: Enable queue mirroring + rabbitmq_policy: > + name="HA" + pattern='^(?!amq\.).*' + args: + tags: + "ha-mode": all + tags: + - rabbit_config + - rabbit_cluster diff --git a/rpc_deployment/roles/rabbit_common/tasks/restart_rabbit.yml b/rpc_deployment/roles/rabbit_common/tasks/restart_rabbit.yml new file mode 100644 index 0000000000..685e7e5918 --- /dev/null +++ b/rpc_deployment/roles/rabbit_common/tasks/restart_rabbit.yml @@ -0,0 +1,22 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Restart rabbitmq-server + service: + name: rabbitmq-server + enabled: yes + state: restarted + tags: + - rabbit_restart diff --git a/rpc_deployment/roles/rabbit_common/tasks/set_cookie.yml b/rpc_deployment/roles/rabbit_common/tasks/set_cookie.yml new file mode 100644 index 0000000000..9e35521d23 --- /dev/null +++ b/rpc_deployment/roles/rabbit_common/tasks/set_cookie.yml @@ -0,0 +1,35 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Stop rabbitmq-server + service: + name: rabbitmq-server + state: stopped + tags: + - rabbit_stop + +- name: Set rabbit cookie + copy: + content: "{{ rabbit_cookie }}" + dest: /var/lib/rabbitmq/.erlang.cookie + mode: 0400 + owner: rabbitmq + group: rabbitmq + register: cookie_set + tags: + - rabbit_config + +- include: restart_rabbit.yml + when: cookie_set|changed diff --git a/rpc_deployment/roles/rabbit_common/templates/rabbitmq.config b/rpc_deployment/roles/rabbit_common/templates/rabbitmq.config new file mode 100644 index 0000000000..4e514d8294 --- /dev/null +++ b/rpc_deployment/roles/rabbit_common/templates/rabbitmq.config @@ -0,0 +1,8 @@ +[ + {rabbit, [ + {loopback_users, []}, + {cluster_nodes, { + [ {% for host in groups['rabbit'] %}'rabbit@{{ hostvars[host]['container_address'] }}'{% if not loop.last %}, {% endif %}{% endfor %}], disc} + } + ]} +]. diff --git a/rpc_deployment/roles/rabbit_create_cluster/tasks/main.yml b/rpc_deployment/roles/rabbit_create_cluster/tasks/main.yml new file mode 100644 index 0000000000..c35b5c95cb --- /dev/null +++ b/rpc_deployment/roles/rabbit_create_cluster/tasks/main.yml @@ -0,0 +1,21 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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 cluster + shell: | + rabbitmqctl set_cluster_name {{ rabbit_cluster_name }} + tags: + - rabbit_cluster + - rabbit_config diff --git a/rpc_deployment/roles/rabbit_join_cluster/tasks/main.yml b/rpc_deployment/roles/rabbit_join_cluster/tasks/main.yml new file mode 100644 index 0000000000..10c737c801 --- /dev/null +++ b/rpc_deployment/roles/rabbit_join_cluster/tasks/main.yml @@ -0,0 +1,50 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# If cluster name is our own hostname, we assume we're not properly clustered +# TODO(someone): implement a more robust way of checking +# if node is clustered or not +- name: Check cluster status + shell: | + rabbitmqctl -q cluster_status | grep {{ rabbit_cluster_name }} + changed_when: result.rc != 0 + failed_when: false + register: result + tags: + - rabbit_cluster + +- name: Stop rabbit app + shell: | + rabbitmqctl stop_app && sleep 5 + failed_when: false + when: result.rc != 0 + tags: + - rabbit_stop_app + - rabbit_cluster + +- name: Join rabbit cluster + shell: | + rabbitmqctl join_cluster "rabbit@{{ hostvars[groups['rabbit'][0]]['container_name'].split('.')[0] }}" + when: result.rc != 0 + tags: + - rabbit_cluster + +- name: Start rabbit app + shell: | + rabbitmqctl start_app + when: result.rc != 0 + tags: + - rabbit_start_app + - rabbit_cluster diff --git a/rpc_deployment/roles/rabbit_remove/tasks/main.yml b/rpc_deployment/roles/rabbit_remove/tasks/main.yml new file mode 100644 index 0000000000..4909c72edd --- /dev/null +++ b/rpc_deployment/roles/rabbit_remove/tasks/main.yml @@ -0,0 +1,41 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Stop Rabbit App + shell: rabbitmqctl stop_app + ignore_errors: yes + +- name: Reset Rabbit State + shell: rabbitmqctl force_reset + ignore_errors: yes + +- name: remove rabbit packages + apt: + pkg: "{{ item }}" + state: absent + purge: yes + update_cache: yes + cache_valid_time: 600 + ignore_errors: yes + with_items: + - rabbitmq-server + - erlang + ignore_errors: yes + +- name: Remove Mnesia State + file: + path: /var/lib/rabbitmq/mnesia/ + state: absent + ignore_errors: yes diff --git a/rpc_deployment/roles/rabbit_user/tasks/main.yml b/rpc_deployment/roles/rabbit_user/tasks/main.yml new file mode 100644 index 0000000000..90f0ed5ba4 --- /dev/null +++ b/rpc_deployment/roles/rabbit_user/tasks/main.yml @@ -0,0 +1,14 @@ +--- +- name: Ensure rabbitmq user + rabbitmq_user: + user: "{{ rabbit_userid }}" + password: "{{ rabbit_password }}" + vhost: "/" + configure_priv: ".*" + read_priv: ".*" + write_priv: ".*" + state: present + tags: + - users + - rabbit_config + - rabbit_user diff --git a/rpc_deployment/roles/raxmon_agent_install/handlers/main.yml b/rpc_deployment/roles/raxmon_agent_install/handlers/main.yml new file mode 100644 index 0000000000..5887c5e21d --- /dev/null +++ b/rpc_deployment/roles/raxmon_agent_install/handlers/main.yml @@ -0,0 +1,18 @@ +# Copyright 2014, Rackspace US, Inc. +# +# 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: Restart raxmon agent + service: + name: rackspace-monitoring-agent + state: restarted diff --git a/rpc_deployment/roles/raxmon_agent_install/tasks/main.yml b/rpc_deployment/roles/raxmon_agent_install/tasks/main.yml new file mode 100644 index 0000000000..72d276f8fa --- /dev/null +++ b/rpc_deployment/roles/raxmon_agent_install/tasks/main.yml @@ -0,0 +1,89 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Add apt key for the raxmon agent + apt_key: + url: "{{ item }}" + state: present + with_items: raxmon_agent_key + +- name: Configure raxmon agent repo + apt_repository: > + repo="{{ item.repo }}" + state="{{ item.state }}" + with_items: raxmon_agent_repos + +- name: Install raxmon agent packages + apt: + pkg: "{{ item }}" + state: latest + update_cache: yes + cache_valid_time: 600 + with_items: + - rackspace-monitoring-agent + +- name: Clone plugins repo + git: + repo: https://github.com/rcbops/rpc-maas.git + dest: /usr/lib/rackspace-monitoring-agent/plugins/ + version: "{{ maas_repo_version }}" + +- name: Chmod plugins + file: path={{ item }} mode=0755 + with_fileglob: + - /usr/lib/rackspace-monitoring-agent/plugins/*.py + +- name: Create openrc file + template: > + src=openrc + dest=/root/openrc-maas + owner=root + group=root + mode=0600 + +- name: Install python dependencies + pip: + requirements: /usr/lib/rackspace-monitoring-agent/plugins/requirements.txt + +- name: Entity {{ entity_name }} count + shell: "raxmon-entities-list | grep ' label={{ entity_name }} provider=Rackspace Monitoring ...>$' | wc -l" + register: entity_count + +- name: At most one {{ entity_name }} entity exists + fail: + msg: "Entity count of {{ entity_count.stdout }} != 1 for entity with the label {{ entity_name }}" + when: entity_count.stdout|int != 1 + +- name: Get entity {{ entity_name }} + shell: "raxmon-entities-list | grep ' label={{ entity_name }} provider=Rackspace Monitoring ...>$' | awk '{print $2}' | cut -d= -f2" + register: entity + +- name: Assign agent ID to entity + shell: "raxmon-entities-update --id {{ entity.stdout }} --agent-id {{ entity_name }}" + +- name: Generate raxmon agent config + template: + src: rackspace-monitoring-agent.cfg + dest: /etc/rackspace-monitoring-agent.cfg + mode: 0600 + owner: root + group: root + notify: Restart raxmon agent + +- name: Start raxmon agent + service: + name: rackspace-monitoring-agent + state: started + enabled: yes diff --git a/rpc_deployment/roles/raxmon_agent_install/templates/openrc b/rpc_deployment/roles/raxmon_agent_install/templates/openrc new file mode 100644 index 0000000000..d6145bb59b --- /dev/null +++ b/rpc_deployment/roles/raxmon_agent_install/templates/openrc @@ -0,0 +1,6 @@ +# COMMON OPENSTACK ENVS +export OS_USERNAME={{ maas_keystone_user }} +export OS_PASSWORD={{ maas_keystone_password }} +export OS_TENANT_NAME={{ auth_admin_tenant }} +export OS_AUTH_URL={{ auth_identity_uri }} +export OS_NO_CACHE=1 diff --git a/rpc_deployment/roles/raxmon_agent_install/templates/rackspace-monitoring-agent.cfg b/rpc_deployment/roles/raxmon_agent_install/templates/rackspace-monitoring-agent.cfg new file mode 100644 index 0000000000..b1dfcdec39 --- /dev/null +++ b/rpc_deployment/roles/raxmon_agent_install/templates/rackspace-monitoring-agent.cfg @@ -0,0 +1,2 @@ +monitoring_id {{ entity_name }} +monitoring_token {{ maas_agent_token }} diff --git a/rpc_deployment/roles/raxmon_cli/tasks/main.yml b/rpc_deployment/roles/raxmon_cli/tasks/main.yml new file mode 100644 index 0000000000..aaf056e8b6 --- /dev/null +++ b/rpc_deployment/roles/raxmon_cli/tasks/main.yml @@ -0,0 +1,25 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Install rackspace-monitoring-cli + pip: name=rackspace-monitoring-cli + +- name: Drop .raxrc file + template: + src: raxrc.j2 + dest: /root/.raxrc + mode: 0600 + owner: root + group: root diff --git a/rpc_deployment/roles/raxmon_cli/templates/raxrc.j2 b/rpc_deployment/roles/raxmon_cli/templates/raxrc.j2 new file mode 100644 index 0000000000..2fa21ae742 --- /dev/null +++ b/rpc_deployment/roles/raxmon_cli/templates/raxrc.j2 @@ -0,0 +1,17 @@ +{% if maas_auth_method == "password" %} +[credentials] +username={{ maas_username }} +api_key={{ maas_api_key }} + +[auth_api] +url={{ maas_auth_url }}/tokens + +{% endif %} +{% if maas_auth_method == "token" %} +[api] +url={{ maas_api_url }} +token={{ maas_auth_token }} + +{% endif %} +[ssl] +verify=true diff --git a/rpc_deployment/roles/rpc_support_api/tasks/main.yml b/rpc_deployment/roles/rpc_support_api/tasks/main.yml new file mode 100644 index 0000000000..7faf0cb623 --- /dev/null +++ b/rpc_deployment/roles/rpc_support_api/tasks/main.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: support_key_pair.yml +- include: support_sec_group.yml diff --git a/rpc_deployment/roles/rpc_support_api/tasks/support_key_pair.yml b/rpc_deployment/roles/rpc_support_api/tasks/support_key_pair.yml new file mode 100644 index 0000000000..6a475e20d7 --- /dev/null +++ b/rpc_deployment/roles/rpc_support_api/tasks/support_key_pair.yml @@ -0,0 +1,43 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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 rpc_support SSH key + user: + name: root + generate_ssh_key: yes + ssh_key_bits: 2048 + ssh_key_comment: "rpc_support key added for Openstack Instances" + ssh_key_file: "/root/.ssh/rpc_support" + register: support_key + tags: + - support_key + - support_keypair + +- name: Check for rpc_support keypair in nova + shell: | + . /root/openrc + nova keypair-list | grep rpc_support + register: rpc_support_key + when: support_key|changed + tags: + - support_keypair + +- name: Add rpc_support key to nova + shell: | + . /root/openrc + nova keypair-add --pub-key /root/.ssh/rpc_support.pub rpc_support + when: support_key|changed and rpc_support_key.rc != 0 + tags: + - support_keypair diff --git a/rpc_deployment/roles/rpc_support_api/tasks/support_sec_group.yml b/rpc_deployment/roles/rpc_support_api/tasks/support_sec_group.yml new file mode 100644 index 0000000000..a717533eb2 --- /dev/null +++ b/rpc_deployment/roles/rpc_support_api/tasks/support_sec_group.yml @@ -0,0 +1,66 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Check for rpc_support security group + shell: | + . /root/openrc + neutron security-group-list | /bin/grep -w "rpc-support" + register: rpc_support_sec_group + changed_when: false + failed_when: rpc_support_sec_group.rc not in [0, 1] + tags: + - sec_group + +- name: Create rpc_support security group + shell: | + . /root/openrc + neutron security-group-create rpc-support + register: sec_group_create + changed_when: sec_group_create.rc == 0 + failed_when: sec_group_create.rc != 0 + when: rpc_support_sec_group.rc != 0 + tags: + - sec_group + +- name: Create rpc_support security group rules ports + shell: | + . /root/openrc + neutron security-group-rule-create --direction ingress \ + --protocol tcp \ + --port-range-min {{ item }} \ + --port-range-max {{ item }} \ + --remote-ip-prefix 0.0.0.0/0 \ + rpc-support + register: sec_group_rules_ports + when: sec_group_create|changed + with_items: + - 22 + - 3389 + tags: + - sec_group + - sec_group_rules + +- name: Create rpc_support security group rules icmp + shell: | + . /root/openrc + neutron security-group-rule-create --direction ingress \ + --protocol icmp \ + --remote-ip-prefix 0.0.0.0/0 \ + rpc-support + register: sec_group_rules_icmp + when: sec_group_create|changed + tags: + - sec_group + - sec_group_rules diff --git a/rpc_deployment/roles/rpc_support_common/handlers/main.yml b/rpc_deployment/roles/rpc_support_common/handlers/main.yml new file mode 100644 index 0000000000..b6ad3b456e --- /dev/null +++ b/rpc_deployment/roles/rpc_support_common/handlers/main.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: SSH restart + service: + name: ssh + state: restarted + pattern: sshd diff --git a/rpc_deployment/roles/rpc_support_common/tasks/bashrc.yml b/rpc_deployment/roles/rpc_support_common/tasks/bashrc.yml new file mode 100644 index 0000000000..7882c7021c --- /dev/null +++ b/rpc_deployment/roles/rpc_support_common/tasks/bashrc.yml @@ -0,0 +1,28 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Check default editor + shell: + echo '' | update-alternatives --config editor | grep 'mode' | grep '*' + register: editor + failed_when: false + tags: + - set_vim_editor + +- name: Set vim as default + command: update-alternatives --set editor /usr/bin/vim.basic + when: editor.rc != 0 and not editor.stdout|search('vim') + tags: + - set_vim_editor diff --git a/rpc_deployment/roles/rpc_support_common/tasks/histformat.yml b/rpc_deployment/roles/rpc_support_common/tasks/histformat.yml new file mode 100644 index 0000000000..b3ed84ef92 --- /dev/null +++ b/rpc_deployment/roles/rpc_support_common/tasks/histformat.yml @@ -0,0 +1,24 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Set history format file + template: + owner: root + group: root + mode: 0755 + src: histformat.sh.j2 + dest: "/etc/profile.d/histformat.sh" + tags: + - history_config diff --git a/rpc_deployment/roles/rpc_support_common/tasks/main.yml b/rpc_deployment/roles/rpc_support_common/tasks/main.yml new file mode 100644 index 0000000000..85200eb6d0 --- /dev/null +++ b/rpc_deployment/roles/rpc_support_common/tasks/main.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: support_packages.yml +- include: bashrc.yml +- include: histformat.yml +- include: motd.yml diff --git a/rpc_deployment/roles/rpc_support_common/tasks/motd.yml b/rpc_deployment/roles/rpc_support_common/tasks/motd.yml new file mode 100644 index 0000000000..6fd9fc8832 --- /dev/null +++ b/rpc_deployment/roles/rpc_support_common/tasks/motd.yml @@ -0,0 +1,34 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Ensude motd is not printed in ssh + lineinfile: + dest: /etc/ssh/sshd_config + regexp: "^PrintMotd" + line: "PrintMotd yes" + state: present + notify: SSH restart + tags: + - set_motd + +- name: Setup support motd + template: + owner: root + group: root + mode: 0755 + src: 20-openstack.j2 + dest: "/etc/update-motd.d/20-openstack" + tags: + - set_motd diff --git a/rpc_deployment/roles/rpc_support_common/tasks/support_packages.yml b/rpc_deployment/roles/rpc_support_common/tasks/support_packages.yml new file mode 100644 index 0000000000..4e28996c99 --- /dev/null +++ b/rpc_deployment/roles/rpc_support_common/tasks/support_packages.yml @@ -0,0 +1,34 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Ensure rpc support packages are installed + apt: + pkg: "{{ item }}" + state: present + update_cache: yes + cache_valid_time: 600 + with_items: + - vim + - linux-crashdump + - iotop + - dstat + - tcpdump + - lsof + - htop + register: rpc_support_packages + until: rpc_support_packages|success + retries: 3 + tags: + - support_packages diff --git a/rpc_deployment/roles/rpc_support_common/templates/20-openstack.j2 b/rpc_deployment/roles/rpc_support_common/templates/20-openstack.j2 new file mode 100644 index 0000000000..0473fc354e --- /dev/null +++ b/rpc_deployment/roles/rpc_support_common/templates/20-openstack.j2 @@ -0,0 +1,6 @@ +#!/bin/sh +printf "\n\n************** +WARNING: This is an OpenStack Private Cloud device. +Please log out if you are not familiar with these environments. +Contact 700-NOVA if you have any questons. +**************\n\n" diff --git a/rpc_deployment/roles/rpc_support_common/templates/histformat.sh.j2 b/rpc_deployment/roles/rpc_support_common/templates/histformat.sh.j2 new file mode 100644 index 0000000000..76880aeca4 --- /dev/null +++ b/rpc_deployment/roles/rpc_support_common/templates/histformat.sh.j2 @@ -0,0 +1,3 @@ +# Add timestamp to history +# 2013-12-16 00:00:00 +export HISTTIMEFORMAT="%F %T " \ No newline at end of file diff --git a/rpc_deployment/roles/rpc_support_holland/tasks/holland.yml b/rpc_deployment/roles/rpc_support_holland/tasks/holland.yml new file mode 100644 index 0000000000..b03e416cd8 --- /dev/null +++ b/rpc_deployment/roles/rpc_support_holland/tasks/holland.yml @@ -0,0 +1,136 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Ensure supporting holland packages are installed + apt: + pkg: "{{ item }}" + state: present + update_cache: yes + cache_valid_time: 600 + with_items: + - mariadb-client + - xtrabackup + register: rpc_support_packages + until: rpc_support_packages|success + retries: 3 + tags: + - holland_supporting_packages + - holland_all + +- name: Create rpc_support backup user + mysql_user: + name: "{{ item.name }}" + host: "{{ item.host }}" + password: "{{ item.password }}" + priv: "{{ item.priv }}" + state: "{{ item.state }}" + with_items: + - name: "rpc_support" + host: "%" + password: "{{ rpc_support_holland_password }}" + priv: "*.*:ALL" + state: present + - name: "rpc_support" + host: "localhost" + password: "{{ rpc_support_holland_password }}" + priv: "*.*:ALL" + state: present + tags: + - holland_sql_user + - holland_all + +- name: Get holland from git + git: + repo: https://github.com/holland-backup/holland + dest: "/opt/holland_{{ holland_release }}" + version: "{{ holland_release }}" + register: holland_clone + until: holland_clone|success + retries: 5 + tags: + - holland_source + - holland_all + +- name: Install holland source + pip: + name: "{{ item }}" + with_items: + - "mysql-python" + - "/opt/holland_{{ holland_release }}" + - "/opt/holland_{{ holland_release }}/plugins/holland.lib.common" + - "/opt/holland_{{ holland_release }}/plugins/holland.lib.mysql" + - "/opt/holland_{{ holland_release }}/plugins/holland.backup.xtrabackup" + tags: + - holland_source + - holland_all + +- name: Create supporting holland directories + file: + state: directory + path: "{{ item }}" + with_items: + - "/var/lib/mysql/holland_backups" + - "/etc/holland" + tags: + - holland_dir + - holland_all + +- name: Create links to point to holland config files + file: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + state: link + with_items: + - { src: "/opt/holland_{{ holland_release }}/config/providers", dest: "/etc/holland/providers" } + - { src: "/opt/holland_{{ holland_release }}/config/backupsets", dest: "/etc/holland/backupsets" } + tags: + - holland_conf + - holland_all + +- name: Setup holland backup + template: + owner: root + group: root + src: "{{ item.src }}" + dest: "{{ item.dest }}" + with_items: + - { src: "holland-xtrabackup.conf.j2", dest: "/etc/holland/backupsets/rpc_support.conf" } + - { src: "holland.conf.j2", dest: "/etc/holland/holland.conf" } + tags: + - holland_conf + - holland_all + +- name: Check for holland cron file + command: ls /etc/cron.d/holland_backups + failed_when: false + changed_when: holland_cron.rc != 0 + register: holland_cron + tags: + - holland_cron + - holland_all + +- name: Create holland backup cron job + cron: + name: "holland-backup" + minute: "{{ 59|random }}" + weekday: "{{ 6|random }}" + state: present + job: "holland bk" + user: root + cron_file: holland_backups + when: holland_cron.rc != 0 + tags: + - holland_cron + - holland_all diff --git a/rpc_deployment/roles/rpc_support_holland/tasks/main.yml b/rpc_deployment/roles/rpc_support_holland/tasks/main.yml new file mode 100644 index 0000000000..a23ae38b35 --- /dev/null +++ b/rpc_deployment/roles/rpc_support_holland/tasks/main.yml @@ -0,0 +1,16 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: holland.yml diff --git a/rpc_deployment/roles/rpc_support_holland/templates/holland-xtrabackup.conf.j2 b/rpc_deployment/roles/rpc_support_holland/templates/holland-xtrabackup.conf.j2 new file mode 100644 index 0000000000..41dfb6ee5c --- /dev/null +++ b/rpc_deployment/roles/rpc_support_holland/templates/holland-xtrabackup.conf.j2 @@ -0,0 +1,41 @@ +## Default Backup-Set +## +## Backs up all MySQL databases in a one-file-per-database fashion using +## lightweight in-line compression and engine auto-detection. This backup-set +## is designed to provide reliable backups "out of the box", however it is +## generally advisable to create additional custom backup-sets to suit +## one's specific needs. + +# For more inforamtion about backup-sets, please consult the online Holland +# documentation. Fully-commented example backup-sets are also provided, by +# default, in /etc/holland/backupsets/examples. +[holland:backup] +plugin = xtrabackup +backups-to-keep = {{ rpc_support_holland_num_backups|default('4') }} +auto-purge-failures = {{ rpc_support_holland_purge_failures|default('yes') }} +purge-policy = after-backup +estimated-size-factor = 1.0 + +# This section defines the configuration options specific to the backup +# plugin. In other words, the name of this section should match the name +# of the plugin defined above. +[xtrabackup] +global-defaults = /etc/mysql/my.cnf +# innobackupex = +# ibbackup = +# stream = +# apply-logs = +# slave-info = +# safe-slave-backup = +# no-lock = +# tmpdir = +# additional-options = +# pre-command = + +# MySQL client configurations +[mysql:client] +defaults-extra-file = /root/.my.cnf +user = rpc_support +password = {{ rpc_support_holland_password }} +host = {{ internal_vip_address }} +port = {{ mysql_port }} diff --git a/rpc_deployment/roles/rpc_support_holland/templates/holland.conf.j2 b/rpc_deployment/roles/rpc_support_holland/templates/holland.conf.j2 new file mode 100644 index 0000000000..5effeac0ed --- /dev/null +++ b/rpc_deployment/roles/rpc_support_holland/templates/holland.conf.j2 @@ -0,0 +1,26 @@ +## Root holland config file +[holland] +## Paths where holland plugins may be found. +## Can be comma separated +plugin_dirs = /usr/share/holland/plugins + +## Top level directory where backups are held +backup_directory = /var/lib/mysql/holland_backups + +## List of enabled backup sets. Can be comma separated. +## Read from /backupsets/.conf +# backupsets = example, traditional, parallel_backups, non_transactional +backupsets = rpc_support + +# Define a umask for file generated by holland +umask = 0007 + +# Define a path for holland and its spawned processes +path = /usr/local/bin:/usr/local/sbin:/bin:/sbin:/usr/bin:/usr/sbin + +[logging] +## where to write the log +filename = /var/log/mysql/holland.log + +## debug, info, warning, error, critical (case insensitive) +level = info diff --git a/rpc_deployment/roles/rsyslog/tasks/main.yml b/rpc_deployment/roles/rsyslog/tasks/main.yml new file mode 100644 index 0000000000..61cb89c164 --- /dev/null +++ b/rpc_deployment/roles/rsyslog/tasks/main.yml @@ -0,0 +1,24 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Rsyslog Setup + template: > + src={{ item }} + dest=/etc/rsyslog.d/{{ item }} + owner=root + group=root + register: results + with_items: + - 50-default.conf diff --git a/rpc_deployment/roles/rsyslog/templates/50-default.conf b/rpc_deployment/roles/rsyslog/templates/50-default.conf new file mode 100644 index 0000000000..c9e8c99106 --- /dev/null +++ b/rpc_deployment/roles/rsyslog/templates/50-default.conf @@ -0,0 +1,72 @@ +# Default rules for rsyslog. +# +# For more information see rsyslog.conf(5) and /etc/rsyslog.conf + +# +# First some standard log files. Log by facility. +# +auth,authpriv.* /var/log/auth.log +*.*;local7.none;auth,authpriv.none /var/log/syslog +syslog.* /var/log/rsyslog.log #rsyslog error messages +#cron.* /var/log/cron.log +#daemon.* /var/log/daemon.log +kern.* /var/log/kern.log +#lpr.* /var/log/lpr.log +mail.* /var/log/mail.log +#user.* /var/log/user.log + +# +# Logging for the mail system. Split it up so that +# it is easy to write scripts to parse these files. +# +#mail.info /var/log/mail.info +#mail.warn /var/log/mail.warn +mail.err /var/log/mail.err + +# +# Logging for INN news system. +# +news.crit /var/log/news/news.crit +news.err /var/log/news/news.err +news.notice /var/log/news/news.notice + +# +# Some "catch-all" log files. +# +#*.=debug;\ +# auth,authpriv.none;\ +# news.none;mail.none /var/log/debug +#*.=info;*.=notice;*.=warn;\ +# auth,authpriv.none;\ +# cron,daemon.none;\ +# mail,news.none /var/log/messages + +# +# Emergencies are sent to everybody logged in. +# +*.emerg :omusrmsg:* + +# +# I like to have messages displayed on the console, but only on a virtual +# console I usually leave idle. +# +#daemon,mail.*;\ +# news.=crit;news.=err;news.=notice;\ +# *.=debug;*.=info;\ +# *.=notice;*.=warn /dev/tty8 + +# The named pipe /dev/xconsole is for the `xconsole' utility. To use it, +# you must invoke `xconsole' with the `-file' option: +# +# $ xconsole -file /dev/xconsole [...] +# +# NOTE: adjust the list below, or you'll go crazy if you have a reasonably +# busy site.. +# +# +# As this functionality is almost never needed, it is commented out. If you +# need it, be sure to remove the comment characters below. +#daemon.*;mail.*;\ +# news.err;\ +# *.=debug;*.=info;\ +# *.=notice;*.=warn |/dev/xconsole diff --git a/rpc_deployment/roles/rsyslog_config/tasks/main.yml b/rpc_deployment/roles/rsyslog_config/tasks/main.yml new file mode 100644 index 0000000000..bdd169bf13 --- /dev/null +++ b/rpc_deployment/roles/rsyslog_config/tasks/main.yml @@ -0,0 +1,41 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Deploy rsyslog config generator + template: > + src={{ item }} + dest=/opt/{{ item }} + owner=root + group=root + mode=0755 + with_items: + - genlog.py + +- name: Stop rsyslog + service: name=rsyslog state=stopped pattern=rsyslog + +- name: Generate Config Files + shell: > + /opt/genlog.py > /etc/rsyslog.d/51-openstack.conf + +- name: Ensure ownership on /var/spool/rsyslog + file: > + path=/var/spool/rsyslog + state=directory + owner=syslog + group=syslog + +- name: Start rsyslog + service: name=rsyslog state=restarted pattern=rsyslog diff --git a/rpc_deployment/roles/rsyslog_config/templates/genlog.py b/rpc_deployment/roles/rsyslog_config/templates/genlog.py new file mode 100644 index 0000000000..b11e62448b --- /dev/null +++ b/rpc_deployment/roles/rsyslog_config/templates/genlog.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# Copyright 2014, Rackspace US, Inc. +# +# 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 os +import fnmatch + +print "$ModLoad imfile\t\t# Load the imfile input module\n" +print "$ActionQueueType LinkedList\t\t# Use asynchronous processing" +print "$ActionQueueFileName srvrfwd\t\t# Set file name, also enables disk mode" +print "$ActionResumeRetryCount -1\t\t# Infinite retries on insert failure" +print "$ActionQueueSaveOnShutdown on\t\t# Save in-memory data if rsyslog shuts down\n" + +matches = [] +for root, dirnames, filenames in os.walk('/openstack/log'): + for filename in fnmatch.filter(filenames, '*.log'): + matches.append(os.path.join(root, filename)) + +for log in matches: + container = log.split('/')[3] + service = log.split('/')[4].split('.')[0] + if 'horizon' in container: + service = container + '_' + service + + print "$InputFileName {}".format(log) + print "$InputFileTag {}:".format(container) + print "$InputFileStateFile state-{}".format(service) + print "$InputFileFacility local7" + print "$InputRunFileMonitor\n" + +{% raw %} +print r'''$template ls_json,"{%timestamp:::date-rfc3339,jsonf:@timestamp%,%source:::jsonf:@source_host%,\"@source\":\"syslog://%app-name:::json%\",\"@message\":\"%msg:::json%\",\"@fields\":{%syslogfacility-text:::jsonf:facility%,%syslogseverity-text:::jsonf:severity%,%app-name:::jsonf:program%,%procid:::jsonf:processid%}}"''' +{% endraw %} + +print "*.* @@{{ hostvars[groups['logstash'][0]]['container_address'] }}:{{ logstash_port }};ls_json" diff --git a/rpc_deployment/roles/rsyslog_stop/tasks/main.yml b/rpc_deployment/roles/rsyslog_stop/tasks/main.yml new file mode 100644 index 0000000000..c8fdba7961 --- /dev/null +++ b/rpc_deployment/roles/rsyslog_stop/tasks/main.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: stop rsyslog + service: name=rsyslog state=stopped pattern=rsyslog diff --git a/rpc_deployment/roles/safe_upgrade/tasks/main.yml b/rpc_deployment/roles/safe_upgrade/tasks/main.yml new file mode 100644 index 0000000000..41941b04d7 --- /dev/null +++ b/rpc_deployment/roles/safe_upgrade/tasks/main.yml @@ -0,0 +1,27 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Update cache + apt: > + update_cache=yes + cache_valid_time=10800 + +- name: Ensure Aptitude + apt: > + pkg=aptitude + state=present + +- name: Do safe upgrade + apt: upgrade=safe diff --git a/rpc_deployment/roles/utility_common/files/Rakefile b/rpc_deployment/roles/utility_common/files/Rakefile new file mode 100644 index 0000000000..b6a9881353 --- /dev/null +++ b/rpc_deployment/roles/utility_common/files/Rakefile @@ -0,0 +1,8 @@ +require 'rake' +require 'rspec/core/rake_task' + +RSpec::Core::RakeTask.new(:spec) do |t| + t.pattern = 'spec/*/*_spec.rb' +end + +task :default => :spec diff --git a/rpc_deployment/roles/utility_common/files/spec_helper.rb b/rpc_deployment/roles/utility_common/files/spec_helper.rb new file mode 100644 index 0000000000..a243a582ca --- /dev/null +++ b/rpc_deployment/roles/utility_common/files/spec_helper.rb @@ -0,0 +1,31 @@ +require 'serverspec' +require 'pathname' +require 'net/ssh' + +include SpecInfra::Helper::Ssh +include SpecInfra::Helper::DetectOS + +RSpec.configure do |c| + if ENV['ASK_SUDO_PASSWORD'] + require 'highline/import' + c.sudo_password = ask("Enter sudo password: ") { |q| q.echo = false } + else + c.sudo_password = ENV['SUDO_PASSWORD'] + end + c.before :all do + block = self.class.metadata[:example_group_block] + if RUBY_VERSION.start_with?('1.8') + file = block.to_s.match(/.*@(.*):[0-9]+>/)[1] + else + file = block.source_location.first + end + host = File.basename(Pathname.new(file).dirname) + if c.host != host + c.ssh.close if c.ssh + c.host = host + options = Net::SSH::Config.for(c.host) + user = options[:user] || Etc.getlogin + c.ssh = Net::SSH.start(host, user, options) + end + end +end diff --git a/rpc_deployment/roles/utility_common/tasks/main.yml b/rpc_deployment/roles/utility_common/tasks/main.yml new file mode 100644 index 0000000000..1dc945395f --- /dev/null +++ b/rpc_deployment/roles/utility_common/tasks/main.yml @@ -0,0 +1,49 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Grab private ssh key + set_fact: + private_ssh_key: "{{ lookup('file', '~/.ssh/id_rsa') }}" + +- name: Drop in private ssh key + copy: + content: "{{ private_ssh_key }}" + dest: ~/.ssh/id_rsa + mode: 0600 + owner: root + group: root + +- name: Install serverspec + gem: name=serverspec user_install=false + +- name: "Create {{ serverspec_install_dir }}/spec directory" + file: + dest: "{{ serverspec_install_dir }}/spec" + state: directory + +- name: Drop in Rakefile + copy: + src: Rakefile + dest: "{{ serverspec_install_dir }}/Rakefile" + +- name: Drop in spec_helper.rb + copy: + src: spec_helper.rb + dest: "{{ serverspec_install_dir }}/spec/spec_helper.rb" + +- name: Create localhost directory + file: + dest: "{{ serverspec_install_dir }}/spec/localhost" + state: directory diff --git a/rpc_deployment/roles/utility_create_configs/tasks/main.yml b/rpc_deployment/roles/utility_create_configs/tasks/main.yml new file mode 100644 index 0000000000..c7b547533d --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/tasks/main.yml @@ -0,0 +1,38 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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 directories for each host + file: + name: "{{ serverspec_install_dir }}/spec/{{ ansible_ssh_host }}" + state: directory + with_items: groups['utility_all'] + delegate_to: "{{ item }}" + +- name: Create all role checks for each host + template: + src: "all_spec.rb.j2" + dest: "{{ serverspec_install_dir }}/spec/{{ ansible_ssh_host }}/all_spec.rb" + with_items: groups['utility_all'] + delegate_to: "{{ item }}" + +- name: Create appropriate role checks for each host + template: + src: "{{ item[1] }}_spec.rb.j2" + dest: "{{ serverspec_install_dir }}/spec/{{ ansible_ssh_host }}/{{ item[1] }}_spec.rb" + with_nested: + - groups['utility_all'] + - openstack_service_types + when: item[1] in group_names + delegate_to: "{{ item[0] }}" diff --git a/rpc_deployment/roles/utility_create_configs/templates/all_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/all_spec.rb.j2 new file mode 100644 index 0000000000..bac5912f11 --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/all_spec.rb.j2 @@ -0,0 +1,12 @@ +require 'spec_helper' + +os_packages = %w( python-software-properties python-dev build-essential + git-core rsyslog lvm2 libssl-dev bridge-utils cgroup-lite + sqlite3 iptables sshpass libffi-dev libxml2-dev libxslt1-dev + mariadb-client libmariadbclient-dev ) + +os_packages.each do |os| + describe package(os) do + it { should be_installed } + end +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/cinder_all_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/cinder_all_spec.rb.j2 new file mode 100644 index 0000000000..bbd95b38c3 --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/cinder_all_spec.rb.j2 @@ -0,0 +1,49 @@ +require 'spec_helper' + +os_packages = %w( libpq-dev ) + +pip_packages = %w( pywbem MySQL-python python-cinderclient + python-keystoneclient cinder ) + +directories = %w( /var/log/cinder /var/lib/cinder /etc/cinder + /etc/cinder/rootwrap.d /var/cache/cinder /var/lock/cinder + /var/run/cinder ) + +conf_files = %w( cinder.conf api-paste.ini policy.json rootwrap.conf + rootwrap.d/volume.filters ) + +os_packages.each do |os| + describe package(os) do + it { should be_installed } + end +end + +pip_packages.each do |pip| + describe package(pip) do + it { should be_installed.by('pip') } + end +end + +describe user('cinder') do + it { should exist } +end + +describe group('cinder') do + it { should exist } +end + +directories.each do |d| + describe file(d) do + it { should be_directory } + it { should be_owned_by 'cinder' } + it { should be_grouped_into 'cinder' } + end +end + +conf_files.each do |f| + describe file("/etc/cinder/#{f}") do + it { should be_file } + it { should be_owned_by 'cinder' } + it { should be_grouped_into 'cinder' } + end +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/cinder_api_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/cinder_api_spec.rb.j2 new file mode 100644 index 0000000000..1648c16828 --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/cinder_api_spec.rb.j2 @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe service('cinder-api') do + it { should be_enabled } + it { should be_running } +end + +describe port(8776) do + it { should be_listening } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/cinder_scheduler_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/cinder_scheduler_spec.rb.j2 new file mode 100644 index 0000000000..10fe0ee6d3 --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/cinder_scheduler_spec.rb.j2 @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe service('cinder-scheduler') do + it { should be_enabled } + it { should be_running } +end + +describe process('cinder-scheduler') do + it { should be_running } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/cinder_volume_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/cinder_volume_spec.rb.j2 new file mode 100644 index 0000000000..6baff98efb --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/cinder_volume_spec.rb.j2 @@ -0,0 +1,14 @@ +require 'spec_helper' + +describe service('cinder-volume') do + it { should be_enabled } + it { should be_running } +end + +describe process('cinder-volume') do + it { should be_running } +end + +describe kernel_module('dm_snapshot') do + it { should be_loaded } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/glance_all_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/glance_all_spec.rb.j2 new file mode 100644 index 0000000000..e35d3a085d --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/glance_all_spec.rb.j2 @@ -0,0 +1,51 @@ +require 'spec_helper' + +os_packages = %w( rsync ) + +pip_packages = %w( warlock MySQL-python python-glanceclient + python-keystoneclient glance ) + + +directories = %w( /var/log/glance /var/lib/glance /var/lib/glance/cache + /var/lib/glance/cache/api /var/lib/glance/cache/registry + /var/lib/glance/scrubber /etc/glance /var/cache/glance ) + +conf_files = %w( glance-api.conf glance-cache.conf glance-registry-paste.ini + glance-registry.conf glance-scrubber.conf policy.json + schema-image.json ) + +os_packages.each do |os| + describe package(os) do + it { should be_installed } + end +end + +pip_packages.each do |pip| + describe package(pip) do + it { should be_installed.by('pip') } + end +end + +describe user('glance') do + it { should exist } +end + +describe group('glance') do + it { should exist } +end + +directories.each do |d| + describe file(d) do + it { should be_directory } + it { should be_owned_by 'glance' } + it { should be_grouped_into 'glance' } + end +end + +conf_files.each do |f| + describe file("/etc/glance/#{f}") do + it { should be_file } + it { should be_owned_by 'glance' } + it { should be_grouped_into 'glance' } + end +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/glance_api_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/glance_api_spec.rb.j2 new file mode 100644 index 0000000000..951e0e836e --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/glance_api_spec.rb.j2 @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe service('glance-api') do + it { should be_enabled } + it { should be_running } +end + +describe port(9292) do + it { should be_listening } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/glance_registry_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/glance_registry_spec.rb.j2 new file mode 100644 index 0000000000..9155f13f38 --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/glance_registry_spec.rb.j2 @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe service('glance-registry') do + it { should be_enabled } + it { should be_running } +end + +describe port(9191) do + it { should be_listening } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/heat_all_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/heat_all_spec.rb.j2 new file mode 100644 index 0000000000..5a83faceaf --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/heat_all_spec.rb.j2 @@ -0,0 +1,49 @@ +require 'spec_helper' + +os_packages = %w( rsync libxslt1.1 ) + +pip_packages = %w( MySQL-python python-heatclient python-keystoneclient + python-troveclient python-ceilometerclient ) + +directories = %w( /etc/heat /etc/heat/environment.d /etc/heat/templates + /var/cache/heat /var/lib/heat /var/log/heat ) + +conf_files = %w( heat.conf environment.d/default.yaml + templates/AWS_CloudWatch_Alarm.yaml + templates/AWS_RDS_DBInstance.yaml api-paste.ini policy.json ) + +os_packages.each do |os| + describe package(os) do + it { should be_installed } + end +end + +pip_packages.each do |pip| + describe package(pip) do + it { should be_installed.by('pip') } + end +end + +describe user('heat') do + it { should exist } +end + +describe group('heat') do + it { should exist } +end + +directories.each do |d| + describe file(d) do + it { should be_directory } + it { should be_owned_by 'heat' } + it { should be_grouped_into 'heat' } + end +end + +conf_files.each do |f| + describe file("/etc/heat/#{f}") do + it { should be_file } + it { should be_owned_by 'heat' } + it { should be_grouped_into 'heat' } + end +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/heat_api_cfn_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/heat_api_cfn_spec.rb.j2 new file mode 100644 index 0000000000..0f8c4f55f5 --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/heat_api_cfn_spec.rb.j2 @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe service('heat-api-cfn') do + it { should be_enabled } + it { should be_running } +end + +describe port(8000) do + it { should be_listening } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/heat_api_cloudwatch_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/heat_api_cloudwatch_spec.rb.j2 new file mode 100644 index 0000000000..4cf40f1a5f --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/heat_api_cloudwatch_spec.rb.j2 @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe service('heat-api-cloudwatch') do + it { should be_enabled } + it { should be_running } +end + +describe port(8003) do + it { should be_listening } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/heat_api_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/heat_api_spec.rb.j2 new file mode 100644 index 0000000000..02e9390006 --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/heat_api_spec.rb.j2 @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe service('heat-api') do + it { should be_enabled } + it { should be_running } +end + +describe port(8004) do + it { should be_listening } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/heat_engine_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/heat_engine_spec.rb.j2 new file mode 100644 index 0000000000..886d5363bd --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/heat_engine_spec.rb.j2 @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe service('heat-engine') do + it { should be_enabled } + it { should be_running } +end + +describe process('heat-engine') do + it { should be_running } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/horizon_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/horizon_spec.rb.j2 new file mode 100644 index 0000000000..7d7efdd77c --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/horizon_spec.rb.j2 @@ -0,0 +1,57 @@ +require 'spec_helper' + +os_packages = %w( apache2 apache2-utils libapache2-mod-wsgi libssl-dev + libxslt1.1 ) + +pip_packages = %w( oslo.config MySQL-python ) + + +directories = %w( /opt/horizon /opt/horizon/lib/python2.7/site-packages) + +conf_files = %w( /etc/apache2/conf-enabled/openstack-dashboard.conf + /opt/horizon/lib/python2.7/site-packages/openstack_dashboard/local/local_settings.py ) + +os_packages.each do |os| + describe package(os) do + it { should be_installed } + end +end + +pip_packages.each do |pip| + describe package(pip) do + it { should be_installed.by('pip') } + end +end + +describe user('www-data') do + it { should exist } +end + +describe group('www-data') do + it { should exist } +end + +directories.each do |d| + describe file(d) do + it { should be_directory } + it { should be_owned_by 'www-data' } + it { should be_grouped_into 'www-data' } + end +end + +conf_files.each do |f| + describe file(f) do + it { should be_file } + it { should be_owned_by 'www-data' } + it { should be_grouped_into 'www-data' } + end +end + +describe service('apache2') do + it { should be_enabled } + it { should be_running } +end + +describe port(80) do + it { should be_listening } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/keystone_all_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/keystone_all_spec.rb.j2 new file mode 100644 index 0000000000..894bf05999 --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/keystone_all_spec.rb.j2 @@ -0,0 +1,67 @@ +require 'spec_helper' + +os_packages = %w( libsasl2-dev debhelper dh-apparmor docutils-common + libjs-sphinxdoc libjs-underscore libxslt1.1 libldap2-dev + apache2 apache2-utils libapache2-mod-wsgi) + +pip_packages = %w( repoze.lru pbr MySQL-python python-keystoneclient keystone ) + +directories = %w( /etc/keystone /etc/keystone/ssl /var/lib/keystone + /var/log/keystone ) + +conf_files = %w( default_catalog.templates keystone-paste.ini keystone.conf + policy.json policy.v3cloudsample.json ) + +os_packages.each do |os| + describe package(os) do + it { should be_installed } + end +end + +pip_packages.each do |pip| + describe package(pip) do + it { should be_installed.by('pip') } + end +end + +describe user('keystone') do + it { should exist } +end + +describe group('keystone') do + it { should exist } +end + +directories.each do |d| + describe file(d) do + it { should be_directory } + it { should be_owned_by 'keystone' } + it { should be_grouped_into 'keystone' } + end +end + +conf_files.each do |f| + describe file("/etc/keystone/#{f}") do + it { should be_file } + it { should be_owned_by 'keystone' } + it { should be_grouped_into 'keystone' } + end +end + +# the following host checks could be run from all containers, however +# we'll assume if they're accessible from the keystone containers then +# they're accessible to the rest +describe host('{{ mysql_address }}') do + it { should be_reachable.with( :port => {{ mysql_port }} ) } +end + +# rabbit_hosts may be a comma-separated list of ip:port rabbit servers, +# so we take that into account here +'{{ rabbit_hosts }}'.split(',').each do |rabbit| + host = rabbit.split(':')[0] + port = rabbit.split(':')[1] + + describe host(host) do + it { should be_reachable.with( :port => port ) } + end +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/keystone_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/keystone_spec.rb.j2 new file mode 100644 index 0000000000..fefcf8d64c --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/keystone_spec.rb.j2 @@ -0,0 +1,14 @@ +require 'spec_helper' + +describe service('apache2') do + it { should be_enabled } + it { should be_running } +end + +describe port(5000) do + it { should be_listening } +end + +describe port(35357) do + it { should be_listening } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/neutron_all_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/neutron_all_spec.rb.j2 new file mode 100644 index 0000000000..310bc1c85f --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/neutron_all_spec.rb.j2 @@ -0,0 +1,49 @@ +require 'spec_helper' + +os_packages = %w( libpq-dev dnsmasq ) + +pip_packages = %w( MySQL-python repoze.lru python-novaclient + python-neutronclient python-keystoneclient ) + +directories = %w( /etc/neutron /etc/neutron/plugins /etc/neutron/plugins/ml2 + /var/cache/neutron /var/lib/neutron /var/lock/neutron + /var/log/neutron /var/run/neutron ) + +conf_files = %w( neutron.conf metadata_agent.ini l3_agent.ini dhcp_agent.ini + plugins/ml2/ml2_conf.ini ) + +os_packages.each do |os| + describe package(os) do + it { should be_installed } + end +end + +pip_packages.each do |pip| + describe package(pip) do + it { should be_installed.by('pip') } + end +end + +describe user('neutron') do + it { should exist } +end + +describe group('neutron') do + it { should exist } +end + +directories.each do |d| + describe file(d) do + it { should be_directory } + it { should be_owned_by 'neutron' } + it { should be_grouped_into 'neutron' } + end +end + +conf_files.each do |f| + describe file("/etc/neutron/#{f}") do + it { should be_file } + it { should be_owned_by 'neutron' } + it { should be_grouped_into 'neutron' } + end +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/neutron_dhcp_agent_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/neutron_dhcp_agent_spec.rb.j2 new file mode 100644 index 0000000000..034ef6ba42 --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/neutron_dhcp_agent_spec.rb.j2 @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe service('neutron-dhcp-agent') do + it { should be_enabled } + it { should be_running } +end + +describe process('neutron-dhcp-agent') do + it { should be_running } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/neutron_linuxbridge_agent_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/neutron_linuxbridge_agent_spec.rb.j2 new file mode 100644 index 0000000000..75c7cbcaeb --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/neutron_linuxbridge_agent_spec.rb.j2 @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe service('neutron-linuxbridge-agent') do + it { should be_enabled } + it { should be_running } +end + +describe process('neutron-linuxbridge-agent') do + it { should be_running } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/neutron_metadata_agent_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/neutron_metadata_agent_spec.rb.j2 new file mode 100644 index 0000000000..63177b58ac --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/neutron_metadata_agent_spec.rb.j2 @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe service('neutron-metadata-agent') do + it { should be_enabled } + it { should be_running } +end + +describe process('neutron-metadata-agent') do + it { should be_running } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/neutron_server_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/neutron_server_spec.rb.j2 new file mode 100644 index 0000000000..9c78a48d71 --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/neutron_server_spec.rb.j2 @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe service('neutron-server') do + it { should be_enabled } + it { should be_running } +end + +describe port(9696) do + it { should be_listening } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/nova_all_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/nova_all_spec.rb.j2 new file mode 100644 index 0000000000..c45138de5f --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/nova_all_spec.rb.j2 @@ -0,0 +1,43 @@ +require 'spec_helper' + +os_packages = %w( libpq-dev ) + +pip_packages = %w( MySQL-python python-keystoneclient python-novaclient nova ) + +directories = %w( /var/log/nova /var/lib/nova /var/lib/nova/cache/api /etc/nova + /etc/nova/rootwrap.d /var/cache/nova /var/lock/nova + /var/run/nova ) + +os_packages.each do |os| + describe package(os) do + it { should be_installed } + end +end + +pip_packages.each do |pip| + describe package(pip) do + it { should be_installed.by('pip') } + end +end + +describe user('nova') do + it { should exist } +end + +describe group('nova') do + it { should exist } +end + +directories.each do |d| + describe file(d) do + it { should be_directory } + it { should be_owned_by 'nova' } + it { should be_grouped_into 'nova' } + end +end + +describe file('/etc/nova/nova.conf') do + it { should be_file } + it { should be_owned_by 'nova' } + it { should be_grouped_into 'nova' } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/nova_api_ec2_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/nova_api_ec2_spec.rb.j2 new file mode 100644 index 0000000000..1814c01b0f --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/nova_api_ec2_spec.rb.j2 @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe service('nova-api-ec2') do + it { should be_enabled } + it { should be_running } +end + +describe port(8773) do + it { should be_listening } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/nova_api_metadata_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/nova_api_metadata_spec.rb.j2 new file mode 100644 index 0000000000..0a610ad605 --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/nova_api_metadata_spec.rb.j2 @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe service('nova-api-metadata') do + it { should be_enabled } + it { should be_running } +end + +describe port(8775) do + it { should be_listening } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/nova_api_os_compute_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/nova_api_os_compute_spec.rb.j2 new file mode 100644 index 0000000000..0b91d1405b --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/nova_api_os_compute_spec.rb.j2 @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe service('nova-api-os-compute') do + it { should be_enabled } + it { should be_running } +end + +describe port(8774) do + it { should be_listening } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/nova_compute_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/nova_compute_spec.rb.j2 new file mode 100644 index 0000000000..e2059cf924 --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/nova_compute_spec.rb.j2 @@ -0,0 +1,29 @@ +require 'spec_helper' + +describe service('nova-compute') do + it { should be_enabled } + it { should be_running } +end + +describe process('nova-compute') do + it { should be_running } +end + +describe package('genisoimage') do + it { should be_installed } +end + +# really wish we could do with_version(/1.2.2/) :( +describe package('libvirt-bin') do + it { should be_installed.with_version('1.2.2-0ubuntu13.1.1') } +end + +describe package('python-libvirt') do + it { should be_installed.with_version('1.2.2-0ubuntu1') } +end + +%w( qemu qemu-utils ).each do |qcow_pkg| + describe package(qcow_pkg) do + it { should be_installed.with_version('2.0.0+dfsg-2ubuntu1.1') } + end +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/nova_conductor_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/nova_conductor_spec.rb.j2 new file mode 100644 index 0000000000..7f880d2d97 --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/nova_conductor_spec.rb.j2 @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe service('nova-conductor') do + it { should be_enabled } + it { should be_running } +end + +describe process('nova-conductor') do + it { should be_running } +end diff --git a/rpc_deployment/roles/utility_create_configs/templates/nova_scheduler_spec.rb.j2 b/rpc_deployment/roles/utility_create_configs/templates/nova_scheduler_spec.rb.j2 new file mode 100644 index 0000000000..a0acae88ba --- /dev/null +++ b/rpc_deployment/roles/utility_create_configs/templates/nova_scheduler_spec.rb.j2 @@ -0,0 +1,10 @@ +require 'spec_helper' + +describe service('nova-scheduler') do + it { should be_enabled } + it { should be_running } +end + +describe process('nova-scheduler') do + it { should be_running } +end diff --git a/rpc_deployment/roles/utility_keystone_checks/tasks/main.yml b/rpc_deployment/roles/utility_keystone_checks/tasks/main.yml new file mode 100644 index 0000000000..98267d85b1 --- /dev/null +++ b/rpc_deployment/roles/utility_keystone_checks/tasks/main.yml @@ -0,0 +1,24 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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 keystone checks for given service + template: + # We create the file w/ {{ service_type }} instead of {{ service_name }} as + # some services have service_name_ec2 and inherit service_name from parent + # (_all.yml) + src: keystone_checks_spec.rb.j2 + dest: "{{ serverspec_install_dir }}/spec/localhost/{{ service_type }}_keystone_checks_spec.rb" + delegate_to: "{{ item }}" + with_items: groups['utility_all'] diff --git a/rpc_deployment/roles/utility_keystone_checks/templates/keystone_checks_spec.rb.j2 b/rpc_deployment/roles/utility_keystone_checks/templates/keystone_checks_spec.rb.j2 new file mode 100644 index 0000000000..45d5f0f6ec --- /dev/null +++ b/rpc_deployment/roles/utility_keystone_checks/templates/keystone_checks_spec.rb.j2 @@ -0,0 +1,16 @@ +require 'spec_helper' + +# We run these checks from the utility container as this means we only have +# to drop openrc and install python-keystone client on a single container. + +describe command('source ~/openrc && keystone service-get {{ service_name }}') do + it { should return_exit_status 0 } +end + +describe command('source ~/openrc && keystone endpoint-get --service {{ service_type }}') do + it { should return_exit_status 0 } +end + +describe command('source ~/openrc && keystone user-get {{ service_admin_username }}') do + it { should return_exit_status 0 } +end diff --git a/rpc_deployment/roles/utility_logging/tasks/main.yml b/rpc_deployment/roles/utility_logging/tasks/main.yml new file mode 100644 index 0000000000..5205b4df7e --- /dev/null +++ b/rpc_deployment/roles/utility_logging/tasks/main.yml @@ -0,0 +1,29 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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: Install elasticshell + get_url: > + url=https://github.com/d34dh0r53/es2unix/raw/master/bin/es + dest=/usr/local/bin/es + mode=0755 + register: es_success + until: es_success|success + retries: 3 + + +- name: Alias elasticshell + lineinfile: > + dest=/etc/bash.bashrc + line="alias es='es -u http://{{ internal_vip_address }}:9200'" diff --git a/rpc_deployment/vars/config_vars/container_config_cinder_volume.yml b/rpc_deployment/vars/config_vars/container_config_cinder_volume.yml new file mode 100644 index 0000000000..ac8f0b2d99 --- /dev/null +++ b/rpc_deployment/vars/config_vars/container_config_cinder_volume.yml @@ -0,0 +1,28 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Set the options that we want for the container, these are config options. +# The option is set as a YAML list which translates into "key = value" in config +container_config_options: + - "lxc.aa_profile=lxc-openstack" + - "lxc.cgroup.devices.allow=a *:* rmw" + +kernel_modules: + - iscsi_tcp + +sysctl_options: + - { key: 'net.ipv4.conf.all.rp_filter', value: 0 } + - { key: 'net.ipv4.conf.default.rp_filter', value: 0 } + - { key: 'net.ipv4.ip_forward', value: 1 } diff --git a/rpc_deployment/vars/config_vars/container_config_elasticsearch.yml b/rpc_deployment/vars/config_vars/container_config_elasticsearch.yml new file mode 100644 index 0000000000..4ee09ba997 --- /dev/null +++ b/rpc_deployment/vars/config_vars/container_config_elasticsearch.yml @@ -0,0 +1,24 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +container_config_options: + - "lxc.mount.entry=/openstack/{{ container_name }}/var/lib/elasticsearch var/lib/elasticsearch none bind 0 0" + - "lxc.aa_profile=unconfined" + +required_inner_dirs: + - "/var/lib/elasticsearch" + +required_outer_dirs: + - "/openstack/{{ container_name }}/var/lib/elasticsearch" diff --git a/rpc_deployment/vars/config_vars/container_config_galera.yml b/rpc_deployment/vars/config_vars/container_config_galera.yml new file mode 100644 index 0000000000..511e833508 --- /dev/null +++ b/rpc_deployment/vars/config_vars/container_config_galera.yml @@ -0,0 +1,24 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +container_config_options: + - "lxc.mount.entry=/openstack/{{ container_name }} var/lib/mysql none bind 0 0" + - "lxc.aa_profile=lxc-openstack" + +required_inner_dirs: + - "/var/lib/mysql" + +required_outer_dirs: + - "/openstack/{{ container_name }}" diff --git a/rpc_deployment/vars/config_vars/container_config_logstash.yml b/rpc_deployment/vars/config_vars/container_config_logstash.yml new file mode 100644 index 0000000000..e7c5adcb52 --- /dev/null +++ b/rpc_deployment/vars/config_vars/container_config_logstash.yml @@ -0,0 +1,17 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +container_config_options: + - "lxc.aa_profile=unconfined" diff --git a/rpc_deployment/vars/config_vars/container_config_memcached.yml b/rpc_deployment/vars/config_vars/container_config_memcached.yml new file mode 100644 index 0000000000..33b349d962 --- /dev/null +++ b/rpc_deployment/vars/config_vars/container_config_memcached.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +memcached_listen: "{{ container_address }}" + +container_config_options: + - "lxc.aa_profile=lxc-openstack" diff --git a/rpc_deployment/vars/config_vars/container_config_neutron.yml b/rpc_deployment/vars/config_vars/container_config_neutron.yml new file mode 100644 index 0000000000..0e5e2174df --- /dev/null +++ b/rpc_deployment/vars/config_vars/container_config_neutron.yml @@ -0,0 +1,49 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Set the options that we want for the container, these are config options. +# The option is set as a YAML list which translates into "key = value" in config +container_config_options: + - "lxc.aa_profile=unconfined" + - "lxc.cgroup.devices.allow=a *:* rmw" + - "lxc.mount.entry=/lib/modules lib/modules none bind 0 0" + +required_inner_dirs: + - "/lib/modules" + +required_outer_dirs: + - "/lib/modules" + +kernel_modules: + - 8021q + - ip6table_filter + - ip6_tables + - ipt_REJECT + - iptable_mangle + - ipt_MASQUERADE + - iptable_nat + - nf_conntrack_ipv4 + - nf_defrag_ipv4 + - nf_nat_ipv4 + - nf_nat + - nf_conntrack + - iptable_filter + - ip_tables + - x_tables + +sysctl_options: + - { key: 'net.ipv4.conf.all.rp_filter', value: 0 } + - { key: 'net.ipv4.conf.default.rp_filter', value: 0 } + - { key: 'net.ipv4.ip_forward', value: 1 } diff --git a/rpc_deployment/vars/config_vars/container_config_nova_compute.yml b/rpc_deployment/vars/config_vars/container_config_nova_compute.yml new file mode 100644 index 0000000000..0ff3f8606e --- /dev/null +++ b/rpc_deployment/vars/config_vars/container_config_nova_compute.yml @@ -0,0 +1,57 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Set the options that we want for the container, these are config options. +# The option is set as a YAML list which translates into "key = value" in config +container_config_options: + - "lxc.tty=4" + - "lxc.pts=1024" + - "lxc.aa_profile=unconfined" + - "lxc.mount.auto=cgroup" + - "lxc.cgroup.devices.allow=a *:* rmw" + - "lxc.mount.entry=/lib/modules lib/modules none bind 0 0" + - "lxc.mount.entry=/openstack/instances var/lib/nova/instances none defaults,bind 0.0" + +required_inner_dirs: + - "/var/lib/nova/instances" + - "/lib/modules" + +required_outer_dirs: + - "/openstack/instances" + - "/lib/modules" + +kernel_modules: + - nbd + - vhost_net + - ip6table_filter + - ip6_tables + - ipt_REJECT + - iptable_mangle + - ipt_MASQUERADE + - iptable_nat + - iptable_filter + - ip_tables + - nf_conntrack_ipv4 + - nf_defrag_ipv4 + - nf_nat_ipv4 + - nf_nat + - nf_conntrack + - x_tables + - iscsi_tcp + +sysctl_options: + - { key: 'net.ipv4.conf.all.rp_filter', value: 0 } + - { key: 'net.ipv4.conf.default.rp_filter', value: 0 } + - { key: 'net.ipv4.ip_forward', value: 1 } diff --git a/rpc_deployment/vars/config_vars/container_config_rsyslog.yml b/rpc_deployment/vars/config_vars/container_config_rsyslog.yml new file mode 100644 index 0000000000..c1c770d3fe --- /dev/null +++ b/rpc_deployment/vars/config_vars/container_config_rsyslog.yml @@ -0,0 +1,24 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +container_config_options: + - "lxc.mount.entry=/openstack/log openstack/log none bind 0 0" + - "lxc.aa_profile=lxc-openstack" + +required_inner_dirs: + - "/openstack/log" + +required_outer_dirs: + - "/openstack/log" diff --git a/rpc_deployment/vars/config_vars/container_interfaces.yml b/rpc_deployment/vars/config_vars/container_interfaces.yml new file mode 100644 index 0000000000..3ceaefa1e4 --- /dev/null +++ b/rpc_deployment/vars/config_vars/container_interfaces.yml @@ -0,0 +1,31 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +container_interface: | + # The loopback network interface + auto lo + iface lo inet loopback + + auto eth0 + iface eth0 inet dhcp + + source /etc/network/interfaces.d/*.cfg + + +management_interface: | + auto {{ hostvars[item]['container_network']['container_interface'] }} + iface {{ hostvars[item]['container_network']['container_interface'] }} inet static + address {{ hostvars[item]['container_address'] }} + netmask {{ hostvars[item]['container_network']['container_netmask']|default(hostvars[item]['container_netmask']) }} diff --git a/rpc_deployment/vars/config_vars/glance_config.yml b/rpc_deployment/vars/config_vars/glance_config.yml new file mode 100644 index 0000000000..b0c4891e8e --- /dev/null +++ b/rpc_deployment/vars/config_vars/glance_config.yml @@ -0,0 +1,249 @@ +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +glance_api_conf: + DEFAULT: + verbose: "{{ verbose }}" + debug: "{{ debug }}" + log_file: /var/log/glance/glance-api.log + use_syslog: False + sql_connection: "mysql://{{ container_mysql_user }}:{{ container_mysql_password }}@{{ mysql_address }}/{{ container_database }}?charset=utf8" + default_store: "{{ default_store }}" + bind_host: 0.0.0.0 + bind_port: 9292 + backlog: 4096 + workers: 1 + registry_host: "{{ registry_host }}" + registry_port: 9191 + registry_client_protocol: http + cinder_catalog_info: "volume:cinder:internalURL" + + ##### RPC MESSAGING OPTIONS ##### + notification_driver: messaging + rpc_backend: "{{ rpc_backend }}" + + rabbit_hosts: "{{ rabbit_hosts }}" + + rabbit_port: "{{ rabbit_port }}" + rabbit_use_ssl: "{{ rabbit_use_ssl }}" + rabbit_userid: "{{ rabbit_userid }}" + rabbit_password: "{{ rabbit_password }}" + rabbit_virtual_host: "{{ rabbit_virtual_host }}" + rabbit_notification_exchange: glance + rabbit_notification_topic: notifications + rabbit_durable_queues: False + + ##### STORE OPTIONS ##### + swift_store_auth_version: 2 + swift_store_auth_address: "{{ swift_store_auth_address }}" + swift_store_user: "{{ swift_store_user }}" + swift_store_key: "{{ swift_store_key }}" + swift_store_region: "{{ swift_store_region }}" + swift_store_container: "{{ swift_store_container }}" + swift_store_create_container_on_put: True + swift_store_large_object_size: 5120 + swift_store_large_object_chunk_size: 200 + swift_store_retry_get_count: 5 + swift_enable_snet: "{{ glance_swift_enable_snet }}" + + filesystem_store_datadir: /var/lib/glance/images/ + delayed_delete: False + scrub_time: 43200 + scrubber_datadir: /var/lib/glance/scrubber/ + image_cache_dir: /var/lib/glance/cache/ + + keystone_authtoken: + signing_dir: /var/lib/glance/cache/api + identity_uri: "{{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}" + auth_uri: "{{ auth_identity_uri }}" + admin_tenant_name: "{{ service_admin_tenant_name }}" + admin_user: "{{ service_admin_username }}" + admin_password: "{{ service_admin_password }}" + + memcached_servers: "{{ internal_vip_address }}:{{ memcached_port }}" + token_cache_time: 300 + revocation_cache_time: 60 + + # if your memcached server is shared, use these settings to avoid cache poisoning + memcache_security_strategy: ENCRYPT + memcache_secret_key: "{{ memcached_secret_key }}" + + # if your keystone deployment uses PKI, and you value security over performance: + check_revocations_for_cached: "{{ hostvars[groups['keystone_all'][0]]['keystone_use_pki'] }}" + + paste_deploy: + flavor: "{{ flavor }}" + + +glance_cache_conf: + DEFAULT: + verbose: "{{ verbose }}" + debug: "{{ debug }}" + admin_password: "{{ glance_service_password }}" + admin_user: glance + admin_tenant_name: service + use_syslog: False + image_cache_dir: /var/lib/glance/cache/ + image_cache_stall_time: 86400 + image_cache_max_size: 10737418240 + registry_host: "{{ registry_host }}" + registry_port: 9191 + auth_url: "{{ auth_admin_uri }}" + filesystem_store_datadir: /var/lib/glance/images/ + + +glance_registry_conf: + DEFAULT: + verbose: "{{ verbose }}" + debug: "{{ debug }}" + log_file: /var/log/glance/glance-registry.log + use_syslog: False + sql_connection: "mysql://{{ container_mysql_user }}:{{ container_mysql_password }}@{{ mysql_address }}/{{ container_database }}?charset=utf8" + bind_host: 0.0.0.0 + bind_port: 9191 + backlog: 4096 + api_limit_max: 1000 + limit_param_default: 25 + + keystone_authtoken: + signing_dir: /var/lib/glance/cache/registry/ + identity_uri: "{{ auth_protocol }}://{{ auth_host }}:{{ auth_port }}" + auth_uri: "{{ auth_identity_uri }}" + admin_tenant_name: "{{ service_admin_tenant_name }}" + admin_user: "{{ service_admin_username }}" + admin_password: "{{ service_admin_password }}" + + memcached_servers: "{{ internal_vip_address }}:{{ memcached_port }}" + token_cache_time: 300 + revocation_cache_time: 60 + + # if your memcached server is shared, use these settings to avoid cache poisoning + memcache_security_strategy: ENCRYPT + memcache_secret_key: "{{ memcached_secret_key }}" + + # if your keystone deployment uses PKI, and you value security over performance: + check_revocations_for_cached: "{{ hostvars[groups['keystone_all'][0]]['keystone_use_pki'] }}" + + paste_deploy: + flavor: keystone + +glance_scrubber_conf: + DEFAULT: + verbose: "{{ verbose }}" + debug: "{{ debug }}" + # Log to this file. Make sure you do not set the same log file for both the API + # and registry servers! + # + # If `log_file` is omitted and `use_syslog` is false, then log messages are + # sent to stdout as a fallback. + log_file: /var/log/glance/scrubber.log + + # Send logs to syslog (/dev/log) instead of to file specified by `log_file` + #use_syslog: False + + # Should we run our own loop or rely on cron/scheduler to run us + daemon: False + + # Loop time between checking for new items to schedule for delete + wakeup_time: 300 + + # Directory that the scrubber will use to remind itself of what to delete + # Make sure this is also set in glance-api.conf + scrubber_datadir: /var/lib/glance/scrubber + + # Only one server in your deployment should be designated the cleanup host + cleanup_scrubber: False + + # pending_delete items older than this time are candidates for cleanup + cleanup_scrubber_time: 86400 + + # Address to find the registry server for cleanups + registry_host: 0.0.0.0 + + # Port the registry server is listening on + registry_port: 9191 + + +glance_api_paste_ini: + # Use this pipeline for no auth or image caching - DEFAULT + pipeline:glance-api: + pipeline: "versionnegotiation unauthenticated-context rootapp" + # Use this pipeline for image caching and no auth + pipeline:glance-api-caching: + pipeline: "versionnegotiation unauthenticated-context cache rootapp" + # Use this pipeline for caching w/ management interface but no auth + pipeline:glance-api-cachemanagement: + pipeline: "versionnegotiation unauthenticated-context cache cachemanage rootapp" + # Use this pipeline for keystone auth + pipeline:glance-api-keystone: + pipeline: "versionnegotiation authtoken context rootapp" + # Use this pipeline for keystone auth with image caching + pipeline:glance-api-keystone+caching: + pipeline: "versionnegotiation authtoken context cache rootapp" + # Use this pipeline for keystone auth with caching and cache management + pipeline:glance-api-keystone+cachemanagement: + pipeline: "versionnegotiation authtoken context cache cachemanage rootapp" + # Use this pipeline for authZ only. This means that the registry will treat a + # user as authenticated without making requests to keystone to reauthenticate + # the user. + pipeline:glance-api-trusted-auth: + pipeline: "versionnegotiation context rootapp" + # Use this pipeline for authZ only. This means that the registry will treat a + # user as authenticated without making requests to keystone to reauthenticate + # the user and uses cache management + pipeline:glance-api-trusted-auth+cachemanagement: + pipeline: "versionnegotiation context cache cachemanage rootapp" + composite:rootapp: + paste.composite_factory: "glance.api:root_app_factory" + /: "apiversions" + /v1: "apiv1app" + /v2: "apiv2app" + app:apiversions: + paste.app_factory: "glance.api.versions:create_resource" + app:apiv1app: + paste.app_factory: "glance.api.v1.router:API.factory" + app:apiv2app: + paste.app_factory: "glance.api.v2.router:API.factory" + filter:versionnegotiation: + paste.filter_factory: "glance.api.middleware.version_negotiation:VersionNegotiationFilter.factory" + filter:cache: + paste.filter_factory: "glance.api.middleware.cache:CacheFilter.factory" + filter:cachemanage: + paste.filter_factory: "glance.api.middleware.cache_manage:CacheManageFilter.factory" + filter:context: + paste.filter_factory: "glance.api.middleware.context:ContextMiddleware.factory" + filter:unauthenticated-context: + paste.filter_factory: "glance.api.middleware.context:UnauthenticatedContextMiddleware.factory" + filter:authtoken: + paste.filter_factory: "keystonemiddleware.auth_token:filter_factory" + delay_auth_decision: true + filter:gzip: + paste.filter_factory: "glance.api.middleware.gzip:GzipMiddleware.factory" + +glance_registry_paste_ini: + pipeline:glance-registry: + pipeline: "unauthenticated-context registryapp" + pipeline:glance-registry-keystone: + pipeline: "authtoken context registryapp" + pipeline:glance-registry-trusted-auth: + pipeline: "context registryapp" + app:registryapp: + paste.app_factory: "glance.registry.api:API.factory" + filter:context: + paste.filter_factory: "glance.api.middleware.context:ContextMiddleware.factory" + filter:unauthenticated-context: + paste.filter_factory: "glance.api.middleware.context:UnauthenticatedContextMiddleware.factory" + filter:authtoken: + paste.filter_factory: "keystonemiddleware.auth_token:filter_factory" + diff --git a/rpc_deployment/vars/config_vars/haproxy_config.yml b/rpc_deployment/vars/config_vars/haproxy_config.yml new file mode 100644 index 0000000000..657886e5db --- /dev/null +++ b/rpc_deployment/vars/config_vars/haproxy_config.yml @@ -0,0 +1,122 @@ +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +haproxy_config: + - service: + hap_service_name: galera + hap_backend_nodes: "{{ [groups['galera'][0]] }}" # list expected + hap_backup_nodes: "{{ groups['galera'][1:] }}" + hap_port: 3306 + hap_balance_type: tcp + hap_backend_options: + - "mysql-check user haproxy" + - service: + hap_service_name: glance_api + hap_backend_nodes: "{{ groups['glance_api'] }}" + hap_port: 9292 + hap_balance_type: http + - service: + hap_service_name: glance_registry + hap_backend_nodes: "{{ groups['glance_registry'] }}" + hap_port: 9191 + hap_balance_type: http + - service: + hap_service_name: heat_api_cfn + hap_backend_nodes: "{{ groups['heat_api_cfn'] }}" + hap_port: 8000 + hap_balance_type: http + - service: + hap_service_name: heat_api_cloudwatch + hap_backend_nodes: "{{ groups['heat_api_cloudwatch'] }}" + hap_port: 8003 + hap_balance_type: http + - service: + hap_service_name: heat_api + hap_backend_nodes: "{{ groups['heat_api'] }}" + hap_port: 8004 + hap_balance_type: http + - service: + hap_service_name: keystone_admin + hap_backend_nodes: "{{ groups['keystone'] }}" + hap_port: 35357 + hap_balance_type: http + - service: + hap_service_name: keystone_service + hap_backend_nodes: "{{ groups['keystone'] }}" + hap_port: 5000 + hap_balance_type: http + - service: + hap_service_name: neutron_server + hap_backend_nodes: "{{ groups['neutron_server'] }}" + hap_port: 9696 + hap_balance_type: http + - service: + hap_service_name: nova_api_ec2 + hap_backend_nodes: "{{ groups['nova_api_ec2'] }}" + hap_port: 8773 + hap_balance_type: http + - service: + hap_service_name: nova_api_metadata + hap_backend_nodes: "{{ groups['nova_api_metadata'] }}" + hap_port: 8775 + hap_balance_type: http + - service: + hap_service_name: nova_api_os_compute + hap_backend_nodes: "{{ groups['nova_api_os_compute'] }}" + hap_port: 8774 + hap_balance_type: http + - service: + hap_service_name: nova_spice_console + hap_backend_nodes: "{{ groups['nova_spice_console'] }}" + hap_port: 6082 + hap_balance_type: http + - service: + hap_service_name: cinder_api + hap_backend_nodes: "{{ groups['cinder_api'] }}" + hap_port: 8776 + hap_balance_type: http + - service: + hap_service_name: horizon + hap_backend_nodes: "{{ groups['horizon'] }}" + hap_port: 80 + hap_balance_type: http + - service: + hap_service_name: horizon_ssl + hap_backend_nodes: "{{ groups['horizon'] }}" + hap_port: 443 + hap_balance_type: tcp + - service: + hap_service_name: memcached + hap_backend_nodes: "{{ [groups['memcached'][0]] }}" # list expected + hap_backup_nodes: "{{ groups['memcached'][1:] }}" + hap_port: 11211 + hap_balance_type: tcp + hap_whitelist_hosts: true + - service: + hap_service_name: elasticsearch + hap_backend_nodes: "{{ [groups['elasticsearch'][0]] }}" + hap_port: 9200 + hap_balance_type: tcp + - service: + hap_service_name: kibana + hap_backend_nodes: "{{ [groups['kibana'][0]] }}" + hap_port: 8080 + hap_backend_port: 80 + hap_balance_type: http + - service: + hap_service_name: kibana_ssl + hap_backend_nodes: "{{ [groups['kibana'][0]] }}" + hap_port: 8443 + hap_balance_type: tcp + diff --git a/rpc_deployment/vars/config_vars/keystone_config.yml b/rpc_deployment/vars/config_vars/keystone_config.yml new file mode 100644 index 0000000000..d0a4fb060c --- /dev/null +++ b/rpc_deployment/vars/config_vars/keystone_config.yml @@ -0,0 +1,189 @@ +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +keystone_conf: + DEFAULT: + verbose: "{{ verbose }}" + debug: "{{ debug }}" + admin_token: "{{ auth_admin_token }}" + bind_host: "0.0.0.0" + # The port number which the public service listens on + public_port: "{{ auth_public_port }}" + # The port number which the public admin listens on + admin_port: "{{ auth_port }}" + public_endpoint: "{{ auth_protocol }}://{{ internal_vip_address }}:{{ auth_public_port }}/" + admin_endpoint: "{{ auth_protocol }}://{{ internal_vip_address }}:{{ auth_port }}/" + log_file: "keystone.log" + log_dir: /var/log/keystone + rabbit_hosts: "{{ rabbit_hosts }}" + rabbit_userid: "{{ rabbit_userid }}" + rabbit_password: "{{ rabbit_password }}" + rpc_backend: "{{ rpc_backend }}" + memcache: + servers: "{{ internal_vip_address }}:{{ memcached_port }}" + max_compare_and_set_retry: 16 + cache: + backend: "dogpile.cache.memcached" + backend_argument: "url:{{ internal_vip_address }}:{{ memcached_port }}" + config_prefix: "cache.keystone" + distributed_lock: True + expiration_time: 5400 + enabled: "true" + revoke: + expiration_buffer: 1800 + caching: "true" + auth: + methods: "{{ auth_methods }}" + database: + connection: "mysql://{{ container_mysql_user }}:{{ container_mysql_password }}@{{ mysql_address }}/{{ container_database }}?charset=utf8" + idle_timeout: 200 + min_pool_size: 5 + max_pool_size: 10 + pool_timeout: 200 + identity: + driver: "{{ keystone_identity_driver|default('keystone.identity.backends.sql.Identity') }}" + assignment: + driver: keystone.assignment.backends.sql.Assignment + caching: true + ldap: + url: "ldap://{{ keystone_ldap_server|default('localhost') }}" + user: "{{ keystone_ldap_user_bind|default('root') }}" + password: "{{ keystone_ldap_user_bind_password|default('secrete') }}" + suffix: "{{ keystone_ldap_suffix|default('cn=example,cn=com') }}" + use_dumb_member: "{{ keystone_ldap_use_dumb_member|default('false') }}" + dumb_member: "{{ keystone_ldap_dumb_member|default('cn=dumb,dc=nonexistent') }}" + allow_subtree_delete: "{{ keystone_ldap_allow_subtree_delete|default('false') }}" + query_scope: "{{ keystone_ldap_query_scope|default('one') }}" + page_size: "{{ keystone_ldap_page_size|default('0') }}" + debug_level: "{{ keystone_ldap_debug_level|default('') }}" + chase_referrals: "{{ keystone_ldap_chase_referrals|default('True') }}" + user_tree_dn: "{{ keystone_ldap_user_tree_dn|default('') }}" + user_filter: "{{ keystone_ldap_user_filter|default('') }}" + user_objectclass: "{{ keystone_ldap_user_objectclass|default('inetOrgPerson') }}" + user_id_attribute: "{{ keystone_ldap_user_id_attribute|default('cn') }}" + user_name_attribute: "{{ keystone_ldap_user_name_attribute|default('sn') }}" + user_mail_attribute: "{{ keystone_ldap_user_mail_attribute|default('email') }}" + user_pass_attribute: "{{ keystone_ldap_user_pass_attribute|default('userPassword')}}" + user_enabled_attribute: "{{ keystone_ldap_user_enabled_attribute|default('enabled') }}" + user_enabled_mask: "{{ keystone_ldap_user_enabled_mask|default('0') }}" + user_enabled_default: "{{ keystone_ldap_user_enabled_default|default('True') }}" + user_attribute_ignore: "{{ keystone_ldap_user_attribute_ignore|default('default_project_id,tenants') }}" + user_default_project_id_attribute: "{{ keystone_ldap_user_default_project_id_attribute|default('') }}" + user_allow_create: "{{ keystone_ldap_user_allow_create|default('true') }}" + user_allow_update: "{{ keystone_ldap_user_allow_update|default('true') }}" + user_allow_delete: "{{ keystone_ldap_user_allow_delete|default('true') }}" + user_enabled_emulation: "{{ keystone_ldap_user_enabled_emulation|default('false') }}" + user_enabled_emulation_dn: "{{ keystone_ldap_user_enabled_emulation_dn|default('') }}" + user_additional_attribute_mapping: "{{ keystone_ldap_user_additional_attribute_mapping|default('') }}" + group_tree_dn: "{{ keystone_ldap_|default('') }}" + group_filter: "{{ keystone_ldap_group_filter|default('') }}" + group_objectclass: "{{ keystone_ldap_group_objectclass|default('groupOfNames') }}" + group_id_attribute: "{{ keystone_ldap_group_id_attribute|default('cn') }}" + group_name_attribute: "{{ keystone_ldap_group_name_attribute|default('ou') }}" + group_member_attribute: "{{ keystone_ldap_group_member_attribute|default('member') }}" + group_desc_attribute: "{{ keystone_ldap_group_desc_attribute|default('description') }}" + group_attribute_ignore: "{{ keystone_ldap_group_attribute_ignore|default('') }}" + group_allow_create: "{{ keystone_ldap_group_allow_create|default('true') }}" + group_allow_update: "{{ keystone_ldap_group_allow_update|default('true') }}" + group_allow_delete: "{{ keystone_ldap_group_allow_delete|default('true') }}" + group_additional_attribute_mapping: "{{ keystone_ldap_group_additional_attribute_mapping|default('') }}" + tls_cacertfile: "{{ keystone_ldap_tls_cacertfile|default('') }}" + tls_cacertdir: "{{ keystone_ldap_tls_cacertdir|default('') }}" + use_tls: "{{ keystone_ldap_use_tls|default('false') }}" + tls_req_cert: "{{ keystone_ldap_tls_req_cert|default('demand') }}" + token: + enforce_token_bind: "permissive" + revocation_cache_time: 3600 + expiration: 43200 + caching: "true" + cache_time: "5400" + provider: "{{ token_provider }}" + +keystone_paste_ini: + filter:debug: + paste.filter_factory: "keystone.common.wsgi:Debug.factory" + filter:build_auth_context: + paste.filter_factory: "keystone.middleware:AuthContextMiddleware.factory" + filter:token_auth: + paste.filter_factory: "keystone.middleware:TokenAuthMiddleware.factory" + filter:admin_token_auth: + paste.filter_factory: "keystone.middleware:AdminTokenAuthMiddleware.factory" + filter:xml_body: + paste.filter_factory: "keystone.middleware:XmlBodyMiddleware.factory" + filter:xml_body_v2: + paste.filter_factory: "keystone.middleware:XmlBodyMiddlewareV2.factory" + filter:xml_body_v3: + paste.filter_factory: "keystone.middleware:XmlBodyMiddlewareV3.factory" + filter:json_body: + paste.filter_factory: "keystone.middleware:JsonBodyMiddleware.factory" + filter:user_crud_extension: + paste.filter_factory: "keystone.contrib.user_crud:CrudExtension.factory" + filter:crud_extension: + paste.filter_factory: "keystone.contrib.admin_crud:CrudExtension.factory" + filter:ec2_extension: + paste.filter_factory: "keystone.contrib.ec2:Ec2Extension.factory" + filter:ec2_extension_v3: + paste.filter_factory: "keystone.contrib.ec2:Ec2ExtensionV3.factory" + filter:federation_extension: + paste.filter_factory: "keystone.contrib.federation.routers:FederationExtension.factory" + filter:oauth1_extension: + paste.filter_factory: "keystone.contrib.oauth1.routers:OAuth1Extension.factory" + filter:s3_extension: + paste.filter_factory: "keystone.contrib.s3:S3Extension.factory" + filter:endpoint_filter_extension: + paste.filter_factory: "keystone.contrib.endpoint_filter.routers:EndpointFilterExtension.factory" + filter:simple_cert_extension: + paste.filter_factory: "keystone.contrib.simple_cert:SimpleCertExtension.factory" + filter:revoke_extension: + paste.filter_factory: "keystone.contrib.revoke.routers:RevokeExtension.factory" + filter:url_normalize: + paste.filter_factory: "keystone.middleware:NormalizingFilter.factory" + filter:sizelimit: + paste.filter_factory: "keystone.middleware:RequestBodySizeLimiter.factory" + filter:stats_monitoring: + paste.filter_factory: "keystone.contrib.stats:StatsMiddleware.factory" + filter:stats_reporting: + paste.filter_factory: "keystone.contrib.stats:StatsExtension.factory" + filter:access_log: + paste.filter_factory: "keystone.contrib.access:AccessLogMiddleware.factory" + app:public_service: + paste.app_factory: "keystone.service:public_app_factory" + app:service_v3: + paste.app_factory: "keystone.service:v3_app_factory" + app:admin_service: + paste.app_factory: "keystone.service:admin_app_factory" + pipeline:public_api: + pipeline: "sizelimit url_normalize build_auth_context token_auth admin_token_auth xml_body_v2 json_body ec2_extension user_crud_extension public_service" + pipeline:admin_api: + pipeline: "sizelimit url_normalize build_auth_context token_auth admin_token_auth xml_body_v2 json_body ec2_extension s3_extension crud_extension admin_service" + pipeline:api_v3: + pipeline: "sizelimit url_normalize build_auth_context token_auth admin_token_auth xml_body_v3 json_body ec2_extension_v3 s3_extension simple_cert_extension service_v3" + app:public_version_service: + paste.app_factory: "keystone.service:public_version_app_factory" + app:admin_version_service: + paste.app_factory: "keystone.service:admin_version_app_factory" + pipeline:public_version_api: + pipeline: "sizelimit url_normalize xml_body public_version_service" + pipeline:admin_version_api: + pipeline: "sizelimit url_normalize xml_body admin_version_service" + composite:main: + use: "egg:Paste#urlmap" + /v2.0: "public_api" + /v3: "api_v3" + /: "public_version_api" + composite:admin: + use: "egg:Paste#urlmap" + /v2.0: "admin_api" + /v3: "api_v3" + /: "admin_version_api" diff --git a/rpc_deployment/vars/config_vars/utility_config.yml b/rpc_deployment/vars/config_vars/utility_config.yml new file mode 100644 index 0000000000..a3c3d6f820 --- /dev/null +++ b/rpc_deployment/vars/config_vars/utility_config.yml @@ -0,0 +1,42 @@ +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +openstack_service_types: + - cinder_all + - cinder_api + - cinder_scheduler + - cinder_volume + - glance_all + - glance_api + - glance_registry + - heat_all + - heat_api_cfn + - heat_api_cloudwatch + - heat_api + - heat_engine + - horizon + - keystone_all + - keystone + - neutron_all + - neutron_dhcp_agent + - neutron_linuxbridge_agent + - neutron_metadata_agent + - neutron_server + - nova_all + - nova_api_ec2 + - nova_api_metadata + - nova_api_os_compute + - nova_compute + - nova_conductor + - nova_scheduler diff --git a/rpc_deployment/vars/openstack_service_vars/cinder_api.yml b/rpc_deployment/vars/openstack_service_vars/cinder_api.yml new file mode 100644 index 0000000000..af9fd5de38 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/cinder_api.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the Cinder-API group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +## Service Type and Data +program_name: cinder-api diff --git a/rpc_deployment/vars/openstack_service_vars/cinder_api_endpoint.yml b/rpc_deployment/vars/openstack_service_vars/cinder_api_endpoint.yml new file mode 100644 index 0000000000..adce9a064e --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/cinder_api_endpoint.yml @@ -0,0 +1,22 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +service_type: volume +service_description: "Cinder volume service" +service_password: "{{ cinder_service_password }}" + +service_publicurl: "http://{{ external_vip_address }}:{{ cinder_service_port }}/v1/%(tenant_id)s" +service_adminurl: "http://{{ internal_vip_address }}:{{ cinder_service_port }}/v1/%(tenant_id)s" +service_internalurl: "http://{{ internal_vip_address }}:{{ cinder_service_port }}/v1/%(tenant_id)s" diff --git a/rpc_deployment/vars/openstack_service_vars/cinder_apiv2_endpoint.yml b/rpc_deployment/vars/openstack_service_vars/cinder_apiv2_endpoint.yml new file mode 100644 index 0000000000..13bb36742a --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/cinder_apiv2_endpoint.yml @@ -0,0 +1,29 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the Cinder-API group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +## Service Type and Data +service_type: volumev2 +service_description: "Cinder Volume Service V2" +service_password: "{{ cinder_v2_service_password }}" + +service_publicurl: "http://{{ external_vip_address }}:{{ cinder_service_port }}/v2/%(tenant_id)s" +service_adminurl: "http://{{ internal_vip_address }}:{{ cinder_service_port }}/v2/%(tenant_id)s" +service_internalurl: "http://{{ internal_vip_address }}:{{ cinder_service_port }}/v2/%(tenant_id)s" + +service_name: cinderv2 +program_name: cinder-api diff --git a/rpc_deployment/vars/openstack_service_vars/cinder_scheduler.yml b/rpc_deployment/vars/openstack_service_vars/cinder_scheduler.yml new file mode 100644 index 0000000000..04f83c358f --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/cinder_scheduler.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the Cinder-API group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: cinder-scheduler diff --git a/rpc_deployment/vars/openstack_service_vars/cinder_volume.yml b/rpc_deployment/vars/openstack_service_vars/cinder_volume.yml new file mode 100644 index 0000000000..cc95278b18 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/cinder_volume.yml @@ -0,0 +1,23 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the Cinder-API group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: cinder-volume +apt_common_packages: + - tgt + - parted + - qemu-utils diff --git a/rpc_deployment/vars/openstack_service_vars/glance_api.yml b/rpc_deployment/vars/openstack_service_vars/glance_api.yml new file mode 100644 index 0000000000..0325e4f4e0 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/glance_api.yml @@ -0,0 +1,18 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the Glance-API group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. +program_name: glance-api diff --git a/rpc_deployment/vars/openstack_service_vars/glance_api_endpoint.yml b/rpc_deployment/vars/openstack_service_vars/glance_api_endpoint.yml new file mode 100644 index 0000000000..07852c27bc --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/glance_api_endpoint.yml @@ -0,0 +1,23 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +## Service Type and Data +service_type: image +service_description: "Glance Image Service" +service_password: "{{ glance_service_password }}" + +service_publicurl: "http://{{ external_vip_address }}:9292" +service_adminurl: "http://{{ internal_vip_address }}:9292" +service_internalurl: "http://{{ internal_vip_address }}:9292" diff --git a/rpc_deployment/vars/openstack_service_vars/glance_registry.yml b/rpc_deployment/vars/openstack_service_vars/glance_registry.yml new file mode 100644 index 0000000000..b4c0082441 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/glance_registry.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the Glance-registry group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: glance-registry diff --git a/rpc_deployment/vars/openstack_service_vars/heat_api.yml b/rpc_deployment/vars/openstack_service_vars/heat_api.yml new file mode 100644 index 0000000000..f1780f62b1 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/heat_api.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the Heat-API group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: heat-api diff --git a/rpc_deployment/vars/openstack_service_vars/heat_api_cfn.yml b/rpc_deployment/vars/openstack_service_vars/heat_api_cfn.yml new file mode 100644 index 0000000000..b05fcc38b7 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/heat_api_cfn.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the Heat-API group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: heat-api-cfn diff --git a/rpc_deployment/vars/openstack_service_vars/heat_api_cfn_endpoint.yml b/rpc_deployment/vars/openstack_service_vars/heat_api_cfn_endpoint.yml new file mode 100644 index 0000000000..760f96115a --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/heat_api_cfn_endpoint.yml @@ -0,0 +1,23 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +## Service Type and Data +service_type: cloudformation +service_description: "Heat CloudFormation Service" +service_password: "{{ heat_cfn_service_password }}" + +service_publicurl: "http://{{ external_vip_address }}:8000/v1" +service_adminurl: "http://{{ internal_vip_address }}:8000/v1" +service_internalurl: "http://{{ internal_vip_address }}:8000/v1" diff --git a/rpc_deployment/vars/openstack_service_vars/heat_api_cloudwatch.yml b/rpc_deployment/vars/openstack_service_vars/heat_api_cloudwatch.yml new file mode 100644 index 0000000000..e9eda630d7 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/heat_api_cloudwatch.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the Heat-API group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: heat-api-cloudwatch diff --git a/rpc_deployment/vars/openstack_service_vars/heat_api_endpoint.yml b/rpc_deployment/vars/openstack_service_vars/heat_api_endpoint.yml new file mode 100644 index 0000000000..5317026e25 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/heat_api_endpoint.yml @@ -0,0 +1,23 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +## Service Type and Data +service_type: orchestration +service_description: "Heat Orchestration Service" +service_password: "{{ heat_service_password }}" + +service_publicurl: "http://{{ external_vip_address }}:8004/v1/$(tenant_id)s" +service_adminurl: "http://{{ internal_vip_address }}:8004/v1/$(tenant_id)s" +service_internalurl: "http://{{ internal_vip_address }}:8004/v1/$(tenant_id)s" diff --git a/rpc_deployment/vars/openstack_service_vars/heat_engine.yml b/rpc_deployment/vars/openstack_service_vars/heat_engine.yml new file mode 100644 index 0000000000..70f1a668ed --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/heat_engine.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the Heat-API group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: heat-engine diff --git a/rpc_deployment/vars/openstack_service_vars/keystone.yml b/rpc_deployment/vars/openstack_service_vars/keystone.yml new file mode 100644 index 0000000000..8d4215030c --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/keystone.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the Keystone-API group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: apache2 diff --git a/rpc_deployment/vars/openstack_service_vars/keystone_endpoint.yml b/rpc_deployment/vars/openstack_service_vars/keystone_endpoint.yml new file mode 100644 index 0000000000..9716eec1a6 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/keystone_endpoint.yml @@ -0,0 +1,23 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +## Service Type and Data +service_type: identity +service_description: "Keystone Identity Service" +service_password: "{{ keystone_service_password }}" + +service_publicurl: "http://{{ external_vip_address }}:{{ service_port }}/v2.0" +service_adminurl: "http://{{ internal_vip_address }}:{{ admin_port }}/v2.0" +service_internalurl: "http://{{ internal_vip_address }}:{{ service_port }}/v2.0" diff --git a/rpc_deployment/vars/openstack_service_vars/neutron_agent.yml b/rpc_deployment/vars/openstack_service_vars/neutron_agent.yml new file mode 100644 index 0000000000..386987c451 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/neutron_agent.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova-api-ec2 group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +## Service Type and Data +program_name: neutron-agent diff --git a/rpc_deployment/vars/openstack_service_vars/neutron_dhcp_agent.yml b/rpc_deployment/vars/openstack_service_vars/neutron_dhcp_agent.yml new file mode 100644 index 0000000000..0d38ff4977 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/neutron_dhcp_agent.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova-api-ec2 group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: neutron-dhcp-agent +program_config_options: --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/dhcp_agent.ini diff --git a/rpc_deployment/vars/openstack_service_vars/neutron_l3_agent.yml b/rpc_deployment/vars/openstack_service_vars/neutron_l3_agent.yml new file mode 100644 index 0000000000..aa1a1cc601 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/neutron_l3_agent.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova-api-ec2 group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: neutron-l3-agent +program_config_options: --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/l3_agent.ini diff --git a/rpc_deployment/vars/openstack_service_vars/neutron_linuxbridge_agent.yml b/rpc_deployment/vars/openstack_service_vars/neutron_linuxbridge_agent.yml new file mode 100644 index 0000000000..4a8afbb9c7 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/neutron_linuxbridge_agent.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova-api-ec2 group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: neutron-linuxbridge-agent +program_config_options: --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2/ml2_conf.ini diff --git a/rpc_deployment/vars/openstack_service_vars/neutron_metadata_agent.yml b/rpc_deployment/vars/openstack_service_vars/neutron_metadata_agent.yml new file mode 100644 index 0000000000..2abfc4bbaf --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/neutron_metadata_agent.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova-api-ec2 group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: neutron-metadata-agent +program_config_options: --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/metadata_agent.ini diff --git a/rpc_deployment/vars/openstack_service_vars/neutron_metering_agent.yml b/rpc_deployment/vars/openstack_service_vars/neutron_metering_agent.yml new file mode 100644 index 0000000000..6a956840b5 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/neutron_metering_agent.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova-api-ec2 group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: neutron-metering-agent +program_config_options: --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/metering_agent.ini diff --git a/rpc_deployment/vars/openstack_service_vars/neutron_server.yml b/rpc_deployment/vars/openstack_service_vars/neutron_server.yml new file mode 100644 index 0000000000..2e72e6d507 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/neutron_server.yml @@ -0,0 +1,20 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova-api-ec2 group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: neutron-server +program_config_options: --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2/ml2_conf.ini diff --git a/rpc_deployment/vars/openstack_service_vars/neutron_server_endpoint.yml b/rpc_deployment/vars/openstack_service_vars/neutron_server_endpoint.yml new file mode 100644 index 0000000000..b6fa169c6c --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/neutron_server_endpoint.yml @@ -0,0 +1,23 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +## Service Type and Data +service_type: network +service_description: "OpenStack Networking" +service_password: "{{ neutron_service_password }}" + +service_publicurl: "http://{{ external_vip_address }}:9696" +service_adminurl: "http://{{ internal_vip_address }}:9696" +service_internalurl: "http://{{ internal_vip_address }}:9696" diff --git a/rpc_deployment/vars/openstack_service_vars/nova_api_ec2.yml b/rpc_deployment/vars/openstack_service_vars/nova_api_ec2.yml new file mode 100644 index 0000000000..85e2691cd8 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/nova_api_ec2.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova-api-ec2 group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: nova-api-ec2 diff --git a/rpc_deployment/vars/openstack_service_vars/nova_api_ec2_endpoint.yml b/rpc_deployment/vars/openstack_service_vars/nova_api_ec2_endpoint.yml new file mode 100644 index 0000000000..72558619eb --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/nova_api_ec2_endpoint.yml @@ -0,0 +1,24 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +## Service Type and Data +service_name: ec2 +service_type: ec2 +service_description: "EC2 Compatibility Layer" +service_password: "{{ nova_ec2_service_password }}" + +service_publicurl: "http://{{ external_vip_address }}:8773/services/Cloud" +service_adminurl: "http://{{ internal_vip_address }}:8773/services/Admin" +service_internalurl: "http://{{ internal_vip_address }}:8773/services/Cloud" diff --git a/rpc_deployment/vars/openstack_service_vars/nova_api_metadata.yml b/rpc_deployment/vars/openstack_service_vars/nova_api_metadata.yml new file mode 100644 index 0000000000..4e9bf10b84 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/nova_api_metadata.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova-api-metadata group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: nova-api-metadata diff --git a/rpc_deployment/vars/openstack_service_vars/nova_api_os_compute.yml b/rpc_deployment/vars/openstack_service_vars/nova_api_os_compute.yml new file mode 100644 index 0000000000..b2be7dc7a4 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/nova_api_os_compute.yml @@ -0,0 +1,16 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +program_name: nova-api-os-compute diff --git a/rpc_deployment/vars/openstack_service_vars/nova_api_os_compute_endpoint.yml b/rpc_deployment/vars/openstack_service_vars/nova_api_os_compute_endpoint.yml new file mode 100644 index 0000000000..1b9b267fb5 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/nova_api_os_compute_endpoint.yml @@ -0,0 +1,26 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova-api-os-compute group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +## Service Type and Data +service_type: compute +service_description: "Nova Compute Service" +service_password: "{{ nova_service_password }}" + +service_publicurl: "http://{{ external_vip_address }}:8774/v2/$(tenant_id)s" +service_adminurl: "http://{{ internal_vip_address }}:8774/v2/$(tenant_id)s" +service_internalurl: "http://{{ internal_vip_address }}:8774/v2/$(tenant_id)s" diff --git a/rpc_deployment/vars/openstack_service_vars/nova_api_os_computev3_endpoint.yml b/rpc_deployment/vars/openstack_service_vars/nova_api_os_computev3_endpoint.yml new file mode 100644 index 0000000000..07a53f03f5 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/nova_api_os_computev3_endpoint.yml @@ -0,0 +1,28 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova-api-os-compute group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +## V3 API services +service_name: novav3 +service_type: computev3 +service_description: "Nova Compute Service V3" +service_password: "{{ nova_v3_service_password }}" + +## V3 API Endpoints +service_publicurl: "http://{{ external_vip_address }}:8774/v3" +service_adminurl: "http://{{ internal_vip_address }}:8774/v3" +service_internalurl: "http://{{ internal_vip_address }}:8774/v3" diff --git a/rpc_deployment/vars/openstack_service_vars/nova_api_s3_endpoint.yml b/rpc_deployment/vars/openstack_service_vars/nova_api_s3_endpoint.yml new file mode 100644 index 0000000000..67127f2902 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/nova_api_s3_endpoint.yml @@ -0,0 +1,27 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +## S3 API services +service_name: s3 +service_type: s3 +service_description: "S3 Compatibility Layer" +service_password: "{{ nova_s3_service_password }}" + +## S3 API Endpoints +service_publicurl: "http://{{ external_vip_address }}:3333" +service_adminurl: "http://{{ internal_vip_address }}:3333" +service_internalurl: "http://{{ internal_vip_address }}:3333" + +program_name: nova-api-ec2 diff --git a/rpc_deployment/vars/openstack_service_vars/nova_compute.yml b/rpc_deployment/vars/openstack_service_vars/nova_compute.yml new file mode 100644 index 0000000000..d4f3b1e6be --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/nova_compute.yml @@ -0,0 +1,27 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova-scheduler group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: nova-compute + +apt_libvirt_packages: + - libvirt-bin + - python-libvirt + - qemu + - qemu-utils + - genisoimage + - sysfsutils diff --git a/rpc_deployment/vars/openstack_service_vars/nova_conductor.yml b/rpc_deployment/vars/openstack_service_vars/nova_conductor.yml new file mode 100644 index 0000000000..19d2520df3 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/nova_conductor.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova-conductor group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: nova-conductor diff --git a/rpc_deployment/vars/openstack_service_vars/nova_console_auth.yml b/rpc_deployment/vars/openstack_service_vars/nova_console_auth.yml new file mode 100644 index 0000000000..97c144d763 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/nova_console_auth.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova-conductor group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: nova-consoleauth diff --git a/rpc_deployment/vars/openstack_service_vars/nova_scheduler.yml b/rpc_deployment/vars/openstack_service_vars/nova_scheduler.yml new file mode 100644 index 0000000000..6075a63e4f --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/nova_scheduler.yml @@ -0,0 +1,19 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova-scheduler group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: nova-scheduler diff --git a/rpc_deployment/vars/openstack_service_vars/nova_spice_console.yml b/rpc_deployment/vars/openstack_service_vars/nova_spice_console.yml new file mode 100644 index 0000000000..574e56532f --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/nova_spice_console.yml @@ -0,0 +1,22 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# The variables file used by the playbooks in the nova-conductor group. +# These don't have to be explicitly imported by vars_files: they are autopopulated. + +program_name: nova-spicehtml5proxy + +container_packages: + - spice-html5 diff --git a/rpc_deployment/vars/openstack_service_vars/nova_spice_console_endpoint.yml b/rpc_deployment/vars/openstack_service_vars/nova_spice_console_endpoint.yml new file mode 100644 index 0000000000..f5a41cb790 --- /dev/null +++ b/rpc_deployment/vars/openstack_service_vars/nova_spice_console_endpoint.yml @@ -0,0 +1,18 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +nova_html5proxy_base_url: "http://{{ external_vip_address }}:6082/spice_auto.html" +nova_console_keymap: en-us +nova_console_agent_enabled: True diff --git a/scripts/cloudserver-aio.sh b/scripts/cloudserver-aio.sh new file mode 100755 index 0000000000..6e1410013e --- /dev/null +++ b/scripts/cloudserver-aio.sh @@ -0,0 +1,179 @@ +#!/usr/bin/env bash +# Copyright 2014, Rackspace US, Inc. +# +# 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. +# +# (c) 2014, Kevin Carter + + +# Assumptions: +# This assumes that the lab environment will be setup using +# a rackspace cloud server build on the rackspace public cloud. +# The lab will attempt to create the required Volume Groups that +# the lab will want to use as it creates your containers, if +# /dev/xvde is not available all containers will be created using +# the local file system. If /dev/xvde is available it WILL BE +# NUKED and partitioned for the environment. Once the partitioning is +# done the lab will create all of the required containers as well as +# anything else that may be needed prior to running the installation. +# If using LVM you should have NO LESS than 100 GB of consumable space +# on your the /dev/xvde device. If you have less than 100G the installation +# will fail. + +# THIS IS NOT FOR PRODUCTION USE, NOR WILL IT EVER BE. This is a simple +# lab setup tool that will allow you to quickly build an ALL IN ONE +# environment for development purposes. + + +set -e -u -v -x + +LAB_NAME=${LAB_NAME:-ansible-lxc-rpc-inventory} +LAB_LV_DEVICE=${LAB_LV_DEVICE:-/dev/xvde} +LAB_BRIDGE_INTERFACE=${LAB_BRIDGE_INTERFACE:-br-mgmt} +LAB_MAIN_INTERFACE=${LAB_MAIN_INTERFACE:-eth0} + +function key_create(){ + ssh-keygen -t rsa -f /root/.ssh/id_rsa -N '' +} + +# Make the system key used for bootstrapping self +pushd /root/.ssh/ +if [ ! -f "id_rsa" ];then + key_create +fi + +if [ ! -f "id_rsa.pub" ];then + rm "id_rsa" + key_create +fi + +KEYENTRY=$(cat id_rsa.pub) +if [ ! "$(grep \"$KEYENTRY\" authorized_keys)" ];then + echo "$KEYENTRY" | tee -a authorized_keys +fi +popd + +# Install base System Packages +apt-get update && apt-get install -y python-dev \ + build-essential \ + curl \ + git-core \ + ipython \ + tmux \ + vim +apt-get -y upgrade + +# If Ephemeral disk is detected carve it up as LVM +if [ -e "${LAB_LV_DEVICE}" ];then + SPACE=$(parted -s /dev/xvde p | awk '/Disk/ {print $3}' | grep -o '[0-9]\+') + ENOUGH_SPACE=$(python -c "o=\"$SPACE\".split('.')[0]; print(int(o) > 100)") + if [ "$ENOUGH_SPACE" == True ];then + apt-get update && apt-get install -y lvm2 + if [ ! "$(echo C | parted ${LAB_LV_DEVICE} p | grep gpt)" ];then + parted -s ${LAB_LV_DEVICE} mktable gpt + parted -s ${LAB_LV_DEVICE} mkpart lvm 0% 90% + parted -s ${LAB_LV_DEVICE} mkpart lvm 90% 100% + fi + if [ ! "$(pvs | grep '/dev/xvde1')" ];then + pvcreate ${LAB_LV_DEVICE}1 + vgcreate lxc ${LAB_LV_DEVICE}1 + fi + if [ ! "$(pvs | grep '/dev/xvde2')" ];then + pvcreate ${LAB_LV_DEVICE}2 + vgcreate cinder-volumes ${LAB_LV_DEVICE}2 + fi + else + CINDER="/opt/cinder.img" + if [ ! "$(losetup -a | grep /opt/cinder.img)" ];then + LOOP=$(losetup -f) + dd if=/dev/zero of=${CINDER} bs=1 count=0 seek=1000G + losetup ${LOOP} ${CINDER} + pvcreate ${LOOP} + vgcreate cinder-volumes ${LOOP} + pvscan + fi + fi +fi + +# Get modern pip +curl https://bootstrap.pypa.io/get-pip.py | python + +# Install ansible +pip install ansible==1.6.6 + +# Get our playbooks +if [ ! -d /opt/ansible-lxc-rpc ]; then + git clone https://github.com/rcbops/ansible-lxc-rpc /opt/ansible-lxc-rpc +fi + +# Get the eth0 IP address +MAINADDR="$(ip route show dev ${LAB_MAIN_INTERFACE} | awk '{print $7}' | tail -n 1)" + +# Get the eth2 CIDR +VIPADDR="$(ip route show dev ${LAB_BRIDGE_INTERFACE} | awk '{print $7}' | tail -n 1)" + +cp -R /opt/ansible-lxc-rpc/etc/rpc_deploy /etc/rpc_deploy + +cat > /etc/rpc_deploy/rpc_user_config.yml <[^_]*)_(?P[^_]*)' + '_(?P[^_]*)') + packages = [] + for line in lines: + match = line_re.match(line) + if match: + packages.append((match.groupdict()['name'], + match.groupdict()['version'])) + + return packages + + def repo_list(self): + """Get list of repos known to aptly""" + return self.run("-raw repo list").splitlines() + + def repo_create(self, name): + """Create an aptly repo""" + self.run("repo create %(name)s" % {'name': name}) + + def repo_get_packages(self, name): + """ get list of name, version tuples from a repo""" + lines = self.run('repo show -with-packages %(name)s' + % {'name': name}) + + return self.parse_aptly_package_list(lines) + + def package_query(self, name, version): + """ return aptly query string for a package name & version """ + return '"%(name)s (=%(version)s)"' % {'name': name, + 'version': version} + + def repo_import_package(self, mirror, repo, package_name, + package_version): + """Pull a package from a mirror into a repo""" + self.run('repo import %(mirror)s %(repo)s %(query)s' + % {'mirror': mirror, + 'repo': repo, + 'query': self.package_query( + package_name, package_version) + }, shell=True) + + def repo_import_packages(self, mirror, repo, packages, batch_size=200): + while packages: + batch = packages[0:batch_size] + if not batch: + break + packages = packages[batch_size:] + query_string = " ".join([self.package_query(n, v) for + n, v in batch]) + self.run('repo import %(mirror)s %(repo)s %(query)s' + % {'mirror': mirror, + 'repo': repo, + 'query': query_string}, + shell=True) + + def repo_publish(self, name): + """Create on disk distribution metata for an aptly internal repo""" + self.run('publish repo -distribution %(name)s %(name)s' + % {'name': name}) + + LOGGER.info("Published repo %(name)s" % {'name': name}) + + def snapshot_list(self): + """ List reposnapshots known to aptly""" + self.run("-raw snapshot list").splitlines() + + def snapshot_create(self, name): + """ Create an empty aptly snapshot""" + self.run("snapshot create %(name)s empty") + + +class Config(object): + """ Class representing YAML config files""" + def __init__(self, path): + self.path = path + self.read(path) + + def read(self, path=None): + """Read yaml from self.path into self.data""" + if path is None: + path = self.path + self.data = yaml.load(open(path).read()) + + def write(self, path=None): + """Write yaml version of self.data to self.path""" + if path is None: + path = self.path + with open(path, 'w') as f: + f.write(yaml.dump(self.data, default_flow_style=False)) + + def __getitem__(self, key): + """pass subscript requests to self.data""" + return self.data.get(key) + + def __setitem__(self, key, value): + """pass subscript requests to self.data""" + self.data[key] = value + + +class AptlyOrechestrator(object): + """ Class which uses the Aptly wrapper to achieve RPC aims + This is mostly creating repos from a supplied config file. + """ + + def __init__(self, args): + self.config_path = args.config_path + self.args = args + self.aptly = Aptly() + self.config = Config(args.config_path) + + def available_versions_for_package(self, name): + """Find available versions for a package""" + versions = [] + for mirror, packages in self.mirrors: + for package_name, version in packages: + if package_name == name: + versions.append(version) + return versions + + def ensure_mirrors(self, required_mirrors): + """ Check mirrors list, create any that are missing""" + current_mirrors = self.aptly.mirror_list() + self.mirrors = [] + for required_mirror in required_mirrors: + # Create mirror if necessary + mirror_name = required_mirror['name'] + if mirror_name not in current_mirrors: + self.aptly.mirror_create(**required_mirror) + + # Update mirror if created or already existed + self.aptly.mirror_update(mirror_name) + + # Store list of available packages for each mirror + self.mirrors.append( + (mirror_name, self.aptly.mirror_get_packages(mirror_name))) + + def packages_from_config(self): + """get list of required packages from config + :returns: list of name,value tuples. + """ + return [(name, str(version)) for name, version + in self.config['packages'].iteritems()] + + def ensure_packages(self, dist_name): + """Add all packages form config file to repo dist_name""" + + # convert name: version dict to [(name,version),..] + required_packages = self.packages_from_config() + repo_packages = self.aptly.repo_get_packages(dist_name) + + # packages that aren't in this repo already so need to be added + missing_packages = [p for p in required_packages + if p not in repo_packages] + + LOGGER.debug("missing packages: %s" % missing_packages) + + # list of packages we dont find in any upstreams + unavailable_packages = [] + + # map of mirror to package list for found packages + package_map = {} + for package in missing_packages: + for mirror, packages in self.mirrors: + if mirror not in package_map: + package_map[mirror] = [] + found = False + if package in packages: + package_map[mirror].append(package) + found = True + LOGGER.debug("Found %(pname)s in %(mname)s" + % {'pname': package, 'mname': mirror}) + break + if not found: + unavailable_packages.append(package) + LOGGER.debug("Failed to find package %(name)s %(version)s" + % {'name': package[0], + 'version': package[1]}) + + # Batch import all the packages that are known to be available + for mirror, packages in package_map.iteritems(): + LOGGER.info("importing packages from %s" % mirror) + self.aptly.repo_import_packages(mirror, dist_name, packages) + + # Return list of packages that were not found + return unavailable_packages + + def create_dist_from_package_list(self): + """High level function for creating a dist from + a supplied config file""" + dist_name = self.args.dist_name + + if dist_name in self.aptly.repo_list(): + raise ValueError("dist name must be unique, %s already exists" + % dist_name) + LOGGER.info("Creating repo %(name)s" % {'name': dist_name}) + self.ensure_mirrors(self.config['upstream_repos']) + self.aptly.repo_create(dist_name) + unavailable_packages = self.ensure_packages(dist_name) + + if unavailable_packages: + LOGGER.warning("The following packages are not available") + for name, version in unavailable_packages: + available_versions_str = ",".join( + self.available_versions_for_package(name)) + LOGGER.warning("Not Found: %(name)s version: %(version)s. " + "Availble versions: %(avs)s" + % {'name': name, + 'version': version, + 'avs': available_versions_str}) + + self.aptly.repo_publish(dist_name) + + def add_package_to_config(self): + """ Add a package to the supplied config file""" + self.config['packages'][self.args.name] = self.args.version + self.config.write() + + def delete_package_from_config(self): + """ Remove a package from the supplied config file""" + del self.config['packages'][self.args.name] + self.config.write() + + def list_upstream_packages(self): + self.ensure_mirrors(self.config['upstream_repos']) + for mirror, packages in self.mirrors: + for package_name, package_version in packages: + print "%(mirror_name)s,%(package_name)s,%(package_version)s"\ + % {'mirror_name': mirror, + 'package_name': package_name, + 'package_version': package_version} + + def list_available_updates(self): + self.ensure_mirrors(self.config['upstream_repos']) + + # needed in order to use apt_pkg.version_compare + apt_pkg.init() + + # Store newest version available for each package with updates + package_updates = {} + + for package_name, package_version in self.packages_from_config(): + updates = [v for v in self.available_versions_for_package( + package_name) if apt_pkg.version_compare( + package_version, v) < 0] + updates = sorted(set(updates), + cmp=apt_pkg.version_compare) + if updates: + package_updates[package_name] = updates[-1] + LOGGER.info("Package %(name)s Config Version: %(current)s" + " Updates: %(updates)s" + % {'name': package_name, + 'current': package_version, + 'updates': updates}) + + # write new config file with updated versions, if requested + if package_updates and 'new_config_path' in self.args: + for package, version in package_updates.iteritems(): + self.config['packages'][package] = version + self.config.write(self.args.new_config_path) + LOGGER.info("updated config written to %s" + % self.args.new_config_path) + + +def main(args): + parser = argparse.ArgumentParser() + + # arguments that are relevant to all subcommands + parser.add_argument('config_path') + parser.add_argument('-v', '--verbose', action='store_true', + help="more logging") + + # Add subparsers for subcommands + subparsers = parser.add_subparsers() + + # dfc = distribution from config + parser_dfc = subparsers.add_parser('dist_from_config') + parser_dfc.add_argument('dist_name', help="must be unique") + parser_dfc.set_defaults(func="dfc") + + # subcommand to add packages to config + parser_add_package = subparsers.add_parser('add_package_to_config') + parser_add_package.add_argument('name') + parser_add_package.add_argument('version') + parser_add_package.set_defaults(func="add_package") + + # subcommand to remove packages from config + parser_del_package = subparsers.add_parser('delete_package_from_config') + parser_del_package.add_argument('name') + parser_del_package.set_defaults(func="del_package") + + # List all packages available in configured upstreams + parser_list_upstream_pkgs = subparsers.add_parser('list_upstream_pkgs') + parser_list_upstream_pkgs.set_defaults(func='list_upstream') + + # List all packages in the package list that have updates available + parser_list_upstream_pkgs = subparsers.add_parser('list_pkg_updates') + parser_list_upstream_pkgs.set_defaults(func='list_updates') + + # Generate new config file with updated package versions + parser_generate_updated_config = subparsers.add_parser( + 'generate_updated_config', + help="Generate new config file with package versions " + "updated to latest available") + parser_generate_updated_config.add_argument( + 'new_config_path', + help="New config with updated package verions will be generated" + " and written to this path") + parser_generate_updated_config.set_defaults(func='list_updates') + + args = parser.parse_args(args=args[1:]) + + if args.verbose: + LOGGER.setLevel(logging.DEBUG) + + ao = AptlyOrechestrator(args) + # Each subparser sets the func arg, call the appropriate function + {'dfc': ao.create_dist_from_package_list, + 'add_package': ao.add_package_to_config, + 'del_package': ao.delete_package_from_config, + 'list_upstream': ao.list_upstream_packages, + 'list_updates': ao.list_available_updates}[args.func]() + +if __name__ == "__main__": + main(sys.argv) diff --git a/scripts/elsa_repo_config.yml b/scripts/elsa_repo_config.yml new file mode 100644 index 0000000000..7f50850d2c --- /dev/null +++ b/scripts/elsa_repo_config.yml @@ -0,0 +1,8814 @@ +--- +# Copyright 2014, Rackspace US, Inc. +# +# 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. + + # Aptly mirrors will be created for the upstreams listed here + # these will be searched for the packages listed in the packages section + # These repos will be searched in order (top first) + upstream_repos: + + - name: rpccdn + url: "http://dc0e2a2ef0676c3453b1-31bb9324d3aeab0d08fa434012c1e64d.r5.cf1.rackcdn.com/" + dist: LA + component: main + architecture: amd64 + key_url: "http://dc0e2a2ef0676c3453b1-31bb9324d3aeab0d08fa434012c1e64d.r5.cf1.rackcdn.com/repo.gpg" + + - name: maria + url: "http://mirrors.coreix.net/mariadb/repo/10.1/ubuntu" + dist: trusty + component: main + architecture: amd64 + key_id: "0xcbcb082a1bb943db" + + - name: rabbit + url: "http://www.rabbitmq.com/debian/" + dist: testing + component: main + architecture: amd64 + key_url: "http://www.rabbitmq.com/rabbitmq-signing-key-public.asc" + + - name: openmanage + url: "http://linux.dell.com/repo/community/deb/latest/" + architecture: amd64 + key_id: "1285491434D8786F" + + - name: cloud_monitoring_agent + url: "http://stable.packages.cloudmonitoring.rackspace.com/ubuntu-14.04-x86_64" + dist: cloudmonitoring + component: main + architecture: amd64 + key_url: "https://monitoring.api.rackspacecloud.com/pki/agent/linux.asc" + + - name: ubuntu_trusty_security_main + url: "http://archive.ubuntu.com/ubuntu" + dist: trusty-security + component: main + architecture: amd64 + key_id: "437D05B5 C0B21F32" + + - name: ubuntu_trusty_updates_main + url: "http://archive.ubuntu.com/ubuntu" + dist: trusty-updates + component: main + architecture: amd64 + key_id: "C0B21F32" + + - name: ubuntu_trusty_main + url: "http://archive.ubuntu.com/ubuntu" + dist: trusty + component: main + architecture: amd64 + key_id: C0B21F32 + + + # Package name: version + packages: + "rackspace-monitoring-agent": "1.0.2-5" + "mariadb-server": "10.1.0+maria-1~trusty" + "apache2": "2.4.7-1ubuntu4.1" + "srvadmin-all": "7.1.0-3" + "rabbitmq-server": "3.3.5-1" + + "libgck-1-dev": "3.10.1-1" + "libgirepository1.0-dev": "1.40.0-1" + "libxml2-dbg": "2.9.1+dfsg1-3ubuntu4" + "libppl-doc": "1:1.1-1ubuntu1" + "corosync-dev": "2.3.3-1ubuntu1" + "libgles1-mesa-lts-quantal": "3:5" + "libpython2.7-minimal": "2.7.6-8" + "libtiff-tools": "4.0.3-7" + "libreoffice-l10n-ka": "1:4.2.3~rc3-0ubuntu1" + "xserver-xorg-video-tdfx-lts-raring": "3:5" + "language-pack-gnome-hy": "1:14.04+20140410" + "libgucharmap-2-90-dev": "1:3.10.1-0ubuntu2" + "rhythmbox-plugins": "3.0.2-0ubuntu1" + "language-pack-br-base": "1:14.04+20140410" + "python-oslo.vmware": "0.2-0ubuntu1" + "ttf-bengali-fonts": "1:0.5.14ubuntu1" + "libnspr4": "2:4.10.2-1ubuntu1" + "libqscintilla-perl": "4:4.13.0-0ubuntu1" + "sa-compile": "3.4.0-1ubuntu1" + "apturl-common": "0.5.2ubuntu4" + "libtxc-dxtn-s2tc0": "0~git20131104-1.1" + "libkimproxy4": "4:4.13.0-0ubuntu1" + "libmnl-dev": "1.0.3-3ubuntu1" + "qtdeclarative5-privatewidgets-plugin": "5.2.1-3ubuntu15" + "language-pack-mt-base": "1:14.04+20140410" + "libjaxp1.3-java": "1.3.05-2ubuntu3" + "libestr0": "0.1.9-0ubuntu2" + "libgstreamer0.10-0-dbg": "0.10.36-1.2ubuntu3" + "libkde3support4": "4:4.13.0-0ubuntu1" + "libtelepathy-farstream-dev": "0.6.1-0ubuntu1" + "libzeitgeist-dev": "0.3.18-1ubuntu2" + "telepathy-indicator": "0.3.1+14.04.20140411-0ubuntu1" + "python-werkzeug": "0.9.4+dfsg-1.1ubuntu1" + "krb5-multidev": "1.12+dfsg-2ubuntu4" + "lib32gfortran-4.8-dev": "4.8.2-19ubuntu1" + "libopencryptoki-dev": "2.3.1+dfsg-3ubuntu5" + "libsunpinyin-dev": "2.0.3+git20130507-1ubuntu1" + "texinfo": "5.2.0.dfsg.1-2" + "gnome-settings-daemon-dev": "3.8.6.1-0ubuntu11" + "libx32ncursesw5-dev": "5.9+20140118-1ubuntu1" + "ntp": "1:4.2.6.p5+dfsg-3ubuntu2" + "tzdata": "2014e-0ubuntu0.14.04" + "libedit-dev": "3.1-20130712-2" + "libpam-smbpass": "2:4.1.6+dfsg-1ubuntu2" + "python-twisted-core": "13.2.0-1ubuntu1" + "grub-efi-amd64-signed": "1.34+2.02~beta2-9" + "mysql-client-5.5": "5.5.35+dfsg-1ubuntu1" + "python-bsddb3": "6.0.1-1build1" + "etckeeper": "1.9ubuntu2" + "language-pack-hu": "1:14.04+20140410" + "libdb5.3-java-jni": "5.3.28-3ubuntu3" + "libreadline5": "5.2+dfsg-2" + "poppler-dbg": "0.24.5-2ubuntu4" + "libgdk-pixbuf2.0-dev": "2.30.7-0ubuntu1" + "language-pack-gnome-ast": "1:14.04+20140410" + "python-netaddr": "0.7.10-1build1" + "file-dbg": "1:5.14-2ubuntu3" + "gir1.2-gck-1": "3.10.1-1" + "gir1.2-gdata-0.0": "0.14.1-1" + "language-pack-tg-base": "1:14.04+20140410" + "libdmx-dev": "1:1.1.3-1" + "python3-pyqt5.qtpositioning-dbg": "5.2.1+dfsg-1ubuntu1" + "xserver-xorg-video-modesetting-lts-saucy-dbg": "3:5" + "hunspell-de-at": "20120607-1" + "python-keystone": "1:2014.1-0ubuntu1" + "lib32atomic1": "4.8.2-19ubuntu1" + "libplist++-dev": "1.10-1" + "libxcb-dri2-0": "1.10-2ubuntu1" + "qtsvg5-dbg": "5.2.1-1" + "syslinux-themes-ubuntu": "8" + "automake1.4": "1:1.4-p6-13.1" + "signond-doc": "8.56+14.04.20140307-0ubuntu2" + "texlive-math-extra": "2013.20140215-2" + "x11proto-xf86bigfont-dev": "1.2.0-3" + "libglib2.0-cil-dev": "2.12.10-5" + "libcaca0": "0.99.beta18-1ubuntu5" + "telepathy-mission-control-5": "1:5.16.1-1ubuntu3" + "zip": "3.0-8" + "mdbtools-doc": "0.7.1-1ubuntu1" + "gcj-native-helper": "2:1.7-51" + "libfolks-dbg": "0.9.5-1ubuntu5" + "libsphinxbase1": "0.8-0ubuntu10" + "linux-signed-generic-lts-raring-eol-upgrade": "3.13.0.24.28" + "libproc-waitstat-perl": "1.00-4" + "checkbox-gui": "0.17.6-0ubuntu6" + "indicator-application": "12.10.1+14.04.20140407-0ubuntu1" + "telepathy-idle": "0.2.0-1" + "libmono-system-web-extensions4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libaio1": "0.3.109-4" + "libevent-openssl-2.0-5": "2.0.21-stable-1ubuntu1" + "libqt5versitorganizer5": "5.0~git20140203~e0c5eebe-0ubuntu2" + "squid3": "3.3.8-1ubuntu6" + "libchewing3": "0.3.5-4build1" + "libfreetype6": "2.5.2-1ubuntu2.2" + "linux-tools-generic": "3.13.0.24.28" + "language-pack-tl-base": "1:14.04+20140410" + "libqdox-java": "1.12-1build1" + "plainbox-secure-policy": "0.5.3-2" + "xorg-dev": "1:7.7+1ubuntu8" + "autofs": "5.0.7-3ubuntu3" + "libhdb9-heimdal": "1.6~git20131207+dfsg-1ubuntu1" + "language-pack-gnome-pt": "1:14.04+20140410" + "language-pack-shs": "1:14.04+20140410" + "libcpan-meta-check-perl": "0.007-1" + "python-maas-provisioningserver": "1.5+bzr2252-0ubuntu1" + "libbonoboui2-0": "2.24.5-0ubuntu3" + "language-pack-fa": "1:14.04+20140410" + "libfop-java": "1:1.1.dfsg-2ubuntu1" + "appmenu-qt": "0.2.7+14.04.20140305-0ubuntu1" + "libident": "0.22-3build4" + "pulseaudio-dbg": "1:4.0-0ubuntu11" + "language-pack-gnome-lg": "1:14.04+20140410" + "libxml-simple-perl": "2.20-1" + "xserver-xorg-video-trident": "1:1.3.6-0ubuntu5" + "libsm-doc": "2:1.2.1-2" + "libunity-control-center-dev": "14.04.3+14.04.20140410-0ubuntu1" + "quagga": "0.99.22.4-3ubuntu1" + "fop": "1:1.1.dfsg-2ubuntu1" + "libdbusmenu-qt-doc": "0.9.3+14.04.20140314-0ubuntu1" + "gir1.2-gst-plugins-base-0.10": "0.10.36-1.1ubuntu2" + "fonts-tlwg-sawasdee": "1:0.5.1-3" + "erlang-tools": "1:16.b.3-dfsg-1ubuntu2" + "indicator-sound": "12.10.2+14.04.20140401-0ubuntu1" + "python-egenix-mxqueue": "3.2.7-1build1" + "fonts-thai-tlwg": "1:0.5.1-3" + "apt-utils": "1.0.1ubuntu2.1" + "libxcb-damage0-dev": "1.10-2ubuntu1" + "pulseaudio-module-gconf": "1:4.0-0ubuntu11" + "xserver-xorg-video-nouveau-lts-raring": "3:5" + "python-genshi": "0.7-3" + "resolvconf": "1.69ubuntu1" + "sound-theme-freedesktop": "0.8-1" + "indicator-bluetooth": "0.0.6+14.04.20140207-0ubuntu2" + "libfltk1.1-dbg": "1.1.10-17" + "powermgmt-base": "1.31build1" + "glance-api": "1:2014.1-0ubuntu1" + "libgssdp-doc": "0.14.7-1ubuntu1" + "libdevel-lexalias-perl": "0.05-1build1" + "libspeex1": "1.2~rc1.1-1ubuntu1" + "language-pack-az-base": "1:14.04+20140410" + "libieee1284-3": "0.2.11-12" + "language-pack-gnome-sl-base": "1:14.04+20140410" + "libreoffice-l10n-pt": "1:4.2.3~rc3-0ubuntu1" + "libgd-dbg": "2.1.0-3" + "sensible-utils": "0.0.9" + "initramfs-tools-bin": "0.103ubuntu4.2" + "language-selector-common": "0.129.2" + "pyqt5-doc": "5.2.1+dfsg-1ubuntu1" + "python-oops-amqp": "0.0.7-0ubuntu2" + "libtext-iconv-perl": "1.7-5build2" + "language-pack-gnome-ka-base": "1:14.04+20140410" + "language-pack-km-base": "1:14.04+20140410" + "libmono-system-reactive-core2.2-cil": "3.2.8+dfsg-4ubuntu1" + "python-lazr.restfulclient": "0.13.3-1build1" + "libcairo-script-interpreter2": "1.13.0~20140204-0ubuntu1" + "libitm1-ppc64el-cross": "4.8.2-16ubuntu4cross0.4" + "python3-pexpect": "3.1-1" + "lib32atomic1-dbg": "4.8.2-19ubuntu1" + "libcogl15-dbg": "1.16.2-1" + "mesa-vdpau-drivers-dbg": "10.1.0-4ubuntu5" + "tdb-tools": "1.2.12-1" + "liblwp-mediatypes-perl": "6.02-1" + "update-motd": "3.5-0ubuntu1" + "libpangoxft-1.0-0": "1.36.3-1ubuntu1" + "libwayland-dev-lts-saucy": "3:5" + "python3.4-dbg": "3.4.0-2ubuntu1" + "cpp-4.8": "4.8.2-19ubuntu1" + "libgc1c2": "1:7.2d-5ubuntu2" + "python-mysqldb": "1.2.3-2ubuntu1" + "libxml-commons-resolver1.1-java-doc": "1.2-7build1" + "nagios3-doc": "3.5.1-1ubuntu1" + "libgvpr2": "2.36.0-0ubuntu3" + "ntfs-3g-dev": "1:2013.1.13AR.1-2ubuntu2" + "gedit-common": "3.10.4-0ubuntu4" + "libhud-client2-doc": "13.10.1+14.04.20140402-0ubuntu1" + "libmono-posix4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libqt4-declarative-particles": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "nagios-nrpe-plugin": "2.15-0ubuntu1" + "openbsd-inetd": "0.20091229-2ubuntu3" + "cloud-image-utils": "0.27-0ubuntu9" + "fonts-manchufont": "2.007.svn0068-4" + "libstdc++-4.8-doc": "4.8.2-19ubuntu1" + "ncurses-doc": "5.9+20140118-1ubuntu1" + "python-egenix-mxuid-doc": "3.2.7-1build1" + "mail-stack-delivery": "1:2.2.9-1ubuntu2" + "libavahi-ui0": "0.6.31-4ubuntu1" + "libboost-chrono1.54.0": "1.54.0-4ubuntu3" + "libqtsql4-perl": "4:4.13.0-0ubuntu1" + "transmission-gtk": "2.82-1.1ubuntu3" + "language-pack-ve-base": "1:14.04+20140410" + "libopus-doc": "1.1-0ubuntu1" + "gcj-jdk": "4:4.8.2-1ubuntu6" + "gir1.2-gtk-vnc-2.0": "0.5.3-0ubuntu2" + "libgbm-dev-lts-raring": "3:5" + "libmono-system-data-services-client4.0-cil": "3.2.8+dfsg-4ubuntu1" + "python-django": "1.6.1-2" + "python3-aptdaemon.pkcompat": "1.1.1-1ubuntu5" + "libcxsparse3.1.2": "1:4.2.1-3ubuntu1" + "libdbusmenu-qt5-dev": "0.9.3+14.04.20140314-0ubuntu1" + "language-pack-ta-base": "1:14.04+20140410" + "swift-account": "1.13.1-0ubuntu1" + "libx32asan0-dbg": "4.8.2-19ubuntu1" + "libreoffice-l10n-el": "1:4.2.3~rc3-0ubuntu1" + "libgconf2-4": "3.2.6-0ubuntu2" + "libgnome-menu-3-dev": "3.10.1-0ubuntu2" + "libpcap0.8-dbg": "1.5.3-2" + "libqt5quick5": "5.2.1-3ubuntu15" + "libsasl2-modules-db": "2.1.25.dfsg1-17build1" + "ps2eps": "1.68-1build1" + "xserver-xorg-video-qxl-dbg": "0.1.1-0ubuntu3" + "language-pack-gnome-tt-base": "1:14.04+20140410" + "automoc": "1.0~version-0.9.88-5build1" + "python3-pyqt4.phonon-dbg": "4.10.4+dfsg-1ubuntu1" + "xserver-xorg-video-radeon-lts-raring": "3:5" + "libxpm4": "1:3.5.10-1" + "nvidia-settings-310": "331.20-0ubuntu8" + "gnome-session-common": "3.9.90-0ubuntu12" + "efibootmgr": "0.5.4-7ubuntu1" + "libcolorhug1": "1.0.6-1" + "libldap-2.4-2-dbg": "2.4.31-1+nmu2ubuntu8" + "libxcb-screensaver0-dbg": "1.10-2ubuntu1" + "libqtassistantclient4": "4.6.3-6" + "automake1.9": "1.9.6+nogfdl-4ubuntu1" + "language-pack-gnome-th-base": "1:14.04+20140410" + "language-pack-gnome-tr": "1:14.04+20140410" + "python-billiard-doc": "3.3.0.15-1ubuntu1" + "bsd-mailx": "8.1.2-0.20131005cvs-1" + "evince-common": "3.10.3-0ubuntu10" + "hunspell-uz": "0.6-3.2ubuntu1" + "ppl-dev": "1:1.1-1ubuntu1" + "libargtable2-0": "12-1" + "libcanberra0-dbg": "0.30-0ubuntu3" + "libkrad-dev": "1.12+dfsg-2ubuntu4" + "language-pack-gnome-ast-base": "1:14.04+20140410" + "language-pack-gnome-is-base": "1:14.04+20140410" + "libmpfr-doc": "3.1.2-1" + "libreoffice-help-om": "1:4.2.3~rc3-0ubuntu1" + "libsignon-glib-doc": "1.10daily13.06.25-0ubuntu2" + "libppl13": "1:1.1-1ubuntu1" + "libptexenc-dev": "2013.20130729.30972-2build3" + "libsane-common": "1.0.23-3ubuntu3" + "libraw1394-11-dbg": "2.1.0-1ubuntu1" + "libxcb-res0": "1.10-2ubuntu1" + "python3-pymongo-ext": "2.6.3-1build1" + "gfxboot-dev": "4.5.1-3ubuntu1" + "indicator-session": "12.10.5+14.04.20140410-0ubuntu1" + "libgd-dev": "2.1.0-3" + "libnet-ssleay-perl": "1.58-1" + "libntdb1": "1.0-2ubuntu1" + "lib32gomp1-dbg": "4.8.2-19ubuntu1" + "libqt5scripttools5": "5.2.1+dfsg-1ubuntu1" + "php5-ldap": "5.5.9+dfsg-1ubuntu4" + "libqt5gui5": "5.2.1+dfsg-1ubuntu14" + "language-pack-mi-base": "1:14.04+20140410" + "language-pack-ne": "1:14.04+20140410" + "language-pack-uz": "1:14.04+20140410" + "libmono-microsoft-build4.0-cil": "3.2.8+dfsg-4ubuntu1" + "printer-driver-postscript-hp": "3.14.3-0ubuntu3" + "pptpd": "1.3.4+27+gddb30f8-1ubuntu1" + "slapd": "2.4.31-1+nmu2ubuntu8" + "clamav": "0.98.1+dfsg-4ubuntu1" + "libboost1.54-tools-dev": "1.54.0-4ubuntu3" + "libusbmuxd2": "1.0.8-2ubuntu1" + "libvirt-dev": "1.2.2-0ubuntu13" + "lilo": "1:24.0-2" + "python3-pil": "2.3.0-1ubuntu3" + "libtommath-docs": "0.42.0-1build1" + "myspell-ku": "0.20.0-2build1" + "libgmpxx4ldbl": "2:5.1.3+dfsg-1ubuntu1" + "libqt5xmlpatterns5-private-dev": "5.2.1-3" + "libstdc++6-4.8-dbg": "4.8.2-19ubuntu1" + "libpopt-dev": "1.16-8ubuntu1" + "usb-modeswitch": "2.1.1+repack0-1ubuntu1" + "language-pack-bn": "1:14.04+20140410" + "language-pack-hne": "1:12.04+20120417" + "libgraphite2-doc": "1.2.4-1ubuntu1" + "libmono-cil-dev": "3.2.8+dfsg-4ubuntu1" + "cpp-powerpc64le-linux-gnu": "4:4.8.2-1" + "xdg-user-dirs": "0.15-1ubuntu3" + "libgcrypt11-doc": "1.5.3-2ubuntu4" + "python3-checkbox-ng-doc": "0.3-2" + "bacula-sd-sqlite3-dbg": "5.2.6+dfsg-9.1ubuntu3" + "giflib-dbg": "4.1.6-11" + "schroot-dbg": "1.6.8-1ubuntu1" + "libgraphite2-dev": "1.2.4-1ubuntu1" + "libnl-3-200-dbg": "3.2.21-1" + "python-tdb-dbg": "1.2.12-1" + "language-pack-gnome-fr-base": "1:14.04+20140410" + "libreoffice-l10n-tr": "1:4.2.3~rc3-0ubuntu1" + "mahjongg": "1:3.10.2-0ubuntu1" + "gcc-4.8-multilib": "4.8.2-19ubuntu1" + "gir1.2-glib-2.0": "1.40.0-1ubuntu0.1" + "xserver-xorg-video-fbdev-lts-quantal": "3:5" + "bzrtools": "2.6.0-1" + "ivy-doc": "2.3.0-3" + "libtext-template-perl": "1.46-1" + "libxtst-dev": "2:1.2.2-1" + "tofrodos": "1.7.13+ds-1ubuntu1" + "hunspell-ko": "0.5.6-1" + "libpadwalker-perl": "1.98-1" + "tftp-hpa": "5.2-7ubuntu3" + "libasan0-powerpc-cross": "4.8.2-16ubuntu3cross0.11" + "passwd": "1:4.1.5.1-1ubuntu9" + "python3-pyatspi": "2.10.0+dfsg-1" + "gnome-screensaver": "3.6.1-0ubuntu13" + "libimobiledevice4-dbg": "1.1.5+git20140313.bafe6a9e-0ubuntu1" + "language-pack-gl": "1:14.04+20140410" + "python-subunit": "0.0.18-0ubuntu7" + "libnfnetlink0-dbg": "1.0.1-2" + "strongswan-tnc-pdp": "5.1.2-0ubuntu2" + "language-pack-ha-base": "1:14.04+20140410" + "python-ubuntu-sso-client": "13.10-0ubuntu6" + "libbison-dev": "2:3.0.2.dfsg-2" + "pulseaudio-module-raop": "1:4.0-0ubuntu11" + "lintian": "2.5.22ubuntu1" + "python3-urllib3": "1.7.1-1build1" + "libopenexr6": "1.6.1-7ubuntu1" + "libpackage-stash-xs-perl": "0.28-1" + "libxcb-ewmh2": "0.4.1-1ubuntu1" + "python-apt-doc": "0.9.3.5" + "imagemagick": "8:6.7.7.10-6ubuntu3" + "libunity-action-qt1": "1.1.0+14.04.20140304-0ubuntu1" + "libusb++-0.1-4c2": "2:0.1.12-23.3ubuntu1" + "xserver-xorg-video-nouveau-lts-saucy-dbg": "3:5" + "fuse": "2.9.2-4ubuntu4" + "srvadmin-smweb": "7.1.0-2" + "libreiser4-dev": "1.0.7-6.3fakesync2" + "libmodule-runtime-perl": "0.013-1" + "maas-cluster-controller": "1.5+bzr2252-0ubuntu1" + "hdparm": "9.43-1ubuntu3" + "libcairo2-dev": "1.13.0~20140204-0ubuntu1" + "liblockfile-dev": "1.09-6ubuntu1" + "livecd-rootfs": "2.208" + "nginx-core-dbg": "1.4.6-1ubuntu3" + "tcl8.6": "8.6.1-4ubuntu1" + "consolekit": "0.4.5-3.1ubuntu2" + "libcurl3-dbg": "7.35.0-1ubuntu2" + "libdb5.3-stl-dev": "5.3.28-3ubuntu3" + "libdevmapper1.02.1": "2:1.02.77-6ubuntu2" + "libfdt1": "1.4.0+dfsg-1" + "xserver-xorg-lts-saucy": "3:5" + "python-pytest": "2.5.1-1" + "hunspell-vi": "1:4.2.1-0ubuntu1" + "bacula-sd-sqlite3": "5.2.6+dfsg-9.1ubuntu3" + "python2.7-dbg": "2.7.6-8" + "libart2.0-cil-dev": "2.24.2-3" + "libgeronimo-jms-1.1-spec-java": "1.1-1.2ubuntu3" + "gcc-4.7": "4.7.3-12ubuntu1" + "python-waitress-doc": "0.8.8-1ubuntu3" + "libqt5xmlpatterns5": "5.2.1-3" + "libreoffice-gtk": "1:4.2.3~rc3-0ubuntu2" + "libtransitioner2-dev": "1.1.10+git20130802-1ubuntu2" + "libtext-unidecode-perl": "0.04-2" + "qttools5-dbg": "5.2.1-8build1" + "xserver-xorg-video-openchrome": "1:0.3.3-1build1" + "thunderbird-locale-nn-no": "1:24.4.0+build1-0ubuntu1" + "hostname": "3.15ubuntu1" + "libraw9": "0.15.4-1" + "libcgmanager-dev": "0.24-0ubuntu5" + "libtcmalloc-minimal4-dbg": "2.1-2ubuntu1" + "walinuxagent": "2.0.4-0ubuntu2" + "libheartbeat2": "1:3.0.5-3.2" + "pulseaudio-module-bluetooth": "1:4.0-0ubuntu11" + "language-pack-gnome-en": "1:14.04+20140707" + "libreoffice-help-nl": "1:4.2.3~rc3-0ubuntu1" + "libxml-perl": "0.08-2" + "powerwake-common": "2.18-0ubuntu2" + "libbrasero-media3-1": "3.10.0-0ubuntu1" + "hunspell-en-ca": "1:4.2.1-0ubuntu1" + "language-pack-ca-base": "1:14.04+20140410" + "gkbd-capplet": "3.6.0-0ubuntu2" + "htmldoc": "1.8.27-8ubuntu1" + "libwavpack-dev": "4.70.0-1" + "python-gnome2-dev": "2.28.1+dfsg-1ubuntu2" + "grub-pc-bin": "2.02~beta2-9" + "libqt4-xmlpatterns": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "libtelepathy-logger3-dbg": "0.8.0-3" + "libvirt-bin": "1.2.2-0ubuntu13" + "libdconf-dev": "0.20.0-1" + "libftdi1": "0.20-1ubuntu1" + "pkg-config-powerpc64le-linux-gnu": "4:4.8.2-1" + "xserver-xorg-video-vesa-lts-raring": "3:5" + "libsam-dev": "2.3.3-1ubuntu1" + "modemmanager-dbg": "1.0.0-2ubuntu1" + "libdatetime-format-strptime-perl": "1.5400-1" + "libreoffice-l10n-st": "1:4.2.3~rc3-0ubuntu1" + "bluez-cups": "4.101-0ubuntu13" + "libecap2-dev": "0.2.0-1ubuntu4" + "librarian0": "0.8.1-5ubuntu1" + "libio-html-perl": "1.00-1" + "libreoffice-help-dz": "1:4.2.3~rc3-0ubuntu1" + "compiz-dev": "1:0.9.11+14.04.20140409-0ubuntu1" + "libilmbase6": "1.0.1-6ubuntu1" + "libxslt1-dev": "1.1.28-2build1" + "account-plugin-flickr": "0.11+14.04.20140409.1-0ubuntu1" + "vim-addon-manager": "0.5.3" + "gsettings-desktop-schemas-dev": "3.10.1-0ubuntu1" + "libegl1-mesa-lts-raring": "3:5" + "xserver-xorg-video-tdfx": "1:1.4.5-1build1" + "language-pack-et-base": "1:14.04+20140410" + "libsp1c2": "1.3.4-1.2.1-47.3ubuntu1" + "linux-cloud-tools-generic": "3.13.0.24.28" + "util-linux": "2.20.1-5.1ubuntu20" + "xserver-xorg-dev": "2:1.15.1-0ubuntu2" + "libaugeas-ruby1.9.1": "0.5.0-2" + "policyrcd-script-zg2": "0.1-2" + "gpgv": "1.4.16-1ubuntu2.1" + "libelf-dev": "0.158-0ubuntu5" + "vim-gnome": "2:7.4.052-1ubuntu3" + "language-pack-gnome-ga": "1:14.04+20140410" + "fglrx-pxpress": "1:0.2.91.4" + "heimdal-multidev": "1.6~git20131207+dfsg-1ubuntu1" + "liboauth0": "1.0.1-1" + "strongswan-plugin-radattr": "5.1.2-0ubuntu2" + "xauth": "1:1.0.7-1ubuntu1" + "mime-construct": "1.11" + "firefox-locale-mr": "28.0+build2-0ubuntu2" + "libacl1": "2.2.52-1" + "libcloog-isl-dev": "0.18.2-1" + "libflac-dev": "1.3.0-2" + "gstreamer1.0-plugins-base-doc": "1.2.3-1" + "libx11-data": "2:1.6.2-1ubuntu2" + "nvidia-settings-310-updates": "331.20-0ubuntu8" + "python-pastescript": "1.7.5-3build1" + "bind9-host": "1:9.9.5.dfsg-3" + "libqt4-network": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "srvadmin-smcommon": "7.1.0-2" + "gparted": "0.18.0-1" + "libudf0": "0.83-4.1ubuntu1" + "docbook-xml": "4.5-7.2" + "gstreamer0.10-plugins-base-doc": "0.10.36-1.1ubuntu2" + "language-pack-it": "1:14.04+20140410" + "libcanberra-gtk-common-dev": "0.30-0ubuntu3" + "linux-headers-3.13.0-30": "3.13.0-30.55" + "libflac++-dev": "1.3.0-2" + "linux-headers-generic-lts-saucy": "3.13.0.24.28" + "libncursesw5-dev": "5.9+20140118-1ubuntu1" + "xserver-xorg-video-intel-lts-raring-dbg": "3:5" + "language-pack-ast": "1:14.04+20140410" + "language-pack-gnome-bg-base": "1:14.04+20140410" + "libconvert-asn1-perl": "0.26-1" + "libgck-1-doc": "3.10.1-1" + "libmono-system-web-abstractions4.0-cil": "3.2.8+dfsg-4ubuntu1" + "bash-completion": "1:2.1-4" + "nova-compute": "1:2014.1-0ubuntu1" + "python-setuptools-doc": "3.3-1ubuntu1" + "firefox-locale-hr": "28.0+build2-0ubuntu2" + "xserver-xorg-input-mouse-lts-raring": "3:5" + "xserver-xorg-video-vmware": "1:13.0.2-2ubuntu1" + "myspell-xh": "20070206-4ubuntu1" + "libgvnc-1.0-0": "0.5.3-0ubuntu2" + "libnetfilter-conntrack3-dbg": "1.0.4-1" + "libstdc++6-4.7-dev": "4.7.3-12ubuntu1" + "libxp-dev": "1:1.0.2-1ubuntu1" + "sshfs-dbg": "2.5-1ubuntu1" + "checkbox-ng-service": "0.3-2" + "findutils": "4.4.2-7" + "gir1.2-gupnpigd-1.0": "0.2.2-1" + "libcamd2.3.1": "1:4.2.1-3ubuntu1" + "linux-signed-image-generic-lts-trusty": "3.13.0.24.28" + "python-egenix-mxurl-doc": "3.2.7-1build1" + "libsmokeqtscript4-3": "4:4.13.0-0ubuntu1" + "linux-signed-generic-lts-raring": "3.13.0.24.28" + "ruby-nokogiri": "1.6.1+ds-1" + "language-pack-rw": "1:14.04+20140410" + "libgladeui-common": "3.16.1-0ubuntu2" + "unity-scope-zotero": "0.1+13.10.20130723-0ubuntu1" + "libpam-modules-bin": "1.1.8-1ubuntu2" + "libtext-charwidth-perl": "0.04-7build3" + "linux-cloud-tools-3.13.0-24": "3.13.0-24.46" + "syslinux-themes-ubuntu-quantal": "8" + "python-gobject-dev": "3.12.0-1" + "swift-object": "1.13.1-0ubuntu1" + "gir1.2-gnomedesktop-3.0": "3.8.4-0ubuntu3" + "libmemcached-dev": "1.0.8-1ubuntu2" + "libpci3": "1:3.2.1-1ubuntu5" + "libreoffice-l10n-en-za": "1:4.2.3~rc3-0ubuntu1" + "python-swiftclient": "1:2.0.3-0ubuntu1" + "vsftpd": "3.0.2-1ubuntu2" + "fonts-arphic-gkai00mp": "2.11-13" + "lib32itm1": "4.8.2-19ubuntu1" + "python3-chardet": "2.0.1-1" + "librsvg2-2": "2.40.2-1" + "libreoffice-l10n-bn": "1:4.2.3~rc3-0ubuntu1" + "m4-doc": "1.4.17-2ubuntu1" + "liblangtag-dev": "0.5.1-2" + "sqlite3-doc": "3.8.2-1ubuntu2" + "python-sqlalchemy-ext": "0.8.4-1build1" + "libbabl-dev": "0.1.10-1ubuntu2" + "liborbit-2-0": "1:2.14.19-0.3" + "x11-session-utils": "7.7+1" + "gimp-help-fr": "2.6.1-1" + "metacity-common": "1:2.34.13-0ubuntu4" + "python3-pkg-resources": "3.3-1ubuntu1" + "xapian-doc": "1.2.16-2ubuntu1" + "gir1.2-appindicator3-0.1": "12.10.1+13.10.20130920-0ubuntu4" + "debconf": "1.5.51ubuntu2" + "language-pack-gnome-gl-base": "1:14.04+20140410" + "libjs-jquery-metadata": "8-2" + "myspell-cs": "20040229-5.1" + "libstylebook-java": "1.0~b3~svn20061109-6" + "at-spi2-doc": "2.10.2.is.2.10.1-0ubuntu1" + "python-logilab-common": "0.61.0-1" + "ibus-unikey": "0.6.1-1build2" + "libglamor-dev-lts-saucy": "3:5" + "libusbredirhost1": "0.6-2ubuntu1" + "libart-2.0-2": "2.3.21-2" + "empathy-common": "3.8.6-0ubuntu9" + "libmono-system-security4.0-cil": "3.2.8+dfsg-4ubuntu1" + "tomcat7": "7.0.52-1" + "gob2": "2.0.20-1" + "libreoffice-help-fi": "1:4.2.3~rc3-0ubuntu1" + "bacula-director-sqlite3": "5.2.6+dfsg-9.1ubuntu3" + "modemmanager": "1.0.0-2ubuntu1" + "python3-pam-dbg": "0.4.2-13.1ubuntu3" + "yasm": "1.2.0-1ubuntu1" + "xserver-xorg-video-ati-lts-saucy-dbg": "3:5" + "libcommons-lang-java-doc": "2.6-3ubuntu2" + "python3-sqlalchemy": "0.8.4-1build1" + "x11proto-video-dev": "2.3.2-1" + "btrfs-tools": "3.12-1" + "libexiv2-dbg": "0.23-1ubuntu2" + "language-pack-ff": "1:14.04+20140410" + "language-pack-zh-hans": "1:14.04+20140410" + "myspell-sw": "1:4.2.1-0ubuntu1" + "firefox-locale-xh": "28.0+build2-0ubuntu2" + "libsystemd-login0": "204-5ubuntu20.3" + "libreoffice-l10n-vi": "1:4.2.3~rc3-0ubuntu1" + "python3-httplib2": "0.8-2build1" + "thunderbird-locale-pt-pt": "1:24.4.0+build1-0ubuntu1" + "fontforge": "20120731.b-5" + "grub-efi-ia32": "2.02~beta2-9" + "libdb5.3-sql-dev": "5.3.28-3ubuntu3" + "librsvg2-bin": "2.40.2-1" + "libsvn-perl": "1.8.8-1ubuntu3" + "linux-image-generic": "3.13.0.32.38" + "libdebian-dpkgcross-perl": "2.6.11ubuntu1" + "libxcb-xprint0": "1.10-2ubuntu1" + "python3-pyqt5.qtserialport": "5.2.1+dfsg-1ubuntu1" + "python-bson-ext": "2.6.3-1build1" + "valac-0.22-dbg": "0.22.1-0ubuntu1" + "pkgbinarymangler": "121" + "ruby-rspec-mocks": "2.14.3-1" + "gir1.2-packagekitglib-1.0": "0.8.12-1ubuntu5" + "libgrip0": "0.3.7+14.04.20140303-0ubuntu1" + "makedumpfile": "1.5.5-2ubuntu1" + "libdbus-c++-1-0": "0.9.0-6ubuntu1" + "libecal-1.2-16": "3.10.4-0ubuntu1" + "libgutenprintui2-1": "5.2.10~pre2-0ubuntu2" + "libxml-parser-perl": "2.41-1build3" + "libmono-system-data-linq2.0-cil": "3.2.8+dfsg-4ubuntu1" + "myspell-en-za": "1:4.2.1-0ubuntu1" + "x11proto-fixes-dev": "1:5.0-2ubuntu2" + "libgconf2-dev": "3.2.6-0ubuntu2" + "thunderbird-locale-ast": "1:24.4.0+build1-0ubuntu1" + "mm-common": "0.9.6-1" + "libudev1": "204-5ubuntu20.3" + "ubuntu-mono": "14.04+14.04.20140410-0ubuntu1" + "libdbi1": "0.9.0-1" + "libgo4": "4.8.2-19ubuntu1" + "libupsclient3": "2.7.1-1ubuntu1" + "libx32ncurses5": "5.9+20140118-1ubuntu1" + "ecj": "3.9.0-1" + "file": "1:5.14-2ubuntu3.1" + "tinycdb": "0.78" + "unity-lens-friends": "0.1.3+14.04.20140317-0ubuntu1" + "libparams-coerce-perl": "0.14-1" + "rhino-doc": "1.7R4-2" + "libao-dev": "1.1.0-2ubuntu2" + "libjbig0": "2.0-2ubuntu4" + "signon-plugin-ssotest": "8.56+14.04.20140307-0ubuntu2" + "dnsmasq-utils": "2.68-1" + "libmemcachedutil2": "1.0.8-1ubuntu2" + "xserver-xorg-video-all-lts-raring": "3:5" + "language-pack-sq": "1:14.04+20140410" + "python3-ply": "3.4-3ubuntu2" + "friends": "0.2.0+14.04.20140217.1-0ubuntu1" + "lib32ncursesw5": "5.9+20140118-1ubuntu1" + "libaal-dev": "1.0.5-6" + "libhsqldb1.8.0-java": "1.8.0.10+dfsg-3ubuntu1" + "python-lockfile": "1:0.8-2ubuntu2" + "libexttextcat-dev": "3.4.3-1ubuntu1" + "language-pack-gnome-or-base": "1:14.04+20140410" + "unity-scope-guayadeque": "0.1+13.10.20130927.1-0ubuntu1" + "gperf": "3.0.4-1" + "libcanberra-gstreamer-dbg": "0.30-0ubuntu3" + "gnu-standards": "2010.03.11-1" + "camlp5": "6.11+dfsg-3" + "gcc-4.8": "4.8.2-19ubuntu1" + "python-gpod": "0.8.3-4ubuntu3" + "xserver-xorg-input-evdev-lts-quantal": "3:5" + "libaccounts-glib-doc": "1.15+14.04.20131126.2-0ubuntu3" + "libmono-system-reactive-interfaces2.2-cil": "3.2.8+dfsg-4ubuntu1" + "libwayland-dev-lts-quantal": "3:5" + "linux-headers-generic": "3.13.0.32.38" + "libgconf2.0-cil": "2.24.2-3" + "libnamespace-clean-perl": "0.24-1" + "libaugeas0": "1.2.0-0ubuntu1" + "libhunspell-1.3-0": "1.3.2-6ubuntu2" + "libido3-0.1-dev": "13.10.0+14.04.20140407-0ubuntu1" + "libstdc++6": "4.8.2-19ubuntu1" + "qtlocation5-examples": "5.2.1-1ubuntu2" + "gccgo-4.9-doc": "4.9-20140406-0ubuntu1" + "language-pack-pap": "1:14.04+20140410" + "language-pack-xh-base": "1:14.04+20140410" + "python3-distutils-extra": "2.38-1build1" + "libice6-dbg": "2:1.0.8-2" + "snmp": "5.7.2~dfsg-8.1ubuntu3" + "libbonobo2-common": "2.32.1-0ubuntu5" + "bison": "2:3.0.2.dfsg-2" + "libk5crypto3": "1.12+dfsg-2ubuntu4" + "openjdk-7-jdk": "7u51-2.4.6-1ubuntu4" + "srvadmin-idrac7": "7.1.0-2" + "language-pack-gnome-br-base": "1:14.04+20140410" + "language-pack-nds-base": "1:14.04+20140410" + "python-amqp": "1.3.3-1ubuntu1" + "libdhash1": "0.3.0.1-4" + "libxml-commons-resolver1.1-java-gcj": "1.2-7build1" + "emacs24-dbg": "24.3+1-2ubuntu1" + "libcib3": "1.1.10+git20130802-1ubuntu2" + "xserver-xorg-video-savage-lts-quantal": "3:5" + "lsb-security": "4.1+Debian11ubuntu6" + "xz-utils": "5.1.1alpha+20120614-2ubuntu2" + "python-twisted-web": "13.2.0-1ubuntu1" + "libegl1-mesa-drivers-lts-saucy-dbg": "3:5" + "libv4lconvert0": "1.0.1-1" + "libxcb-xtest0": "1.10-2ubuntu1" + "libxplc0.3.13": "0.3.13-4" + "anthy-common": "9100h-23ubuntu2" + "python3-commandnotfound": "0.3ubuntu12" + "gcj-4.8-jre": "4.8.2-19ubuntu1" + "libqt5test5": "5.2.1+dfsg-1ubuntu14" + "xserver-xorg": "1:7.7+1ubuntu8" + "neutron-plugin-ryu-agent": "1:2014.1-0ubuntu1" + "wdanish": "1.6.25-1.1" + "libqtdbus4": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "qtdeclarative5-examples": "5.2.1-3ubuntu15" + "libboost-program-options1.54.0": "1.54.0-4ubuntu3" + "libdee-qt4-3": "3.3+14.04.20140317-0ubuntu1" + "libfontconfig1-dev": "2.11.0-0ubuntu4" + "libxcb-ewmh-dev": "0.4.1-1ubuntu1" + "fonts-lklug-sinhala": "0.6-3" + "apt": "1.0.1ubuntu2.1" + "libunity-webapps-dev": "2.5.0~+14.04.20140409-0ubuntu1" + "git-man": "1:1.9.1-1" + "language-pack-ss": "1:12.04+20120417" + "language-pack-tk": "1:14.04+20140410" + "libavahi-client-dev": "0.6.31-4ubuntu1" + "libgnomekbd8": "3.6.0-0ubuntu2" + "multipath-tools": "0.4.9-3ubuntu7" + "libc6-powerpc-cross": "2.19-0ubuntu2cross1.1" + "python-distutils-extra": "2.38-1build1" + "texlive-latex-extra": "2013.20140215-2" + "libasound2-dev": "1.0.27.2-3ubuntu7" + "libcfg-dev": "2.3.3-1ubuntu1" + "xfsprogs": "3.1.9ubuntu2" + "erlang-examples": "1:16.b.3-dfsg-1ubuntu2" + "foomatic-db-compressed-ppds": "20140410-0ubuntu1" + "gawk": "1:4.0.1+dfsg-2.1ubuntu2" + "libdbi-dev": "0.9.0-1" + "libusb-1.0-0": "2:1.0.17-1ubuntu2" + "exim4-daemon-light-dbg": "4.82-3ubuntu2" + "xserver-xorg-video-radeon-lts-quantal": "3:5" + "python-glance-doc": "1:2014.1-0ubuntu1" + "qtdeclarative5-models-plugin": "5.2.1-3ubuntu15" + "language-pack-gnome-bs": "1:14.04+20140410" + "libalgorithm-merge-perl": "0.08-2" + "libbcpkix-java-doc": "1.49+dfsg-2" + "python-ldb-dbg": "1:1.1.16-1" + "xserver-xorg-core-lts-raring-dbg": "3:5" + "fonts-opensymbol": "2:102.6+LibO4.2.3~rc3-0ubuntu2" + "libmono-system-windows-forms4.0-cil": "3.2.8+dfsg-4ubuntu1" + "python3-pbr": "0.7.0-0ubuntu2" + "myspell-he": "1.2-2" + "tk-doc": "8.6.0+6ubuntu3" + "libmonosgen-2.0-1": "3.2.8+dfsg-4ubuntu1" + "linux-tools-generic-lts-trusty": "3.13.0.24.28" + "postfix-mysql": "2.11.0-1" + "python3-pygments": "1.6+dfsg-1ubuntu1" + "g++-4.7": "4.7.3-12ubuntu1" + "libcroco3-dev": "0.6.8-2ubuntu1" + "qttools5-examples": "5.2.1-8build1" + "xserver-xorg-video-neomagic-lts-saucy": "3:5" + "python3-gridfs": "2.6.3-1build1" + "xml-core": "0.13+nmu2" + "gir1.2-javascriptcoregtk-3.0": "2.4.0-1ubuntu2" + "libcwidget3-dbg": "0.5.16-3.5ubuntu1" + "espeak-data": "1.47.11-1ubuntu1" + "libphonon4": "4:4.7.1-0ubuntu8" + "libpython3-all-dev": "3.4.0-0ubuntu2" + "libxcb-glx0": "1.10-2ubuntu1" + "eject": "2.1.5+deb1+cvs20081104-13.1" + "libxcb-dri2-0-dbg": "1.10-2ubuntu1" + "hyphen-fr": "1:4.2.1-0ubuntu1" + "libisofs-doc": "1.3.4-0ubuntu1" + "linux-image-generic-lts-quantal": "3.13.0.24.28" + "tgt": "1:1.0.43-0ubuntu4" + "libfile-which-perl": "1.09-1" + "libjack-dev": "1:0.121.3+20120418git75e3e20b-2.1ubuntu1" + "libpcap0.8-dev": "1.5.3-2" + "gfortran-4.8-doc": "4.8.2-19ubuntu1" + "libmono-webbrowser2.0-cil": "3.2.8+dfsg-4ubuntu1" + "myspell-uk": "1.6.5-2" + "python-kombu": "3.0.7-1ubuntu1" + "dh-modaliases": "1:0.2.91.4" + "python-networkx": "1.8.1-0ubuntu3" + "libmirserver-dev": "0.1.8+14.04.20140411-0ubuntu1" + "python-msgpack": "0.3.0-1ubuntu3" + "qtdeclarative5-doc-html": "5.2.1-3ubuntu15" + "linux-tools-lts-raring": "3.13.0.24.28" + "thunderbird-locale-eu": "1:24.4.0+build1-0ubuntu1" + "crossbuild-essential-ppc64el": "11.6ubuntu6" + "graphviz-dev": "2.36.0-0ubuntu3" + "language-pack-ga": "1:14.04+20140410" + "libgdata-doc": "0.14.1-1" + "gir1.2-telepathyglib-0.12": "0.22.1-1ubuntu2" + "python-iscpy": "1.05-0ubuntu2" + "gir1.2-gstreamer-0.10": "0.10.36-1.2ubuntu3" + "libfontforge-dev": "20120731.b-5" + "libxatracker1-lts-raring-dbg": "3:5" + "libgcc-4.8-dev-arm64-cross": "4.8.2-13ubuntu1cross0.11" + "kmod": "15-0ubuntu6" + "libsysfs-dev": "2.1.0+repack-3ubuntu1" + "uuidcdef": "0.3.13-4" + "finch-dev": "1:2.10.9-0ubuntu3" + "qtcore4-l10n": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "ubuntu-session": "3.9.90-0ubuntu12" + "libgbm1": "10.1.0-4ubuntu5" + "libpcre3-dbg": "1:8.31-2ubuntu2" + "libcanberra-gtk3-0": "0.30-0ubuntu3" + "librpm-dbg": "4.11.1-3" + "xserver-xorg-video-cirrus": "1:1.5.2-1build1" + "libc6-dev-armel-cross": "2.19-0ubuntu2cross1.104" + "libmono-winforms2.0-cil": "3.2.8+dfsg-4ubuntu1" + "liborc-0.4-doc": "1:0.4.18-1ubuntu1" + "lzma-dev": "9.22-2ubuntu2" + "python-amqplib": "1.0.2-1" + "libx32objc4-dbg": "4.8.2-19ubuntu1" + "language-pack-mt": "1:14.04+20140410" + "indicator-power": "12.10.6+14.04.20140411-0ubuntu1" + "libaa1-dbg": "1.4p5-41" + "libfolks-telepathy25": "0.9.5-1ubuntu5" + "libwayland-egl1-mesa": "10.1.0-4ubuntu5" + "heat-common": "2014.1-0ubuntu1" + "myspell-ss": "20070206-4ubuntu1" + "libusbredirparser1": "0.6-2ubuntu1" + "thunderbird-locale-ga": "1:24.4.0+build1-0ubuntu1" + "xserver-xorg-video-dummy": "1:0.3.7-1build1" + "gdebi-core": "0.9.5.3" + "language-pack-gnome-so-base": "1:13.04+20130418" + "libebackend1.2-dev": "3.10.4-0ubuntu1" + "libgtk-3-bin": "3.10.8-0ubuntu1" + "libgupnp-1.0-dbg": "0.20.10-1ubuntu1" + "libclass-data-inheritable-perl": "0.08-2" + "libdatetime-format-mysql-perl": "0.04-3" + "libreoffice-l10n-be": "1:4.2.3~rc3-0ubuntu1" + "rake": "10.0.4-1" + "xserver-xorg-video-siliconmotion-lts-raring": "3:5" + "libwayland-cursor0": "1.4.0-1ubuntu1" + "myspell-ga": "2.0-22" + "python-cinderclient": "1:1.0.8-0ubuntu1" + "keepalived": "1:1.2.7-1ubuntu1" + "libkdeui5": "4:4.13.0-0ubuntu1" + "libnuma-dev": "2.0.9~rc5-1ubuntu2" + "libxxf86vm1": "1:1.1.3-1" + "python3-pyqt4.qtopengl": "4.10.4+dfsg-1ubuntu1" + "liblangtag-common": "0.5.1-2" + "libmono-system-json2.0-cil": "3.2.8+dfsg-4ubuntu1" + "monodoc-browser": "2.11+git20131009.5b1ef35-1build1" + "libpipeline1": "1.3.0-1" + "libsuitesparse-dev": "1:4.2.1-3ubuntu1" + "language-pack-da-base": "1:14.04+20140410" + "libglibmm-2.4-doc": "2.39.93-0ubuntu1" + "libxplc0.3.13-dev": "0.3.13-4" + "mklibs-copy": "0.1.39" + "python3-pyqt5.qtquick": "5.2.1+dfsg-1ubuntu1" + "language-pack-nan": "1:14.04+20140410" + "libow-util-ant-tasks-java": "1.3.2-4build1" + "libupstart-app-launch2-dev": "0.3+14.04.20140411-0ubuntu1" + "mailman": "1:2.1.16-2" + "libqb0": "0.16.0.real-1ubuntu3" + "libspectre1-dbg": "0.2.7-2ubuntu1" + "patchutils": "0.3.2-3" + "libgpgme11": "1.4.3-0.1ubuntu5" + "libllvm3.4": "1:3.4-1ubuntu3" + "libtalloc-dev": "2.1.0-1" + "lib64gcc-4.8-dev-powerpc-cross": "4.8.2-16ubuntu3cross0.11" + "libdiscid-doc": "0.6.1-2" + "python-docutils": "0.11-3" + "yelp-xsl": "3.10.1-1" + "iptraf": "3.0.0-8.1" + "python-appconf": "0.5-2build1" + "lib32ncurses5": "5.9+20140118-1ubuntu1" + "libgexiv2-2": "0.10.0-1ubuntu1" + "libipc-run3-perl": "0.046-1" + "apt-transport-https": "1.0.1ubuntu2" + "qdbus": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "xserver-xorg-video-nouveau-lts-raring-dbg": "3:5" + "libnet-smtp-ssl-perl": "1.01-3" + "ubuntu-location-service-doc": "0.0.2+14.04.20140307-0ubuntu1" + "libboost-regex-dev": "1.54.0.1ubuntu1" + "libtcl8.5-dbg": "8.5.15-2ubuntu1" + "libgnome2-common": "2.32.1-4ubuntu1" + "indent": "2.2.11-4" + "python3-pyqt4-dbg": "4.10.4+dfsg-1ubuntu1" + "sysvinit-utils": "2.88dsf-41ubuntu6" + "strongswan-ike": "5.1.2-0ubuntu2" + "libgbm1-lts-raring-dbg": "3:5" + "libphonon4qt5-dev": "4:4.7.1-0ubuntu8" + "mesa-common-dev-lts-saucy": "3:5" + "nautilus-dbg": "1:3.10.1-0ubuntu8" + "overlay-scrollbar-gtk3": "0.2.16+r359+14.04.20131129-0ubuntu1" + "libglapi-mesa-lts-quantal-dbg": "3:5" + "libogg-dbg": "1.3.1-1ubuntu1" + "myspell-ve": "20070206-3ubuntu1" + "ruby-mocha": "0.14.0-2ubuntu1" + "sharutils-doc": "1:4.14-1ubuntu1" + "gir1.2-ibus-1.0": "1.5.5-1ubuntu3" + "libdebconfclient0": "0.187ubuntu1" + "bridge-utils": "1.5-6ubuntu2" + "libmysqlcppconn-dev": "1.1.3-5" + "libwnck-3-0": "3.4.7-0ubuntu3" + "libwrap0": "7.6.q-25" + "libcheese-dev": "3.10.2-0ubuntu2" + "powertop": "2.5-1ubuntu1" + "thunderbird": "1:24.4.0+build1-0ubuntu1" + "libcrypt-passwdmd5-perl": "1.3-10" + "thunderbird-locale-es-ar": "1:24.4.0+build1-0ubuntu1" + "anacron": "2.3-20ubuntu1" + "lftp": "4.4.13-1" + "libatspi2.0-0-dbg": "2.10.2.is.2.10.1-0ubuntu1" + "hyphen-hr": "20060617-2.4" + "libwnck-common": "1:2.30.7-0ubuntu4" + "libmission-control-plugins-dev": "1:5.16.1-1ubuntu3" + "ruby-ffi": "1.9.3debian-1ubuntu2" + "dpkg-dev": "1.17.5ubuntu5.3" + "language-pack-gnome-my": "1:14.04+20140410" + "language-pack-he": "1:14.04+20140410" + "seabios": "1.7.4-4" + "virt-manager": "0.9.5-1ubuntu3" + "libdumbnet1": "1.12-4build1" + "libical-dev": "1.0-0ubuntu1" + "fonts-texgyre": "2.004.2-4" + "tcl8.5-doc": "8.5.15-2ubuntu1" + "xkb-data": "2.10.1-1ubuntu1" + "ftp": "0.17-28" + "libdevhelp-3-2": "3.8.2-2ubuntu1" + "language-pack-kw-base": "1:14.04+20140410" + "libspectre1": "0.2.7-2ubuntu1" + "qtscript5-examples": "5.2.1+dfsg-1ubuntu1" + "neutron-plugin-ryu": "1:2014.1-0ubuntu1" + "pep8": "1.4.6-1.1build1" + "libminiupnpc8": "1.6-3ubuntu2" + "libpulse0": "1:4.0-0ubuntu11" + "libgconf-2-4": "3.2.6-0ubuntu2" + "libpython-dev": "2.7.5-5ubuntu3" + "rtkit": "0.10-3" + "llvm-3.4-examples": "1:3.4-1ubuntu3" + "xtrabackup": "2.1.8-1" + "emacs24-lucid-dbg": "24.3+1-2ubuntu1" + "firefox-locale-ta": "28.0+build2-0ubuntu2" + "gfortran-4.8": "4.8.2-19ubuntu1" + "libxom-java": "1.2.10-1" + "cups-client": "1.7.2-0ubuntu1" + "libdhash-dev": "0.3.0.1-4" + "libjunitperf-java-doc": "1.9.1-8ubuntu1" + "python3-testtools": "0.9.35-0ubuntu1" + "python-sane-dbg": "2.3.0-1ubuntu3" + "libbluetooth-dev": "4.101-0ubuntu13" + "libphobos-4.8-dev": "4.8.2-19ubuntu1" + "libsane-dev": "1.0.23-3ubuntu3" + "xserver-xorg-video-mach64-lts-quantal-dbg": "3:5" + "libnumber-compare-perl": "0.03-1" + "libtest-deep-perl": "0.112-1" + "cpp-doc": "4:4.8.2-1ubuntu6" + "gvfs-bin": "1.20.1-1ubuntu1" + "libparted0debian1": "2.3-19ubuntu1" + "ceilometer-agent-compute": "2014.1-0ubuntu1" + "txt2man": "1.5.5-4.1" + "ldm": "2:2.2.13-1" + "libkdc2-heimdal": "1.6~git20131207+dfsg-1ubuntu1" + "libmtp-runtime": "1.1.6-20-g1b9f164-1ubuntu2" + "libipmimonitoring5": "1.1.5-3ubuntu3" + "pulseaudio-module-lirc": "1:4.0-0ubuntu11" + "hyphen-en-us": "2.8.6-3ubuntu2" + "language-pack-sc-base": "1:14.04+20140410" + "e2fsprogs-dbg": "1.42.9-3ubuntu1" + "erlang-ssl": "1:16.b.3-dfsg-1ubuntu2" + "libreoffice-base-drivers": "1:4.2.3~rc3-0ubuntu2" + "liburcu-dev": "0.7.12-0ubuntu2" + "libstdc++6-ppc64el-cross": "4.8.2-16ubuntu4cross0.4" + "python3-cxx-dev": "6.2.5-1ubuntu2" + "x11proto-dmx-dev": "1:2.3.1-2" + "gir1.2-rsvg-2.0": "2.40.2-1" + "libprelude-dev": "1.0.0-11ubuntu4" + "printer-driver-foo2zjs": "20140209dfsg0-1ubuntu1" + "docbook": "4.5-5.1ubuntu1" + "language-pack-gnome-crh": "1:14.04+20140410" + "readline-common": "6.3-4ubuntu2" + "bamf-dbg": "0.5.1+14.04.20140409-0ubuntu1" + "libconfig++-dev": "1.4.9-2" + "libnet1-dbg": "1.1.6+dfsg-2ubuntu1" + "libupower-glib1": "0.9.23-2ubuntu1" + "cython-doc": "0.20.1+git90-g0e6e38e-1ubuntu2" + "libogg0": "1.3.1-1ubuntu1" + "libraptor2-0-dbg": "2.0.13-1" + "libaugeas-ruby1.8": "0.5.0-2" + "libspice-protocol-dev": "0.12.6-1" + "libboost-test1.54.0": "1.54.0-4ubuntu3" + "libgssapi-krb5-2": "1.12+dfsg-2ubuntu4" + "libnl-3-dev": "3.2.21-1" + "libx32asan0": "4.8.2-19ubuntu1" + "perl": "5.18.2-2ubuntu1" + "qtdeclarative5-qtfeedback-plugin": "5.0~git20130529-0ubuntu3" + "libhtml-tree-perl": "5.03-1" + "libstax-java-doc": "1.2.0-3build1" + "vala-0.22-doc": "0.22.1-0ubuntu1" + "libjasper-dev": "1.900.1-14ubuntu3" + "libverto-libevent1": "0.2.4-1ubuntu2" + "intltool-debian": "0.35.0+20060710.1" + "language-pack-gnome-sv-base": "1:14.04+20140410" + "mythes-it": "2.0.7.gh.deb1-4.1" + "libqt4-qt3support-dbg": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "libzzip-dev": "0.13.62-2" + "plymouth": "0.8.8-0ubuntu17" + "thunderbird-locale-it": "1:24.4.0+build1-0ubuntu1" + "libtelepathy-farstream3-dbg": "0.6.1-0ubuntu1" + "libreoffice-l10n-ga": "1:4.2.3~rc3-0ubuntu1" + "resolvconf": "1.69ubuntu1.1" + "ubuntu-artwork": "1:14.04+14.04.20140410-0ubuntu1" + "erlang-odbc": "1:16.b.3-dfsg-1ubuntu2" + "lib32readline-gplv2-dev": "5.2+dfsg-2" + "libapache2-mod-python-doc": "3.3.1-11ubuntu2" + "libicu-dev": "52.1-3" + "libpolkit-agent-1-dev": "0.105-4ubuntu2" + "libqimageblitz-perl": "4:4.13.0-0ubuntu1" + "python-tdb": "1.2.12-1" + "tk8.5-doc": "8.5.15-2ubuntu3" + "account-plugin-jabber": "3.8.6-0ubuntu9" + "libsearchclient0": "0.7.8-1ubuntu2" + "python3-sip-dev": "4.15.5-1build1" + "language-pack-gnome-se": "1:14.04+20140410" + "libmono-system-xml-serialization4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libpangomm-1.4-doc": "2.34.0-1ubuntu1" + "ubiquity-ubuntu-artwork": "2.18.7" + "initscripts": "2.88dsf-41ubuntu6" + "libmono-messaging-rabbitmq4.0-cil": "3.2.8+dfsg-4ubuntu1" + "qtsvg5-doc-html": "5.2.1-1" + "libpam-apparmor": "2.8.95~2430-0ubuntu5" + "libx32go4-dbg": "4.8.2-19ubuntu1" + "php5-json": "1.3.2-2build1" + "vim-dbg": "2:7.4.052-1ubuntu3" + "language-pack-lv-base": "1:14.04+20140410" + "libproperties-cpp-doc": "0.0.1+14.04.20140220-0ubuntu1" + "libmoose-perl": "2.1005-1" + "libotf-dev": "0.9.13-1ubuntu1" + "libssl-dev": "1.0.1f-1ubuntu2" + "cyrus-sasl2-dbg": "2.1.25.dfsg1-17build1" + "dnsutils": "1:9.9.5.dfsg-3" + "libqt4-dbus": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "hyphen-pa": "0.7.0-1" + "libappindicator-doc": "12.10.1+13.10.20130920-0ubuntu4" + "python-mako-doc": "0.9.1-1" + "wbulgarian": "4.1-3ubuntu1" + "xserver-xorg-input-synaptics-lts-raring": "3:5" + "diveintopython": "5.4-2ubuntu2" + "dpkg-dev": "1.17.5ubuntu5" + "libreoffice-l10n-ts": "1:4.2.3~rc3-0ubuntu1" + "libsoftware-license-perl": "0.103008-1" + "python-ntdb": "1.0-2ubuntu1" + "thunderbird-locale-ar": "1:24.4.0+build1-0ubuntu1" + "libevent-dev": "2.0.21-stable-1ubuntu1" + "libipmimonitoring-dev": "1.1.5-3ubuntu3" + "librtmp0": "2.4+20121230.gitdf6c518-1" + "libubuntu-application-api-mirserver1": "0.20+14.04.20140411-0ubuntu1" + "libx32atomic1-dbg": "4.8.2-19ubuntu1" + "gnome-orca": "3.10.3-0ubuntu1" + "python-mimeparse": "0.1.4-1build1" + "libgnome-bluetooth11": "3.8.2.1-0ubuntu4" + "libqtdbus4-perl": "4:4.13.0-0ubuntu1" + "python-egenix-mxbeebase-doc": "3.2.7-1build1" + "libdrm2": "2.4.52-1" + "libqca2-dbg": "2.0.3-5" + "libsam4": "2.3.3-1ubuntu1" + "libt1-5": "5.1.2-3.6ubuntu1" + "libclass-load-perl": "0.20-1" + "linux-headers-virtual": "3.13.0.24.28" + "openssh-server": "1:6.6p1-2ubuntu1" + "apt": "1.0.1ubuntu2" + "gcc-4.8-base": "4.8.2-19ubuntu1" + "libaccount-plugin-1.0-dev": "0.1.7~+14.04.20140211.2-0ubuntu4" + "libcunit1-ncurses": "2.1-2.dfsg-1" + "libvte9": "1:0.28.2-5ubuntu1" + "language-pack-gnome-sw-base": "1:14.04+20140410" + "python-ldap-dbg": "2.4.10-1build1" + "libcommons-collections3-java": "3.2.1-6" + "nut-doc": "2.7.1-1ubuntu1" + "cups-filters-core-drivers": "1.0.52-0ubuntu1" + "eatmydata": "26-2" + "python-yaml-dbg": "3.10-4build4" + "libcunit1": "2.1-2.dfsg-1" + "libstreamanalyzer-dev": "0.7.8-1ubuntu2" + "libxext6-dbg": "2:1.3.2-1" + "postgresql-9.3": "9.3.4-1" + "munin": "2.0.19-3" + "libtcl8.5": "8.5.15-2ubuntu1" + "language-pack-gnome-li-base": "1:14.04+20140410" + "language-pack-gnome-nso": "1:14.04+20140410" + "libboost-system1.54-dev": "1.54.0-4ubuntu3" + "libsystemd-daemon-dev": "204-5ubuntu20" + "openjdk-7-jre": "7u51-2.4.6-1ubuntu4" + "ttf-indic-fonts-core": "1:0.5.14ubuntu1" + "libdbusmenu-qt5": "0.9.3+14.04.20140314-0ubuntu1" + "libecpg-dev": "9.3.4-1" + "libx32gcc1-dbg": "1:4.9-20140406-0ubuntu1" + "libxrandr-dev": "2:1.4.2-1" + "language-pack-mn-base": "1:14.04+20140410" + "libtext-csv-perl": "1.32-1" + "gir1.2-json-1.0": "0.16.2-1ubuntu1" + "libdiscid0-dev": "0.6.1-2" + "libwnck-3-dev": "3.4.7-0ubuntu3" + "ibus-table": "1.5.0.is.1.5.0.20130419-2" + "language-pack-gnome-nl": "1:14.04+20140410" + "lib64gomp1-powerpc-cross": "4.8.2-16ubuntu3cross0.11" + "libperl-minimumversion-perl": "1.32-1" + "antlr": "2.7.7+dfsg-5" + "language-pack-gnome-ug-base": "1:14.04+20140410" + "libraw1394-doc": "2.1.0-1ubuntu1" + "gir1.2-gdesktopenums-3.0": "3.10.1-0ubuntu1" + "python-dbg": "2.7.5-5ubuntu3" + "xul-ext-webaccounts": "0.5-0ubuntu2" + "avahi-daemon": "0.6.31-4ubuntu1" + "libhpmud-dev": "3.14.3-0ubuntu3" + "libpango1.0-0": "1.36.3-1ubuntu1" + "libreadline6-dev": "6.3-4ubuntu2" + "xserver-xorg-video-mga": "1:1.6.3-1build1" + "libio-socket-inet6-perl": "2.71-1" + "libreoffice-l10n-nn": "1:4.2.3~rc3-0ubuntu1" + "m17n-contrib": "1.1.14-1" + "nvidia-prime": "0.6.2" + "xserver-xorg-video-mga-lts-quantal": "3:5" + "onboard-data": "1.0.0-0ubuntu4" + "libexempi3-dbg": "2.2.1-1ubuntu1" + "mesa-common-dev-lts-quantal": "3:5" + "autoconf-doc": "2.69-6" + "ibus-table-cangjie3": "1.4.6-Source-1" + "libio-string-perl": "1.08-3" + "libaudiofile-dbg": "0.3.6-2" + "libmono-system-messaging2.0-cil": "3.2.8+dfsg-4ubuntu1" + "clamav-dbg": "0.98.1+dfsg-4ubuntu1" + "libkadm5srv8-heimdal": "1.6~git20131207+dfsg-1ubuntu1" + "libunistring0": "0.9.3-5ubuntu3" + "libreoffice-help-ja": "1:4.2.3~rc3-0ubuntu1" + "libsss-idmap-dev": "1.11.5-1ubuntu3" + "qtpositioning5-dev": "5.2.1-1ubuntu2" + "xserver-xorg-video-r128-lts-raring-dbg": "3:5" + "python3-mox3": "0.7.0-1build1" + "binutils-arm-linux-gnueabihf": "2.24-2ubuntu3cross1.98" + "libtokyocabinet9": "1.4.48-2" + "rpm-common": "4.11.1-3" + "language-pack-ms": "1:14.04+20140410" + "pulseaudio-module-jack": "1:4.0-0ubuntu11" + "libmono-microsoft-visualc10.0-cil": "3.2.8+dfsg-4ubuntu1" + "ecj-gcj": "3.9.0-1" + "gconf-service-backend": "3.2.6-0ubuntu2" + "libx32ncurses5-dev": "5.9+20140118-1ubuntu1" + "libgcc1-ppc64el-cross": "1:4.8.2-16ubuntu4cross0.4" + "libegl1-mesa-dbg": "10.1.0-4ubuntu5" + "libss2": "1.42.9-3ubuntu1" + "python-egenix-mx-base-dbg": "3.2.7-1build1" + "pkg-config-arm-linux-gnueabihf": "4:4.8.2-1" + "rhythmbox-dev": "3.0.2-0ubuntu1" + "language-pack-nb-base": "1:14.04+20140410" + "libb-keywords-perl": "1.13-1" + "libjson-glib-doc": "0.16.2-1ubuntu1" + "libtext-format-perl": "0.59-1" + "firefox-locale-ko": "28.0+build2-0ubuntu2" + "libnet1-doc": "1.1.6+dfsg-2ubuntu1" + "libclucene-contribs1": "2.3.3.4-4build1" + "libgles1-mesa-dev": "10.1.0-4ubuntu5" + "libplymouth-dev": "0.8.8-0ubuntu17" + "libwbclient0": "2:4.1.6+dfsg-1ubuntu2" + "libxv1": "2:1.0.10-1" + "recode": "3.6-21" + "language-pack-gnome-ks-base": "1:14.04+20140410" + "libreoffice-l10n-sk": "1:4.2.3~rc3-0ubuntu1" + "libc6": "2.19-0ubuntu6" + "libftdi1-dbg": "0.20-1ubuntu1" + "libopenhpi2": "2.14.1-1.3ubuntu2" + "language-pack-gnome-ar-base": "1:14.04+20140410" + "libapt-pkg-doc": "1.0.1ubuntu2" + "libdevhelp-dev": "3.8.2-2ubuntu1" + "libjpeg8-dev": "8c-2ubuntu8" + "libphonon4qt5experimental4": "4:4.7.1-0ubuntu8" + "libreoffice-l10n-is": "1:4.2.3~rc3-0ubuntu1" + "ncurses-bin": "5.9+20140118-1ubuntu1" + "language-pack-gnome-el-base": "1:14.04+20140410" + "libtokyocabinet-dev": "1.4.48-2" + "nagios-plugins-standard": "1.5-3ubuntu1" + "hyphen-sh": "1:3.3.0-2ubuntu3" + "libmono-microsoft-build2.0-cil": "3.2.8+dfsg-4ubuntu1" + "libcgmanager0": "0.24-0ubuntu5" + "libgo5-dbg": "4.9-20140406-0ubuntu1" + "libxslt1-dbg": "1.1.28-2build1" + "luatex": "0.76.0-3ubuntu1" + "tk-dev": "8.6.0+6ubuntu3" + "libbcpg-java": "1.49+dfsg-2" + "liblzma-doc": "5.1.1alpha+20120614-2ubuntu2" + "logcheck": "1.3.16" + "firefox-locale-uk": "28.0+build2-0ubuntu2" + "librpmio3": "4.11.1-3" + "xterm": "297-1ubuntu1" + "language-pack-fa-base": "1:14.04+20140410" + "libtotem-plparser-dev": "3.10.2-0ubuntu1" + "sg3-utils": "1.36-1ubuntu1" + "apt-xapian-index": "0.45ubuntu4" + "language-pack-sa-base": "1:14.04+20140410" + "gir1.2-gconf-2.0": "3.2.6-0ubuntu2" + "libstreamanalyzer0": "0.7.8-1ubuntu2" + "speech-dispatcher-audio-plugins": "0.8-5ubuntu1" + "make-doc": "3.81-5.1" + "libqtsvg4-perl": "4:4.13.0-0ubuntu1" + "linux-image-3.13.0-24-generic": "3.13.0-24.46" + "pulseaudio-module-jack-dbg": "1:4.0-0ubuntu11" + "libtest-nowarnings-perl": "1.04-1" + "python3-pyinotify": "0.9.4-1build1" + "libgstreamer1.0-0-dbg": "1.2.3-1" + "libhcrypto4-heimdal": "1.6~git20131207+dfsg-1ubuntu1" + "libyaml-libyaml-perl": "0.41-5" + "libtinfo-dev": "5.9+20140118-1ubuntu1" + "language-pack-gnome-he-base": "1:14.04+20140410" + "python-iso8601": "0.1.10-0ubuntu1" + "python3-prettytable": "0.7.2-2ubuntu2" + "compiz-plugins-default": "1:0.9.11+14.04.20140409-0ubuntu1" + "heartbeat": "1:3.0.5-3.2" + "libsonic0": "0.1.18-0ubuntu1" + "openjdk-7-demo": "7u51-2.4.6-1ubuntu4" + "language-pack-br": "1:14.04+20140410" + "libappindicator3-dev": "12.10.1+13.10.20130920-0ubuntu4" + "login": "1:4.1.5.1-1ubuntu9" + "qt5-default": "5.2.1+dfsg-1ubuntu14" + "xserver-xorg-input-synaptics-dbg": "1.7.4-0ubuntu1" + "curtin-common": "0.1.0~bzr126-0ubuntu1" + "hyphen-ru": "20030310-1ubuntu1" + "python3-imaging-dbg": "2.3.0-1ubuntu3" + "giflib-tools": "4.1.6-11" + "ppp": "2.4.5-5.1ubuntu2" + "myspell-pt-br": "20131030-1" + "dselect": "1.17.5ubuntu5" + "libnepomukutils4": "4:4.13.0-0ubuntu1" + "python-xapian": "1.2.16-2ubuntu1" + "libdw-dev": "0.158-0ubuntu5" + "wdutch": "1:2.10-1" + "firefox-locale-nb": "28.0+build2-0ubuntu2" + "libwayland-dev-lts-raring": "3:5" + "libb-hooks-endofscope-perl": "0.13-1" + "libreoffice-l10n-ro": "1:4.2.3~rc3-0ubuntu1" + "libunique-doc": "1.1.6-4ubuntu2" + "dconf-gsettings-backend": "0.20.0-1" + "libcompizconfig0-dev": "1:0.9.11+14.04.20140409-0ubuntu1" + "fonts-khmeros-core": "5.0-7ubuntu1" + "liblwp-protocol-https-perl": "6.04-2" + "libxtst-doc": "2:1.2.2-1" + "python-secretstorage": "2.0.0-1ubuntu1" + "compat-libstdc": "5-1" + "libsemanage1-dev": "2.2-1" + "libpolkit-agent-1-0": "0.105-4ubuntu2" + "language-pack-gnome-nl-base": "1:14.04+20140410" + "libparse-debianchangelog-perl": "1.2.0-1ubuntu1" + "brltty-dbg": "5.0-2ubuntu2" + "libfontconfig1-dbg": "2.11.0-0ubuntu4" + "libkrb5-3": "1.12+dfsg-2ubuntu4" + "libfarstream-0.1-doc": "0.1.2-1ubuntu3" + "libglib2.0-0": "2.40.0-2" + "libhfsp0": "1.0.4-12.1" + "libqt5concurrent5": "5.2.1+dfsg-1ubuntu14" + "libverto1": "0.2.4-1ubuntu2" + "python3-sip-dbg": "4.15.5-1build1" + "qtbase5-dev": "5.2.1+dfsg-1ubuntu14" + "xserver-xorg-core-lts-saucy": "3:5" + "monodoc-manual": "3.2.8+dfsg-4ubuntu1" + "libqt4-scripttools": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "libqt5location5-plugins": "5.2.1-1ubuntu2" + "libqt5opengl5-dev": "5.2.1+dfsg-1ubuntu14" + "libruby1.9.1": "1.9.3.484-2ubuntu1" + "neutron-plugin-linuxbridge-agent": "1:2014.1-0ubuntu1" + "libfarstream-0.1-0": "0.1.2-1ubuntu3" + "libnl-route-3-dev": "3.2.21-1" + "libplatform-api1-dev": "0.20+14.04.20140411-0ubuntu1" + "vorbis-tools-dbg": "1.4.0-1ubuntu3" + "hunspell-ru": "20120501-1" + "libmodule-implementation-perl": "0.07-1" + "libcorosync-common-dev": "2.3.3-1ubuntu1" + "python-pyorbit-dbg": "2.24.0-6ubuntu4" + "zenity": "3.8.0-1ubuntu1" + "libbrlapi0.6": "5.0-2ubuntu2" + "konwert-dev": "1.8-11.2build2" + "language-pack-gnome-zh-hans-base": "1:14.04+20140410" + "libtest-harness-perl": "3.30-1" + "swig-examples": "2.0.11-1ubuntu2" + "libaccount-plugin-google": "0.11+14.04.20140409.1-0ubuntu1" + "libgs9-common": "9.10~dfsg-0ubuntu10" + "libgpod-cil": "0.8.3-4ubuntu3" + "libtiffxx5": "4.0.3-7" + "oxideqt-codecs-dbg": "1.0.0~bzr501-0ubuntu1" + "qtdeclarative5-qtmultimedia-plugin": "5.2.1-0ubuntu5" + "thunderbird-locale-ta-lk": "1:24.4.0+build1-0ubuntu1" + "pacemaker": "1.1.10+git20130802-1ubuntu2" + "python-bzrlib-dbg": "2.6.0+bzr6593-1ubuntu1" + "hyphen-hu": "1:4.2.1-0ubuntu1" + "libmono-npgsql4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libcloog-ppl-dev": "0.16.1-5" + "libphononexperimental-dev": "4:4.7.1-0ubuntu8" + "libdbusmenu-qt5-doc": "0.9.3+14.04.20140314-0ubuntu1" + "libsoup2.4-doc": "2.44.2-1ubuntu2" + "libcib3-dev": "1.1.10+git20130802-1ubuntu2" + "language-pack-gnome-nn": "1:14.04+20140410" + "qt4-demos": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "xserver-xorg-input-wacom-lts-raring-dbg": "3:5" + "libsasl2-modules-sql": "2.1.25.dfsg1-17build1" + "libxcb-xf86dri0-dbg": "1.10-2ubuntu1" + "language-pack-sr": "1:14.04+20140410" + "btrfs-tools-dbg": "3.12-1" + "libdconf-dbg": "0.20.0-1" + "libgtk2.0-bin": "2.24.23-0ubuntu1" + "librbd1": "0.79-0ubuntu1" + "radosgw-dbg": "0.79-0ubuntu1" + "tidy-doc": "20091223cvs-1.2ubuntu1" + "evince": "3.10.3-0ubuntu10" + "kerneloops-daemon": "0.12+git20090217-3ubuntu8" + "libecap2": "0.2.0-1ubuntu4" + "qtxmlpatterns5-examples": "5.2.1-3" + "usbmuxd": "1.0.8-2ubuntu1" + "language-pack-gnome-om-base": "1:14.04+20140410" + "python-pycountry": "0.14.1+ds1-3build1" + "libcmap-dev": "2.3.3-1ubuntu1" + "libhangul-dev": "0.1.0-3" + "libisoburn-dev": "1.3.2-1ubuntu1" + "tipa-doc": "2:1.3-19" + "libdbus-cpp2": "2.0.0+14.04.20140326-0ubuntu1" + "libsigc++-2.0-0c2a": "2.2.10-0.2ubuntu2" + "python-django-openstack": "1:2014.1-0ubuntu1" + "icu-devtools": "52.1-3" + "libgtk2.0-dev": "2.24.23-0ubuntu1" + "libspeexdsp-dev": "1.2~rc1.1-1ubuntu1" + "samba": "2:4.1.6+dfsg-1ubuntu2" + "python-babel-localedata": "1.3+dfsg.1-2ubuntu1" + "libfarstream-0.1-dbg": "0.1.2-1ubuntu3" + "libimlib2-dev": "1.4.6-2" + "perlmagick": "8:6.7.7.10-6ubuntu3" + "language-pack-os": "1:14.04+20140410" + "ttf-unifont": "1:6.3.20131221-1" + "libmono-sharpzip4.84-cil": "3.2.8+dfsg-4ubuntu1" + "libunwind8-dbg": "1.1-2.2ubuntu3" + "libxml2-dev": "2.9.1+dfsg1-3ubuntu4" + "phonon-backend-gstreamer-dbg": "4:4.7.1+git20140403-0ubuntu1" + "junit4": "4.11-2" + "munin-common": "2.0.19-3" + "libgtkmm-2.4-1c2a": "1:2.24.4-1ubuntu1" + "liblockfile-bin": "1.09-6ubuntu1" + "libnfnetlink0": "1.0.1-2" + "tcpd": "7.6.q-25" + "libpython3.4-testsuite": "3.4.0-2ubuntu1" + "python3-pyqt5.qtsql": "5.2.1+dfsg-1ubuntu1" + "libreoffice-help-pl": "1:4.2.3~rc3-0ubuntu1" + "maas-enlist": "0.4+bzr38-0ubuntu1" + "xserver-xorg-video-ati-lts-raring-dbg": "3:5" + "ss-dev": "2.0-1.42.9-3ubuntu1" + "whois": "5.1.1" + "ant-doc": "1.9.3-2build1" + "lib64stdc++-4.8-dev-powerpc-cross": "4.8.2-16ubuntu3cross0.11" + "linuxdoc-tools-text": "0.9.69-2" + "libgsf-1-dev": "1.14.27-2ubuntu2" + "lxc-dbg": "1.0.3-0ubuntu3" + "language-pack-gnome-yo": "1:14.04+20140410" + "libxml-regexp-perl": "0.04-1" + "libnet1-dev": "1.1.6+dfsg-2ubuntu1" + "libpaper1": "1.1.24+nmu2ubuntu3" + "logcheck-database": "1.3.16" + "firefox-locale-ku": "28.0+build2-0ubuntu2" + "gimp": "2.8.10-0ubuntu1" + "libimlib2": "1.4.6-2" + "libpoppler-cpp-dev": "0.24.5-2ubuntu4" + "thunderbird-gnome-support": "1:24.4.0+build1-0ubuntu1" + "git-bzr": "1:1.9.1-1" + "libreoffice-l10n-sl": "1:4.2.3~rc3-0ubuntu1" + "gnome-bluetooth": "3.8.2.1-0ubuntu4" + "libfriends0": "0.1.2+14.04.20131108.1-0ubuntu1" + "libxtst6": "2:1.2.2-1" + "cups-daemon": "1.7.2-0ubuntu1" + "erlang-xmerl": "1:16.b.3-dfsg-1ubuntu2" + "libpoppler-glib8": "0.24.5-2ubuntu4" + "python-django-doc": "1.6.1-2" + "erlang-diameter": "1:16.b.3-dfsg-1ubuntu2" + "libapache2-mod-wsgi": "3.4-4ubuntu2" + "gcc-4.8-multilib-arm-linux-gnueabihf": "4.8.2-16ubuntu4cross0.11" + "gir1.2-accountsservice-1.0": "0.6.35-0ubuntu7" + "libcdio-cdda-dev": "0.83-4.1ubuntu1" + "unity-lens-music": "6.9.0+13.10.20131011-0ubuntu1" + "memcached": "1.4.14-0ubuntu9" + "language-pack-gnome-it": "1:14.04+20140410" + "libwebkitgtk-3.0-common": "2.4.0-1ubuntu2" + "libflite1": "1.4-release-8" + "librpm-dev": "4.11.1-3" + "mdetect": "0.5.2.3build2" + "libhud2-dev": "13.10.1+14.04.20140402-0ubuntu1" + "libmedia-dev": "0.1.0+git20131207+e452e83-0ubuntu12" + "language-pack-ko-base": "1:14.04+20140410" + "libmono-system-runtime-durableinstancing4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libreoffice-help-sl": "1:4.2.3~rc3-0ubuntu1" + "ipvsadm": "1:1.26-2ubuntu1" + "libgail-3-0-dbg": "3.10.8-0ubuntu1" + "automake": "1:1.14.1-2ubuntu1" + "texlive-latex-recommended": "2013.20140215-1" + "ubuntu-keyring": "2012.05.19" + "gucharmap": "1:3.10.1-0ubuntu2" + "linux-source-3.13.0": "3.13.0-24.46" + "x11proto-xf86vidmode-dev": "2.3.1-2" + "python3-dbus": "1.2.0-2build2" + "libreoffice-help-en-gb": "1:4.2.3~rc3-0ubuntu1" + "libreoffice-l10n-ug": "1:4.2.3~rc3-0ubuntu1" + "libatomic1-dbg": "4.8.2-19ubuntu1" + "libavahi-gobject0": "0.6.31-4ubuntu1" + "nut-client": "2.7.1-1ubuntu1" + "language-pack-gnome-uk-base": "1:14.04+20140410" + "libijs-dev": "0.35-8build1" + "libvoikko-dev": "3.7-2ubuntu2" + "linux-signed-generic-lts-saucy": "3.13.0.24.28" + "xinput": "1.6.1-1" + "language-pack-bo": "1:14.04+20140410" + "language-pack-bs": "1:14.04+20140410" + "libpam0g-dev": "1.1.8-1ubuntu2" + "libwebkitgtk-1.0-0": "2.4.0-1ubuntu2" + "phonon-dbg": "4:4.7.1-0ubuntu8" + "asciidoc": "8.6.9-2ubuntu1" + "libjarjar-java-doc": "1.4+svn142-3" + "python-txamqp": "0.6.1-0ubuntu2" + "libsoprano-dev": "2.9.4+dfsg1-0ubuntu2" + "thunderbird-globalmenu": "1:24.4.0+build1-0ubuntu1" + "lsb-core": "4.1+Debian11ubuntu6" + "xserver-xorg-video-mach64": "6.9.4-1build1" + "libfile-sharedir-projectdistdir-perl": "0.5.2-1" + "libkidletime4": "4:4.13.0-0ubuntu1" + "libxft-dev": "2.3.1-2" + "dmidecode": "2.12-2" + "ed": "1.9-2" + "libhunspell-1.3-0-dbg": "1.3.2-6ubuntu2" + "libxxf86dga1-dbg": "2:1.1.4-1" + "libparted0debian1-dbg": "2.3-19ubuntu1" + "libdom4j-java": "1.6.1+dfsg.3-2ubuntu1" + "libtimedate-perl": "2.3000-1" + "djvulibre-dbg": "3.5.25.4-3" + "gir1.2-vte-2.90": "1:0.34.9-1ubuntu1" + "liborbit2": "1:2.14.19-0.3" + "language-pack-cy": "1:14.04+20140410" + "at-spi2-core-dbg": "2.10.2.is.2.10.1-0ubuntu1" + "libgtk-vnc-2.0-0-dbg": "0.5.3-0ubuntu2" + "thunderbird-locale-rm": "1:24.4.0+build1-0ubuntu1" + "yelp-tools": "3.10.0-1" + "libgles1-mesa-lts-raring-dbg": "3:5" + "libgstreamer-plugins-base0.10-dev": "0.10.36-1.1ubuntu2" + "libcarp-clan-perl": "6.04-1" + "firefox-locale-nl": "28.0+build2-0ubuntu2" + "libnm-glib-vpn1": "0.9.8.8-0ubuntu7" + "cvs": "2:1.12.13+real-12" + "libxcb-xkb1-dbg": "1.10-2ubuntu1" + "python3-gi-dbg": "3.12.0-1" + "xserver-xorg-video-ati-lts-raring": "3:5" + "libappconfig-perl": "1.66-1" + "libssl-doc": "1.0.1f-1ubuntu2.4" + "libavc1394-dev": "0.5.4-2" + "libglade2-0": "1:2.6.4-2" + "python3-pyqt5.qtx11extras-dbg": "5.2.1+dfsg-1ubuntu1" + "libupsclient-dev": "2.7.1-1ubuntu1" + "language-pack-gnome-sa": "1:14.04+20140410" + "icedtea-netx": "1.5-1ubuntu1" + "libcanberra-gtk-module": "0.30-0ubuntu3" + "qemu-system-sparc": "2.0.0~rc1+dfsg-0ubuntu3" + "dpatch": "2.0.35" + "libunity-misc-doc": "4.0.5+14.04.20140115-0ubuntu1" + "software-properties-common": "0.92.36" + "gnome-pkg-tools": "0.19.3ubuntu2" + "libgtk2.0-common": "2.24.23-0ubuntu1" + "libsqlite3-0": "3.8.2-1ubuntu2" + "libxcb-xvmc0-dev": "1.10-2ubuntu1" + "python3-lxc": "1.0.4-0ubuntu0.1" + "libcommons-net2-java-doc": "2.2-2" + "libglamor-dev": "0.6.0-0ubuntu4" + "libsub-identify-perl": "0.04-1build3" + "php5-gd": "5.5.9+dfsg-1ubuntu4" + "firefox-locale-fy": "28.0+build2-0ubuntu2" + "language-pack-ku": "1:14.04+20140410" + "nova-network": "1:2014.1-0ubuntu1" + "xserver-xorg-video-nouveau": "1:1.0.10-1ubuntu2" + "librsvg2-doc": "2.40.2-1" + "libtest-exception-perl": "0.32-1" + "libjavascript-minifier-xs-perl": "0.09-2build1" + "python-lxml": "3.3.3-1ubuntu0.1" + "language-pack-fy": "1:14.04+20140410" + "libgpgme11-dev": "1.4.3-0.1ubuntu5" + "libopencc-dbg": "0.4.3-2build1" + "python-celery-doc": "3.1.6-1ubuntu1" + "python-lazr.uri": "1.0.3-1build1" + "libpython-all-dev": "2.7.5-5ubuntu3" + "tcpdump": "4.5.1-2ubuntu1" + "gimp-help-ko": "2.6.1-1" + "dmraid": "1.0.0.rc16-4.2ubuntu3" + "firefox-locale-it": "28.0+build2-0ubuntu2" + "gir1.2-gee-1.0": "0.6.8-1ubuntu1" + "libgfortran-4.8-dev": "4.8.2-19ubuntu1" + "libreoffice-help-el": "1:4.2.3~rc3-0ubuntu1" + "python-pecan": "0.3.0-1ubuntu2" + "execstack": "0.0.20090925-8" + "libmeanwhile1": "1.0.2-4.1ubuntu1" + "libobjc4": "4.8.2-19ubuntu1" + "language-pack-gnome-tl-base": "1:14.04+20140410" + "myspell-lt": "1.2.1-4" + "gnome-contacts": "3.8.3-1ubuntu1" + "nvidia-settings-313-updates": "331.20-0ubuntu8" + "python3-gdbm-dbg": "3.4.0-0ubuntu1" + "libatk1.0-doc": "2.10.0-2ubuntu2" + "busybox-static": "1:1.21.0-1ubuntu1" + "libpoppler-glib-dev": "0.24.5-2ubuntu4" + "libxml-libxml-perl": "2.0108+dfsg-1" + "libreoffice-l10n-ve": "1:4.2.3~rc3-0ubuntu1" + "update-manager": "1:0.196.11" + "language-pack-zu": "1:14.04+20140410" + "gir1.2-brasero-3.0": "3.10.0-0ubuntu1" + "libtiff5-alt-dev": "4.0.3-7" + "xserver-xorg-video-s3": "1:0.6.5-0ubuntu4" + "libjmock-java": "1.2.0-2" + "libdaemon0-dbg": "0.14-2ubuntu1" + "libdbus-glib-1-2-dbg": "0.100.2-1" + "libxt-dev": "1:1.1.4-1" + "telepathy-mission-control-5-dbg": "1:5.16.1-1ubuntu3" + "valac": "0.22.1-0ubuntu1" + "mesa-vdpau-drivers": "10.1.0-4ubuntu5" + "python3-pycurl": "7.19.3-0ubuntu3" + "python-libxslt1": "1.1.28-2build1" + "x11-apps": "7.7+2" + "libmono-system-data-linq4.0-cil": "3.2.8+dfsg-4ubuntu1" + "unity-scope-calculator": "0.1+14.04.20140328-0ubuntu1" + "libfltk1.1": "1.1.10-17" + "libpcsclite-dev": "1.8.10-1ubuntu1" + "librsync-dev": "0.9.7-10" + "language-pack-lg": "1:14.04+20140410" + "grub-pc-dbg": "2.02~beta2-9" + "ncurses-term": "5.9+20140118-1ubuntu1" + "diffstat": "1.58-1" + "libdee-dev": "1.2.7+14.04.20140324-0ubuntu1" + "libxdamage-dev": "1:1.1.4-1ubuntu1" + "aisleriot": "1:3.10.2-1" + "dbus": "1.6.18-0ubuntu4.1" + "libparse-pidl-perl": "2:4.1.6+dfsg-1ubuntu2" + "ibus-table-wubi": "1.4.6-Source-1" + "python3-pep8": "1.4.6-1.1build1" + "libfftw3-quad3": "3.3.3-7ubuntu3" + "librdmacm-dev": "1.0.16-1" + "language-pack-ti": "1:14.04+20140410" + "linux-tools-common": "3.13.0-24.46" + "libmagickwand-dev": "8:6.7.7.10-6ubuntu3" + "python-talloc": "2.1.0-1" + "strongswan-plugin-openssl": "5.1.2-0ubuntu2" + "language-pack-gnome-af-base": "1:14.04+20140410" + "libcommons-cli-java": "1.2-3ubuntu1" + "libebook-1.2-14": "3.10.4-0ubuntu1" + "light-themes": "14.04+14.04.20140410-0ubuntu1" + "python-gdbm": "2.7.5-1ubuntu1" + "language-pack-so-base": "1:13.04+20130418" + "python-dbus-dbg": "1.2.0-2build2" + "python-cairo-dbg": "1.8.8-1ubuntu5" + "qtpim5-dbg": "5.0~git20140203~e0c5eebe-0ubuntu2" + "neutron-metadata-agent": "1:2014.1-0ubuntu1" + "libdlm-dev": "4.0.1-0ubuntu1" + "libdmapsharing-3.0-2": "2.9.24-0ubuntu1" + "libvala-0.22-0-dbg": "0.22.1-0ubuntu1" + "ocfs2-tools": "1.6.4-3ubuntu1" + "fonts-droid": "1:4.3-3ubuntu1" + "cups-bsd": "1.7.2-0ubuntu1" + "libneon27-dev": "0.30.0-1ubuntu1" + "python3-apparmor": "2.8.95~2430-0ubuntu5" + "libnewt-pic": "0.52.15-2ubuntu5" + "libgles1-mesa-dev-lts-raring": "3:5" + "libxatracker-dev-lts-quantal": "3:5" + "thunderbird-dev": "1:24.4.0+build1-0ubuntu1" + "twm": "1:1.0.6-1ubuntu1" + "xserver-xorg-video-mach64-lts-raring-dbg": "3:5" + "check": "0.9.10-6ubuntu3" + "erlang-os-mon": "1:16.b.3-dfsg-1ubuntu2" + "libdaemon-dev": "0.14-2ubuntu1" + "python-gst0.10-dbg": "0.10.22-3ubuntu2" + "sudo": "1.8.9p5-1ubuntu1" + "libgcr-ui-3-1": "3.10.1-1" + "libgtk-3-doc": "3.10.8-0ubuntu1" + "libmono-system-dynamic4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libtest-spelling-perl": "0.19-2" + "fastjar": "2:0.98-5" + "libcurl3-nss": "7.35.0-1ubuntu2" + "language-pack-gnome-fil": "1:14.04+20140410" + "libpoppler-glib-doc": "0.24.5-2ubuntu4" + "libgnome-keyring-dev": "3.8.0-2" + "libvorbis-dbg": "1.3.2-1.3ubuntu1" + "vbetool": "1.1-3" + "nova-api": "1:2014.1-0ubuntu1" + "libboost-iostreams1.54-dev": "1.54.0-4ubuntu3" + "libmhash2": "0.9.9.9-4" + "xserver-xorg-video-fbdev": "1:0.4.4-1build1" + "language-pack-gnome-az-base": "1:14.04+20140410" + "language-pack-gnome-de-base": "1:14.04+20140410" + "ruby": "1:1.9.3.4" + "librest-extras-dev": "0.7.90-0ubuntu1" + "libc-ares-dev": "1.10.0-2" + "python-psycopg2-dbg": "2.4.5-1build5" + "libjargs-java-doc": "1.0.0-4" + "libc-bin": "2.19-0ubuntu6" + "libsunpinyin3": "2.0.3+git20130507-1ubuntu1" + "srvadmin-storage": "7.1.0-2" + "ttf-ubuntu-font-family": "0.80-0ubuntu6" + "kdoctools": "4:4.13.0-0ubuntu1" + "libice-dev": "2:1.0.8-2" + "libpq5": "9.3.4-1" + "python3-icu": "1.5-2ubuntu4" + "libantlr-java": "2.7.7+dfsg-5" + "libtag1-doc": "1.9.1-2" + "wportuguese": "20140102-1" + "libnuma1": "2.0.9~rc5-1ubuntu2" + "installation-report": "2.54ubuntu1" + "libbcel-java-doc": "5.2-9build1" + "libgo4-dbg": "4.8.2-19ubuntu1" + "libvirtodbc0": "6.1.6+repack-0ubuntu3" + "gnome-font-viewer": "3.8.0-1build1" + "liblpsolve55-dev": "5.5.0.13-7build1" + "fonts-farsiweb": "0.4.dfsg-12" + "makedev": "2.3.1-93ubuntu1" + "python-glanceclient": "1:0.12.0-0ubuntu1" + "activity-log-manager": "0.9.7-0ubuntu14" + "gfortran-multilib": "4:4.8.2-1ubuntu6" + "libpod-latex-perl": "0.61-1" + "python-keyring": "3.5-1" + "libwps-0.2-2": "0.2.9-2ubuntu1" + "libfarstream-0.2-doc": "0.2.3-1ubuntu2" + "dpkg": "1.17.5ubuntu5.3" + "libqt5printsupport5": "5.2.1+dfsg-1ubuntu14" + "openssh-server": "1:6.6p1-2ubuntu2" + "tk": "8.6.0+6ubuntu3" + "libmalaga7": "7.12-4.1ubuntu1" + "python3-pyqt5.qtxmlpatterns-dbg": "5.2.1+dfsg-1ubuntu1" + "libwpg-doc": "0.2.2-1ubuntu1" + "ttf-kannada-fonts": "1:0.5.14ubuntu1" + "grub-ieee1275-dbg": "2.02~beta2-9" + "hfsutils": "3.2.6-12ubuntu3" + "libapache2-mod-auth-pgsql": "2.0.3-6" + "libruby2.0": "2.0.0.484-1ubuntu2" + "libgnomevfs2-common": "1:2.24.4-1ubuntu6" + "libzeitgeist-1.0-1-dbg": "0.3.18-1ubuntu2" + "libslp-dev": "1.2.1-9" + "libtinfo5": "5.9+20140118-1ubuntu1" + "libx32gfortran3": "4.8.2-19ubuntu1" + "language-pack-pl": "1:14.04+20140410" + "libemail-valid-perl": "1.192-1" + "python-jsonrpclib": "0.1.3-1build1" + "libpam-p11": "0.1.5-3ubuntu1" + "sane-utils": "1.0.23-3ubuntu3" + "libpar-dist-perl": "0.49-2" + "libyajl-doc": "2.0.4-4" + "ceph": "0.79-0ubuntu1" + "libconfig-dev": "1.4.9-2" + "libenchant-dev": "1.6.0-10ubuntu1" + "libmono-system-design4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libmono-system-identitymodel-selectors4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libaccount-plugin-1.0-0": "0.1.7~+14.04.20140211.2-0ubuntu4" + "libqt5organizer5": "5.0~git20140203~e0c5eebe-0ubuntu2" + "kdelibs5-data": "4:4.13.0-0ubuntu1" + "libglib2.0-doc": "2.40.0-2" + "libadns1-dev": "1.4-2ubuntu1" + "qtdeclarative5-private-dev": "5.2.1-3ubuntu15" + "unity-settings-daemon": "14.04.0+14.04.20140414-0ubuntu1" + "libasound2-plugins": "1.0.27-2ubuntu2" + "cloud-init": "0.7.5-0ubuntu1" + "fonts-sil-scheherazade": "1.001-8" + "language-pack-lo": "1:14.04+20140410" + "libcorosync4": "2.3.3-1ubuntu1" + "unity-2d-dbg": "7.2.0+14.04.20140416-0ubuntu1" + "libnunit-cil-dev": "2.6.0.12051+dfsg-2" + "po4a": "0.45-1" + "isc-dhcp-dev": "4.2.4-7ubuntu12" + "qtdeclarative5-xmllistmodel-plugin": "5.2.1-3ubuntu15" + "wodim": "9:1.1.11-2ubuntu3" + "emacs24-common-non-dfsg": "24.3+1-1" + "neutron-server": "1:2014.1-0ubuntu1" + "libgbm1-lts-saucy-dbg": "3:5" + "libmultidimensional-perl": "0.010-1build1" + "libogg-dev": "1.3.1-1ubuntu1" + "python3-testresources": "0.2.7-1ubuntu2" + "cgmanager": "0.24-0ubuntu5" + "libini-config3": "0.3.0.1-4" + "libjack-jackd2-dev": "1.9.9.5+20130622git7de15e7a-1ubuntu1" + "python3-pyqt5.qtx11extras": "5.2.1+dfsg-1ubuntu1" + "libjstl1.1-java": "1.1.2-2ubuntu1" + "libunity-gtk-parser-dev-common": "0.0.0+14.04.20140403-0ubuntu1" + "python-commandnotfound": "0.3ubuntu12" + "libisofs-dev": "1.3.4-0ubuntu1" + "xserver-xorg-video-nouveau-dbg": "1:1.0.10-1ubuntu2" + "euca2ools": "3.0.2-1ubuntu1" + "libfreeradius2": "2.1.12+dfsg-1.2ubuntu8" + "librelp-dev": "1.2.2-2ubuntu1" + "libbatik-java": "1.7.ubuntu-8ubuntu2" + "libaccountsservice-dbg": "0.6.35-0ubuntu7" + "libclutter-gtk-1.0-0": "1.4.4-3ubuntu2" + "byobu": "5.77-0ubuntu1" + "language-pack-el": "1:14.04+20140410" + "libreoffice-l10n-fa": "1:4.2.3~rc3-0ubuntu1" + "libcrmcluster4": "1.1.10+git20130802-1ubuntu2" + "unity-gtk2-module": "0.0.0+14.04.20140403-0ubuntu1" + "language-pack-pt-base": "1:14.04+20140410" + "blt-dev": "2.4z-7ubuntu2" + "gir1.2-gtkspell3-3.0": "3.0.4-1" + "lib32gcc1": "1:4.9-20140406-0ubuntu1" + "linux-image-extra-3.13.0-32-generic": "3.13.0-32.57" + "qtwebkit5-doc": "5.1.1-1ubuntu8" + "evolution-data-server-doc": "3.10.4-0ubuntu1" + "leveldb-doc": "1.15.0-2" + "libbsf-java-doc": "1:2.4.0-5build1" + "libharfbuzz-doc": "0.9.27-1" + "python-passlib": "1.5.3-0ubuntu3" + "liblqr-1-0-dbg": "0.4.1-2ubuntu1" + "xserver-xorg-video-savage-lts-saucy": "3:5" + "language-pack-mk": "1:14.04+20140410" + "language-pack-tk-base": "1:14.04+20140410" + "libgnome-menu-3-0-dbg": "3.10.1-0ubuntu2" + "libidl-dev": "0.8.14-0.2ubuntu4" + "libnice10": "0.1.4-1" + "language-pack-lg-base": "1:14.04+20140410" + "libglu1-mesa-dev": "9.0.0-2" + "python3-gi": "3.12.0-1" + "libmono-system-core4.0-cil": "3.2.8+dfsg-4ubuntu1" + "finch": "1:2.10.9-0ubuntu3" + "libsdl1.2debian": "1.2.15-8ubuntu1" + "libxcb-xtest0-dbg": "1.10-2ubuntu1" + "open-vm-tools-desktop": "2:9.4.0-1280544-5ubuntu6" + "gobi-loader": "0.7-0ubuntu2" + "libunity-control-center1": "14.04.3+14.04.20140410-0ubuntu1" + "signond-dev": "8.56+14.04.20140307-0ubuntu2" + "libipc-run-perl": "0.92-1" + "dvd+rw-tools-dbg": "7.1-10build1" + "libc-ares2": "1.10.0-2" + "libcanberra-pulse": "0.30-0ubuntu3" + "libfontenc-dev": "1:1.1.2-1" + "libegl1-mesa-lts-quantal-dbg": "3:5" + "libraw-dev": "0.15.4-1" + "xfonts-unifont": "1:6.3.20131221-1" + "duplicity": "0.6.23-1ubuntu4" + "libgl1-mesa-glx-lts-raring-dbg": "3:5" + "libnetpbm10": "2:10.0-15ubuntu2" + "php5-cli": "5.5.9+dfsg-1ubuntu4" + "debootstrap": "1.0.59" + "python-twisted-lore": "13.2.0-1ubuntu1" + "python-coverage-dbg": "3.7.1+dfsg.1-1ubuntu2" + "language-pack-zh-hant-base": "1:14.04+20140410" + "libconfig-dbg": "1.4.9-2" + "libsolid4": "4:4.13.0-0ubuntu1" + "qtdeclarative5-dialogs-plugin": "5.2.1-3ubuntu15" + "bcc": "0.16.17-3.1ubuntu3" + "libgnome-desktop-3-dev": "3.8.4-0ubuntu3" + "libsmokeqtnetwork4-3": "4:4.13.0-0ubuntu1" + "xserver-xorg-video-intel-lts-saucy-dbg": "3:5" + "libgnome-vfs2.0-cil": "2.24.2-3" + "python-simpletal": "4.1-7ubuntu1" + "tzdata": "2014b-1" + "openvswitch-common": "2.0.1+git20140120-0ubuntu2" + "geoip-database": "20140313-1" + "python-waitress": "0.8.8-1ubuntu3" + "libdotconf-dev": "1.3-0ubuntu2" + "python-gevent-doc": "1.0-1ubuntu1" + "libsm-dev": "2:1.2.1-2" + "erlang-doc": "1:16.b.3-dfsg-1ubuntu2" + "libreoffice-l10n-cy": "1:4.2.3~rc3-0ubuntu1" + "libpam-modules": "1.1.8-1ubuntu2" + "ttf-dejavu-core": "2.34-1ubuntu1" + "libdevel-declare-perl": "0.006015-1" + "libgo5": "4.9-20140406-0ubuntu1" + "libltdl7": "2.4.2-1.7ubuntu1" + "konwert-filters": "1.8-11.2build2" + "language-pack-gnome-eu": "1:14.04+20140410" + "python-bs4-doc": "4.2.1-1ubuntu2" + "qemu-keymaps": "2.0.0~rc1+dfsg-0ubuntu3" + "cup": "0.11a+20060608-3build1" + "lsb-invalid-mta": "4.1+Debian11ubuntu6" + "python-memcache": "1.53-1build1" + "libpaper-utils": "1.1.24+nmu2ubuntu3" + "mono-runtime-sgen": "3.2.8+dfsg-4ubuntu1" + "python3-speechd": "0.8-5ubuntu1" + "acpid": "1:2.0.21-1ubuntu2" + "libnice-dev": "0.1.4-1" + "malaga-bin": "7.12-4.1ubuntu1" + "jadetex": "3.13-14" + "gir1.2-udisks-2.0": "2.1.3-1" + "libdconf1": "0.20.0-1" + "libdecoration0-dev": "1:0.9.11+14.04.20140409-0ubuntu1" + "libnuma-dbg": "2.0.9~rc5-1ubuntu2" + "libdatetime-format-builder-perl": "0.8100-1" + "libidn11": "1.28-1ubuntu2" + "fonts-tlwg-kinnari": "1:0.5.1-3" + "xul-ext-ubufox": "2.8-0ubuntu1" + "gnome-mines": "1:3.10.1-0ubuntu1" + "libapr1": "1.5.0-1" + "libv4l-0": "1.0.1-1" + "linux-signed-generic-lts-trusty": "3.13.0.24.28" + "libalgorithm-c3-perl": "0.08-1" + "python-xmpp": "0.4.1-cvs20080505.3build1" + "wamerican-large": "7.1-1" + "libcss-minifier-xs-perl": "0.09-1" + "libmilter1.0.1": "8.14.4-4.1ubuntu1" + "libgd-graph-perl": "1.44-6" + "python-ceilometer": "2014.1-0ubuntu1" + "python-pyparsing": "2.0.1+dfsg1-1build1" + "libklu1.2.1": "1:4.2.1-3ubuntu1" + "language-pack-kn": "1:14.04+20140410" + "language-pack-nso-base": "1:14.04+20140410" + "mythes-ca": "1:4.2.1-0ubuntu1" + "lib32go4-dbg": "4.8.2-19ubuntu1" + "libdbustest1": "14.04.1+14.04.20140320-0ubuntu1" + "libjbig-dev": "2.0-2ubuntu4" + "libxcursor-dev": "1:1.1.14-1" + "python-egenix-mxbeebase": "3.2.7-1build1" + "libreoffice-l10n-gu": "1:4.2.3~rc3-0ubuntu1" + "maas-region-controller": "1.5+bzr2252-0ubuntu1" + "mythes-fr": "1:4.2.1-0ubuntu1" + "erlang-erl-docgen": "1:16.b.3-dfsg-1ubuntu2" + "libboost-filesystem-dev": "1.54.0.1ubuntu1" + "libcommons-net2-java": "2.2-2" + "libcdt5": "2.36.0-0ubuntu3" + "libclutter-1.0-dbg": "1.16.4-0ubuntu2" + "libcups2-dev": "1.7.2-0ubuntu1" + "tar": "1.27.1-1" + "language-pack-wo": "1:14.04+20140410" + "python-crypto-doc": "2.6.1-4build1" + "libreoffice-dev": "1:4.2.3~rc3-0ubuntu2" + "gir1.2-zeitgeist-2.0": "0.9.14-0ubuntu4" + "libunity-dev": "7.1.4+14.04.20140210-0ubuntu1" + "e2fsprogs": "1.42.9-3ubuntu1" + "libgnutls-dev": "2.12.23-12ubuntu2" + "libxatracker1-lts-quantal-dbg": "3:5" + "qtmultimedia5-examples": "5.2.1-0ubuntu5" + "srvadmin-jre": "7.1.0-3" + "libesd0": "0.2.41-11" + "python-apport": "2.14.1-0ubuntu3" + "python-aptdaemon": "1.1.1-1ubuntu5" + "libsnmp30-dbg": "5.7.2~dfsg-8.1ubuntu3" + "libspiro0": "20071029-8ubuntu1" + "libreoffice-l10n-bg": "1:4.2.3~rc3-0ubuntu1" + "libwps-doc": "0.2.9-2ubuntu1" + "python-cloudfiles": "1.7.11-2build1" + "fonts-tlwg-loma": "1:0.5.1-3" + "keystone": "1:2014.1-0ubuntu1" + "language-pack-bg-base": "1:14.04+20140410" + "language-pack-gnome-or": "1:14.04+20140410" + "libnm-gtk-common": "0.9.8.8-0ubuntu4" + "python3-pyqt5.qtserialport-dbg": "5.2.1+dfsg-1ubuntu1" + "unity-scope-clementine": "0.1+13.10.20130723-0ubuntu1" + "libgtkhtml-4.0-dbg": "4.6.6-2ubuntu1" + "libmpc3": "1.0.1-1ubuntu1" + "linux-cloud-tools-3.13.0-24-generic": "3.13.0-24.46" + "ltrace": "0.7.3-4ubuntu5" + "libdlmcontrol3": "4.0.1-0ubuntu1" + "libntdb-dev": "1.0-2ubuntu1" + "language-pack-lv": "1:14.04+20140410" + "irssi-dev": "0.8.15-5ubuntu3" + "libsctp-dev": "1.0.15+dfsg-1" + "webapp-container": "0.23+14.04.20140414-0ubuntu1" + "libpath-finddev-perl": "0.4.0-1" + "libdiscid0-dbg": "0.6.1-2" + "libotp0-heimdal": "1.6~git20131207+dfsg-1ubuntu1" + "libraptor2-dev": "2.0.13-1" + "libevview3-3": "3.10.3-0ubuntu10" + "libgvnc-1.0-dev": "0.5.3-0ubuntu2" + "libm17n-0": "1.6.4-2ubuntu1" + "libsignon-glib-dev": "1.10daily13.06.25-0ubuntu2" + "dbconfig-common": "1.8.47+nmu1" + "libnss-sss": "1.11.5-1ubuntu3" + "openhpid": "2.14.1-1.3ubuntu2" + "thunderbird-locale-uk": "1:24.4.0+build1-0ubuntu1" + "gtkmm-documentation": "3.8.0-1" + "grub-common": "2.02~beta2-9" + "libgnomevfs2-0": "1:2.24.4-1ubuntu6" + "libx32gcc-4.7-dev": "4.7.3-12ubuntu1" + "language-pack-el-base": "1:14.04+20140410" + "language-pack-gnome-et-base": "1:14.04+20140410" + "firefox-locale-is": "28.0+build2-0ubuntu2" + "libglib2.0-bin": "2.40.0-2" + "liblvm2-dev": "2.02.98-6ubuntu2" + "emacs24-el": "24.3+1-2ubuntu1" + "libstdc++6-arm64-cross": "4.8.2-13ubuntu1cross0.11" + "libdotconf0-dbg": "1.3-0ubuntu2" + "libgstreamer-plugins-base1.0-dev": "1.2.3-1" + "libsgutils2-dev": "1.36-1ubuntu1" + "libvala-0.22-0": "0.22.1-0ubuntu1" + "libsoprano-doc": "2.9.4+dfsg1-0ubuntu2" + "libtest-script-perl": "1.07-2" + "libyaml-perl": "0.84-1" + "python-imaging-dbg": "2.3.0-1ubuntu3" + "python-tornado": "3.1.1-1ubuntu2" + "gnupg-doc": "2003.04.06+dak1-1ubuntu1" + "libraw1394-tools": "2.1.0-1ubuntu1" + "upower": "0.9.23-2ubuntu1" + "libmpfr4": "3.1.2-1" + "libspice-server1": "0.12.4-0nocelt2" + "clamav-docs": "0.98.1+dfsg-4ubuntu1" + "wngerman": "20120607-1" + "libmtp9": "1.1.6-20-g1b9f164-1ubuntu2" + "libatk-adaptor-dbg": "2.10.2-2ubuntu1" + "libmetacity-dev": "1:2.34.13-0ubuntu4" + "lxc-templates": "1.0.4-0ubuntu0.1" + "hplip-data": "3.14.3-0ubuntu3" + "hyphen-zu": "1:4.2.1-0ubuntu1" + "libauthen-sasl-perl": "2.1500-1" + "python3-scripttest": "1.2-1build1" + "gir1.2-dbusmenu-gtk3-0.4": "12.10.3+14.04.20140319-0ubuntu1" + "libgcc-4.8-dev-powerpc-cross": "4.8.2-16ubuntu3cross0.11" + "python-yaml": "3.10-4build4" + "samba-dbg": "2:4.1.6+dfsg-1ubuntu2" + "language-pack-fo-base": "1:14.04+20140410" + "libattr1-dev": "1:2.4.47-1ubuntu1" + "libqt4-xml": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "qt3d5-examples": "5.0~git20130731-0ubuntu5" + "rfkill": "0.5-1ubuntu1" + "libopus0": "1.1-0ubuntu1" + "libshout3-dev": "2.3.1-3" + "libfile-homedir-perl": "1.00-1" + "x11proto-gl-dev": "1.4.17-1" + "gnome-control-center": "1:3.6.3-0ubuntu56" + "libexempi3": "2.2.1-1ubuntu1" + "libmilter1.0.1-dbg": "8.14.4-4.1ubuntu1" + "libx32gcc1": "1:4.9-20140406-0ubuntu1" + "x11proto-bigreqs-dev": "1:1.1.2-1" + "libfolks-telepathy-dev": "0.9.5-1ubuntu5" + "liblightdm-gobject-1-dev": "1.10.0-0ubuntu3" + "firefox-locale-he": "28.0+build2-0ubuntu2" + "libarchive13": "3.1.2-7ubuntu2" + "otf2bdf": "3.1-3" + "linux-headers-3.13.0-24-lowlatency": "3.13.0-24.46" + "pulseaudio-module-bluetooth-dbg": "1:4.0-0ubuntu11" + "libtasn1-3-bin": "3.4-3" + "libatspi2.0-dev": "2.10.2.is.2.10.1-0ubuntu1" + "libgladeui-2-6": "3.16.1-0ubuntu2" + "libllvm3.4-dbg": "1:3.4-1ubuntu3" + "libpe-rules2": "1.1.10+git20130802-1ubuntu2" + "libclass-method-modifiers-perl": "2.09-1" + "python-convoy": "0.2.1+bzr20-0ubuntu2" + "python-avahi": "0.6.31-4ubuntu1" + "signond": "8.56+14.04.20140307-0ubuntu2" + "libproxy1-plugin-gsettings": "0.4.11-0ubuntu4" + "libudev1": "204-5ubuntu20" + "libuuid1": "2.20.1-5.1ubuntu20.1" + "strongswan-plugin-eap-ttls": "5.1.2-0ubuntu2" + "mono-gmcs": "3.2.8+dfsg-4ubuntu1" + "libgtkhtml-editor-4.0-0": "4.6.6-2ubuntu1" + "libwavpack1": "4.70.0-1" + "language-pack-ky-base": "1:14.04+20140410" + "openobex-apps": "1.5-2.1" + "python3.4": "3.4.0-2ubuntu1" + "python3.4-minimal": "3.4.0-2ubuntu1" + "libpoppler-qt5-dev": "0.24.5-2ubuntu4" + "fonts-dejavu-core": "2.34-1ubuntu1" + "libgomp1-ppc64el-cross": "4.8.2-16ubuntu4cross0.4" + "python-migrate": "0.8.2-3ubuntu1" + "libirman-dev": "0.4.4-2build3" + "libjpeg8-dbg": "8c-2ubuntu8" + "libqtcore4": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "libzephyr-dev": "3.1.2-1" + "db-util": "1:5.3.21~exp1ubuntu1" + "liblightdm-gobject-1-doc": "1.10.0-0ubuntu3" + "libfuse-dev": "2.9.2-4ubuntu4" + "libgpod-nogtk-dev": "0.8.3-4ubuntu3" + "libpython3-all-dbg": "3.4.0-0ubuntu2" + "firefox-locale-hi": "28.0+build2-0ubuntu2" + "python-pisock-dbg": "0.12.5-6ubuntu2" + "fontforge-common": "20120731.b-5" + "libinline-files-perl": "0.68-1" + "gir1.2-friends-0.1": "0.1.2+14.04.20131108.1-0ubuntu1" + "libisoburn1": "1.3.2-1ubuntu1" + "ltsp-client-core": "5.5.1-1ubuntu2" + "lib32itm1-dbg": "4.8.2-19ubuntu1" + "ubiquity-frontend-debconf": "2.18.7" + "libc6-dev-ppc64-powerpc-cross": "2.19-0ubuntu2cross1.1" + "python-mutagen-doc": "1.22-1ubuntu2" + "liblist-moreutils-perl": "0.33-1build3" + "libpam-mount": "2.14-1" + "libpython-dbg": "2.7.5-5ubuntu3" + "qtscript5-dbg": "5.2.1+dfsg-1ubuntu1" + "neutron-l3-agent": "1:2014.1-0ubuntu1" + "remmina-common": "1.0.0-4ubuntu3" + "libxrender-dev": "1:0.9.8-1" + "python-pyvorbis-dbg": "1.5-2ubuntu2" + "python-dns": "2.3.6-3" + "libgnome2-0": "2.32.1-4ubuntu1" + "liboxideqt-qmlplugin": "1.0.0~bzr501-0ubuntu1" + "python-xdg": "0.25-4" + "faketime": "0.9.5-2" + "gvfs-fuse": "1.20.1-1ubuntu1" + "python-twisted-bin": "13.2.0-1ubuntu1" + "docbook-utils": "0.6.14-3ubuntu1" + "libmono-security4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libreoffice-l10n-eo": "1:4.2.3~rc3-0ubuntu1" + "libcairomm-1.0-dev": "1.10.0-1ubuntu3" + "libjdom1-java-doc": "1.1.3-1" + "apache2-mpm-prefork": "2.4.7-1ubuntu4" + "libncurses5-dbg": "5.9+20140118-1ubuntu1" + "qtbase5-dev-tools-dbg": "5.2.1+dfsg-1ubuntu14" + "thunderbird-locale-el": "1:24.4.0+build1-0ubuntu1" + "libjavascriptcoregtk-3.0-0": "2.4.0-1ubuntu2" + "libopencc1": "0.4.3-2build1" + "libselinux1-dev": "2.2.2-1" + "fonts-ukij-uyghur": "20110217-3" + "language-pack-gnome-be": "1:14.04+20140410" + "language-pack-ig-base": "1:14.04+20140410" + "paramiko-doc": "1.10.1-1git1build1" + "empathy": "3.8.6-0ubuntu9" + "libunity-core-6.0-dev": "7.2.0+14.04.20140416-0ubuntu1" + "libvdpau-dev": "0.7-1" + "python-heat": "2014.1-0ubuntu1" + "firefox-locale-fi": "28.0+build2-0ubuntu2" + "python-svn": "1.7.8-0.2" + "language-pack-gnome-kn": "1:14.04+20140410" + "python-amqplib-doc": "1.0.2-1" + "brasero-cdrkit": "3.10.0-0ubuntu1" + "indicator-keyboard": "0.0.0+14.04.20140410.1-0ubuntu1" + "libgnome2.0-cil-dev": "2.24.2-3" + "language-pack-ro-base": "1:14.04+20140410" + "libcppunit-doc": "1.13.1-2ubuntu1" + "yapps2-runtime": "2.1.1-17.2ubuntu1" + "libotf0-dbg": "0.9.13-1ubuntu1" + "python-m2crypto": "0.21.1-3ubuntu5" + "gimp-help-es": "2.6.1-1" + "cmake": "2.8.12.2-0ubuntu3" + "language-pack-gnome-da": "1:14.04+20140410" + "dovecot-core": "1:2.2.9-1ubuntu2" + "libqt4-private-dev": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "xserver-xorg-video-sisusb": "1:0.9.6-2build1" + "language-pack-gnome-shs-base": "1:14.04+20140410" + "libmono-system4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libptexenc1": "2013.20130729.30972-2build3" + "libqtwebkit4": "2.3.2-0ubuntu7" + "memtest86+": "4.20-1.1ubuntu8" + "libeval-closure-perl": "0.11-1" + "libmono-system-web-mvc2.0-cil": "3.2.8+dfsg-4ubuntu1" + "ttf-devanagari-fonts": "1:0.5.14ubuntu1" + "opencryptoki": "2.3.1+dfsg-3ubuntu5" + "language-pack-bem-base": "1:14.04+20140410" + "language-pack-gnome-sc": "1:14.04+20140410" + "language-pack-gnome-se-base": "1:14.04+20140410" + "libtest-strict-perl": "0.22-1" + "ruby-shoulda-context": "1.1.2-1" + "language-pack-nds": "1:14.04+20140410" + "libxorg-gtest-data": "0.7.1-0ubuntu1" + "libreadline6-dbg": "6.3-4ubuntu2" + "xbitmaps": "1.1.1-2" + "grub-common": "2.02~beta2-9ubuntu1" + "libosmesa6": "10.1.0-4ubuntu5" + "libpixman-1-0-dbg": "0.30.2-2ubuntu1" + "multiarch-support": "2.19-0ubuntu6" + "python-talloc-dbg": "2.1.0-1" + "libisoburn-doc": "1.3.2-1ubuntu1" + "myspell-eo": "2.1.2000.02.25-45" + "python-novaclient": "1:2.17.0-0ubuntu1" + "libquadmath0": "4.8.2-19ubuntu1" + "python-cups": "1.9.66-0ubuntu2" + "language-pack-gnome-ig": "1:14.04+20140410" + "libmono-rabbitmq2.0-cil": "3.2.8+dfsg-4ubuntu1" + "libjte1": "1.19-2" + "libqt4-designer": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "remmina": "1.0.0-4ubuntu3" + "libcurl4-doc": "7.35.0-1ubuntu2" + "libgnomekbd-common": "3.6.0-0ubuntu2" + "libdee-1.0-4-dbg": "1.2.7+14.04.20140324-0ubuntu1" + "libdevmapper-event1.02.1": "2:1.02.77-6ubuntu2" + "apparmor-easyprof": "2.8.95~2430-0ubuntu5" + "language-pack-gnome-sr-base": "1:14.04+20140410" + "libtemplate-perl-doc": "2.24-1.1" + "libgl1-mesa-dev-lts-saucy": "3:5" + "ibus-chewing": "1.4.10.1-1" + "dict-jargon": "4.4.7-2ubuntu1" + "linux-signed-generic-lts-quantal": "3.13.0.24.28" + "doxygen-doc": "1.8.6-2" + "libgles2-mesa-dev-lts-saucy": "3:5" + "libgtk2.0-cil-dev": "2.12.10-5" + "sed": "4.2.2-4ubuntu1" + "transmission-cli": "2.82-1.1ubuntu3" + "language-pack-mn": "1:14.04+20140410" + "dmidecode-dbg": "2.12-2" + "libqt5webkit5-qmlwebkitplugin": "5.1.1-1ubuntu8" + "libtevent0-dbg": "0.9.19-1" + "ifupdown": "0.7.47.2ubuntu4.1" + "srvadmin-idrac-ivmcli": "7.1.0-2" + "krb5-config": "2.3" + "language-pack-gnome-te": "1:14.04+20140410" + "language-pack-zu-base": "1:14.04+20140410" + "gcc-4.7-plugin-dev": "4.7.3-12ubuntu1" + "libglapi-mesa-lts-saucy": "3:5" + "grub-ieee1275": "2.02~beta2-9" + "libgupnp-1.0-dev": "0.20.10-1ubuntu1" + "php5-readline": "5.5.9+dfsg-1ubuntu4" + "libgoogle-perftools-dev": "2.1-2ubuntu1" + "libvariable-magic-perl": "0.53-1" + "libp11-dev": "0.2.8-3ubuntu1" + "python-sip-dev": "4.15.5-1build1" + "libgmp10-doc": "2:5.1.3+dfsg-1ubuntu1" + "bsdmainutils": "9.0.5ubuntu1" + "gir1.2-gcr-3": "3.10.1-1" + "libc6-prof": "2.19-0ubuntu6" + "libfarstream-0.1-dev": "0.1.2-1ubuntu3" + "libsaxon-java": "1:6.5.5-10" + "myspell-pl": "20130519-1" + "python3-crypto-dbg": "2.6.1-4build1" + "libheimntlm0-heimdal": "1.6~git20131207+dfsg-1ubuntu1" + "linux-image-3.13.0-24-lowlatency": "3.13.0-24.46" + "openjade": "1.4devel1-21" + "libconfig-doc": "1.4.9-2" + "powernap-common": "2.18-0ubuntu2" + "qt4-doc": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "ceph-common-dbg": "0.79-0ubuntu1" + "gconf2": "3.2.6-0ubuntu2" + "xserver-xorg-video-mach64-lts-raring": "3:5" + "libgl1-mesa-glx-lts-quantal-dbg": "3:5" + "libqt5multimedia5": "5.2.1-0ubuntu5" + "libsmokeqtcore4-3": "4:4.13.0-0ubuntu1" + "libreoffice-help-it": "1:4.2.3~rc3-0ubuntu1" + "libreoffice-l10n-as": "1:4.2.3~rc3-0ubuntu1" + "python-wsme": "0.6-0ubuntu1" + "dbus-1-dbg": "1.6.18-0ubuntu4" + "libfribidi-dev": "0.19.6-1" + "hyphen-sl": "1:4.2.1-0ubuntu1" + "neutron-common": "1:2014.1-0ubuntu1" + "firefox": "28.0+build2-0ubuntu2" + "ocaml-compiler-libs": "4.01.0-3ubuntu3" + "libx32stdc++6-4.7-dev": "4.7.3-12ubuntu1" + "libxkbfile1-dbg": "1:1.0.8-1" + "xserver-xorg-core-dbg": "2:1.15.1-0ubuntu2" + "libdatetime-format-mail-perl": "0.3001-2" + "nova-objectstore": "1:2014.1-0ubuntu1" + "hdparm-dbg": "9.43-1ubuntu3" + "librbd1-dbg": "0.79-0ubuntu1" + "srvadmin-deng": "7.1.0-3" + "libnet-http-perl": "6.06-1" + "libpackage-deprecationmanager-perl": "0.13-1" + "python-django-south": "0.7.5-1.1build1" + "libcephfs1": "0.79-0ubuntu1" + "libwmf0.2-7-gtk": "0.2.8.4-10.3ubuntu1" + "language-pack-gnome-ff-base": "1:14.04+20140410" + "libreoffice-l10n-hi": "1:4.2.3~rc3-0ubuntu1" + "libtext-wrapi18n-perl": "0.06-7" + "cramfsprogs": "1.1-6build4" + "libconfig++9": "1.4.9-2" + "libsub-exporter-perl": "0.986-1" + "libprocess-cpp-dev": "1.0.0+14.04.20140328-0ubuntu1" + "notification-daemon": "0.7.6-1" + "python3-pyqt4.phonon": "4.10.4+dfsg-1ubuntu1" + "dbus-1-doc": "1.6.18-0ubuntu4" + "libgutenprint2": "5.2.10~pre2-0ubuntu2" + "auth-client-config": "0.9ubuntu1" + "libfile-remove-perl": "1.52-1" + "logstash-contrib": "1.4.1-1-6e42745" + "unity-scope-gourmet": "0.1+13.10.20130723-0ubuntu1" + "libdconf-dbus-1-dev": "0.20.0-1" + "language-pack-ts-base": "1:14.04+20140410" + "libpython3.4-minimal": "3.4.0-2ubuntu1" + "libspeex-dev": "1.2~rc1.1-1ubuntu1" + "libwpd-0.9-9": "0.9.9-1" + "network-manager-dbg": "0.9.8.8-0ubuntu7" + "hyphen-gu": "0.7.0-2" + "libsubunit-perl": "0.0.18-0ubuntu7" + "libgimp2.0-dev": "2.8.10-0ubuntu1" + "libgnome-control-center-dev": "1:3.6.3-0ubuntu56" + "libgtk-3-common": "3.10.8-0ubuntu1" + "liblangtag-doc": "0.5.1-2" + "liborcus-dev": "0.5.1-7" + "libssh-dbg": "0.6.1-0ubuntu3" + "libgif-dev": "4.1.6-11" + "libglade2.0-cil-dev": "2.12.10-5" + "libproxy-dev": "0.4.11-0ubuntu4" + "vim-haproxy": "1.4.24-2" + "x11proto-dri2-dev": "2.8-2" + "click": "0.4.21.1" + "cpp-4.7": "4.7.3-12ubuntu1" + "ibus-hangul": "1.4.2-3" + "libx11-6-dbg": "2:1.6.2-1ubuntu2" + "openjdk-7-dbg": "7u51-2.4.6-1ubuntu4" + "plainbox-provider-resource-generic": "0.3-1" + "crossbuild-essential-arm64": "11.6ubuntu6" + "libpils2": "1.0.11+hg2754-1.1build1" + "lua5.2-doc": "5.2.3-1" + "texlive-pictures": "2013.20140215-1" + "php-pear": "5.5.9+dfsg-1ubuntu4" + "python3-mimeparse": "0.1.4-1build1" + "parted-doc": "2.3-19ubuntu1" + "unity-scope-virtualbox": "0.1+13.10.20130723-0ubuntu1" + "lsb-release": "4.1+Debian11ubuntu6" + "libopenvg1-mesa-dbg": "10.1.0-4ubuntu5" + "librest-dev": "0.7.90-0ubuntu1" + "python-qt4-dbus-dbg": "4.10.4+dfsg-1ubuntu1" + "libtagc0": "1.9.1-2" + "libvotequorum-dev": "2.3.3-1ubuntu1" + "evolution-common": "3.10.4-0ubuntu1" + "language-pack-gnome-nn-base": "1:14.04+20140410" + "texlive-font-utils": "2013.20140215-2" + "cython3-dbg": "0.20.1+git90-g0e6e38e-1ubuntu2" + "libgles1-mesa-lts-raring": "3:5" + "automake1.10": "1:1.10.3-3.1ubuntu1" + "gir1.2-langtag-0.5": "0.5.1-2" + "ibus-anthy": "1.5.4-2" + "libusbredirparser-dev": "0.6-2ubuntu1" + "libxshmfence-dev": "1.1-2" + "libgail-doc": "2.24.23-0ubuntu1" + "libalgorithm-diff-xs-perl": "0.04-2build4" + "libpulsedsp": "1:4.0-0ubuntu11" + "libreoffice-help-eu": "1:4.2.3~rc3-0ubuntu1" + "bacula-common": "5.2.6+dfsg-9.1ubuntu3" + "gir1.2-gladeui-2.0": "3.16.1-0ubuntu2" + "libhangul1-dbg": "0.1.0-3" + "libxenstore3.0": "4.4.0-0ubuntu5" + "libencode-locale-perl": "1.03-1" + "gcc-4.8-powerpc-linux-gnu": "4.8.2-16ubuntu3cross0.11" + "libespeak-dev": "1.47.11-1ubuntu1" + "nvidia-settings-304-updates": "331.20-0ubuntu8" + "scons": "2.3.0-2" + "libbogl-dev": "0.1.18-9ubuntu1" + "nvidia-settings-304": "331.20-0ubuntu8" + "libsunpinyin3-dbg": "2.0.3+git20130507-1ubuntu1" + "libwmf-dev": "0.2.8.4-10.3ubuntu1" + "gstreamer1.0-nice": "0.1.4-1" + "libwayland-dev": "1.4.0-1ubuntu1" + "strongswan-plugin-eap-tls": "5.1.2-0ubuntu2" + "gtk3-engines-unico": "1.0.3+14.04.20140109-0ubuntu1" + "libdrm-radeon1-dbg": "2.4.52-1" + "libgl1-mesa-dri-dbg": "10.1.0-4ubuntu5" + "libp11-kit0-dbg": "0.20.2-2ubuntu2" + "unixodbc": "2.2.14p2-5ubuntu5" + "gfortran-4.7-doc": "4.7.3-12ubuntu1" + "libfribidi0": "0.19.6-1" + "libtevent0": "0.9.19-1" + "python-egenix-mxuid": "3.2.7-1build1" + "python-pyrex": "0.9.8.5-2ubuntu3" + "rhino": "1.7R4-2" + "libpciaccess-dev": "0.13.2-1" + "qtmultimedia5-dbg": "5.2.1-0ubuntu5" + "language-pack-dz": "1:14.04+20140410" + "libmono-system-reactive-runtime-remoting2.2-cil": "3.2.8+dfsg-4ubuntu1" + "libbsd-dev": "0.6.0-2ubuntu1" + "libgomp1-dbg": "4.8.2-19ubuntu1" + "libmemcached-dbg": "1.0.8-1ubuntu2" + "dh-ocaml": "1.0.8" + "libssl-dev": "1.0.1f-1ubuntu2.4" + "python-pam-dbg": "0.4.2-13.1ubuntu3" + "libpod-spell-perl": "1.12-1" + "python-stevedore": "0.14.1-1" + "gir1.2-webkit2-3.0": "2.4.0-1ubuntu2" + "libexttextcat-2.0-0": "3.4.3-1ubuntu1" + "libx32objc-4.8-dev": "4.8.2-19ubuntu1" + "x11-xkb-utils": "7.7+1" + "bacula": "5.2.6+dfsg-9.1ubuntu3" + "language-pack-gnome-ps-base": "1:14.04+20140410" + "libjdepend-java": "2.9.1-1" + "libcups2": "1.7.2-0ubuntu1" + "libxdmcp6": "1:1.1.1-1" + "libxcb-damage0-dbg": "1.10-2ubuntu1" + "cpp-4.8-doc": "4.8.2-19ubuntu1" + "libmono-system-data2.0-cil": "3.2.8+dfsg-4ubuntu1" + "libmono-system-reactive-platformservices2.2-cil": "3.2.8+dfsg-4ubuntu1" + "freeradius-dbg": "2.1.12+dfsg-1.2ubuntu8" + "keyutils-dbg": "1.5.6-1" + "libijs-0.35": "0.35-8build1" + "libxss1-dbg": "1:1.2.2-1" + "python-dbus": "1.2.0-2build2" + "db5.3-doc": "5.3.28-3ubuntu3" + "aptitude": "0.6.8.2-1ubuntu4" + "bacula-console-dbg": "5.2.6+dfsg-9.1ubuntu3" + "gir1.2-gtop-2.0": "2.28.5-2" + "libasound2": "1.0.27.2-3ubuntu7" + "python-gd-dbg": "0.56+dfsg-4build1" + "qt4-dev-tools": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "firefox-locale-fr": "28.0+build2-0ubuntu2" + "libsamplerate0-dev": "0.1.8-7" + "python-scgi": "1.13-1.1build1" + "language-pack-gnome-ht-base": "1:14.04+20140410" + "python-pytest-doc": "2.5.1-1" + "qtxmlpatterns5-doc": "5.2.1-8build1" + "tex-common": "4.04" + "vim-runtime": "2:7.4.052-1ubuntu3" + "xserver-xorg-input-evdev-dev-lts-saucy": "3:5" + "fonts-arphic-bsmi00lp": "2.10-13" + "librdmacm1": "1.0.16-1" + "libmono-system-configuration-install4.0-cil": "3.2.8+dfsg-4ubuntu1" + "puppet": "3.4.3-1" + "libfile-rsyncp-perl": "0.70-1ubuntu3" + "libxcb-xprint0-dbg": "1.10-2ubuntu1" + "libmono-system-reactive-observable-aliases0.0-cil": "3.2.8+dfsg-4ubuntu1" + "libqca2-doc": "2.0.3-5" + "libvte-common": "1:0.28.2-5ubuntu1" + "libref-array1": "0.3.0.1-4" + "libx32gomp1": "4.8.2-19ubuntu1" + "language-pack-ml-base": "1:14.04+20140410" + "python3-paste": "1.7.5.1-6ubuntu3" + "libmspub-0.0-0": "0.0.6-1ubuntu2" + "libparted0-dev": "2.3-19ubuntu1" + "language-pack-wa-base": "1:14.04+20140410" + "libnunit-doc": "2.6.0.12051+dfsg-2" + "auditd": "1:2.3.2-2ubuntu1" + "ipxe": "1.0.0+git-20131111.c3d1e78-2ubuntu1" + "libgbm-dev": "10.1.0-4ubuntu5" + "slapd-dbg": "2.4.31-1+nmu2ubuntu8" + "sshpass": "1.05-1" + "libmono-accessibility2.0-cil": "3.2.8+dfsg-4ubuntu1" + "libmono-system-data4.0-cil": "3.2.8+dfsg-4ubuntu1" + "lib32gcc-4.8-dev": "4.8.2-19ubuntu1" + "libmng2": "2.0.2-0ubuntu3" + "libspe2-doc": "2.2.80-95-3.1ubuntu7" + "devhelp-common": "3.8.2-2ubuntu1" + "fonts-nanum-extra": "20131007-1" + "fonts-dejavu": "2.34-1ubuntu1" + "libipc-sharedcache-perl": "1.3-8" + "python-renderpm": "3.0-1build1" + "eog": "3.10.2-0ubuntu5" + "libprotobuf-dev": "2.5.0-9ubuntu1" + "libtextwrap-dev": "0.1-14" + "libxmuu1-dbg": "2:1.1.1-1" + "libexception-class-perl": "1.37-1" + "libraw1394-11": "2.1.0-1ubuntu1" + "x11proto-kb-dev": "1.0.6-2" + "libboost-serialization1.54-dev": "1.54.0-4ubuntu3" + "libsystemd-login0": "204-5ubuntu20" + "libtdb1-dbg": "1.2.12-1" + "libxatracker2": "10.1.0-4ubuntu5" + "ttf-wqy-zenhei": "0.9.45-5ubuntu1" + "guile-2.0": "2.0.9+1-1ubuntu1" + "libcwidget3": "0.5.16-3.5ubuntu1" + "poppler-utils": "0.24.5-2ubuntu4" + "python-epydoc": "3.0.1+dfsg-4" + "python-psycopg2-doc": "2.4.5-1build5" + "gir1.2-gusb-1.0": "0.1.6-5" + "libgoa-1.0-dev": "3.10.3-0ubuntu1" + "libwayland-egl1-mesa-dbg": "10.1.0-4ubuntu5" + "libxcb-image0-dev": "0.3.9-1ubuntu2" + "fonts-liberation": "1.07.3-3" + "python-twisted-mail": "13.2.0-1ubuntu1" + "python3-pyparsing": "2.0.1+dfsg1-1build1" + "libkunitconversion4": "4:4.13.0-0ubuntu1" + "libopenvg1-mesa-dev-lts-raring": "3:5" + "apparmor-profiles": "2.8.95~2430-0ubuntu5" + "tk8.6-dev": "8.6.1-3ubuntu2" + "expect-dev": "5.45-5ubuntu1" + "libdevmapper-dev": "2:1.02.77-6ubuntu2" + "liblxc1": "1.0.4-0ubuntu0.1" + "fonts-arphic-ukai": "0.2.20080216.2-4ubuntu2" + "libmm-glib0": "1.0.0-2ubuntu1" + "libnss-ldap": "264-2.2ubuntu4" + "libslang2": "2.2.4-15ubuntu1" + "python-egenix-mxdatetime": "3.2.7-1build1" + "gvfs-backends": "1.20.1-1ubuntu1" + "libenchant1c2a": "1.6.0-10ubuntu1" + "libgssrpc4": "1.12+dfsg-2ubuntu4" + "libraptor1-dbg": "1.4.21-10" + "linux-crashdump": "3.13.0.24.28" + "dict-vera": "1:1.20-1" + "libreoffice-l10n-ta": "1:4.2.3~rc3-0ubuntu1" + "libgeoip-dev": "1.6.0-1" + "libgusb-dev": "0.1.6-5" + "libyajl-dev": "2.0.4-4" + "libdee-1.0-4": "1.2.7+14.04.20140324-0ubuntu1" + "libfarstream-0.2-2": "0.2.3-1ubuntu2" + "libnux-4.0-0": "4.0.6+14.04.20140409-0ubuntu1" + "aspell-doc": "0.60.7~20110707-1ubuntu1" + "doc-base": "0.10.5" + "language-pack-gv-base": "1:14.04+20140410" + "libreoffice-l10n-rw": "1:4.2.3~rc3-0ubuntu1" + "xdiagnose": "3.6.3build2" + "subversion-tools": "1.8.8-1ubuntu3" + "libcurl4-nss-dev": "7.35.0-1ubuntu2" + "libntdb1-dbg": "1.0-2ubuntu1" + "python3-dbus.mainloop.pyqt5-dbg": "5.2.1+dfsg-1ubuntu1" + "thunderbird-locale-tr": "1:24.4.0+build1-0ubuntu1" + "hatop": "0.7.7-1" + "libmono-csharp4.0c-cil": "3.2.8+dfsg-4ubuntu1" + "libgeis1": "2.2.16+14.04.20140303-0ubuntu1" + "libx32itm1-dbg": "4.8.2-19ubuntu1" + "systemd-services": "204-5ubuntu20" + "libgail-3-0": "3.10.8-0ubuntu1" + "libibverbs1-dbg": "1.1.7-1ubuntu1" + "libubuntu-location-service-dev": "0.0.2+14.04.20140307-0ubuntu1" + "libx11-xcb1": "2:1.6.2-1ubuntu2" + "libwpg-dev": "0.2.2-1ubuntu1" + "xserver-xorg-video-siliconmotion-lts-quantal": "3:5" + "tipa": "2:1.3-19" + "ttf-gujarati-fonts": "1:0.5.14ubuntu1" + "libfs6-dbg": "2:1.0.5-1" + "libio-pty-perl": "1:1.08-1build4" + "libpath-utils1": "0.3.0.1-4" + "xserver-xorg-video-savage": "1:2.3.7-2ubuntu2" + "ifenslave-2.6": "2.4ubuntu1" + "qttools5-doc": "5.2.1-8build1" + "libneon27-gnutls-dbg": "0.30.0-1ubuntu1" + "libpolkit-qt-1-dev": "0.103.0-1ubuntu1" + "libxcursor1-dbg": "1:1.1.14-1" + "libauparse0": "1:2.3.2-2ubuntu1" + "libgtk2.0-cil": "2.12.10-5" + "libxapian22-dbg": "1.2.16-2ubuntu1" + "ruby-json": "1.8.0-1build1" + "libexiv2-doc": "0.23-1ubuntu2" + "cpp-powerpc-linux-gnu": "4:4.8.2-1" + "dc": "1.06.95-8ubuntu1" + "fonts-tlwg-umpush": "1:0.5.1-3" + "language-pack-gnome-sw": "1:14.04+20140410" + "language-pack-id-base": "1:14.04+20140410" + "mariadb-common": "5.5.38+maria-1~trusty" + "myspell-nl": "1:2.10-1" + "liblouis-data": "2.5.3-2ubuntu1" + "texlive-latex-extra-doc": "2013.20140215-2" + "libdbusmenu-jsonloader-dev": "12.10.3+14.04.20140319-0ubuntu1" + "aide-common": "0.16~a2.git20130520-2" + "ibus-table-erbi": "1.4.6-Source-1" + "language-pack-li": "1:14.04+20140410" + "libmysqlclient-dev": "5.5.35+dfsg-1ubuntu1" + "ltspfsd-core": "1.3-1" + "liboro-java": "2.0.8a-9" + "python-qt4-dev": "4.10.4+dfsg-1ubuntu1" + "libkpathsea6": "2013.20130729.30972-2build3" + "isc-dhcp-client": "4.2.4-7ubuntu12" + "libqtdbustest1-dev": "0.2+14.04.20140325-0ubuntu1" + "lvm2": "2.02.98-6ubuntu2" + "libgirepository1.0-doc": "1.40.0-1" + "syslinux-common": "3:4.05+dfsg-6+deb8u1" + "b43-fwcutter": "1:018-2" + "libhud-client2-dev": "13.10.1+14.04.20140402-0ubuntu1" + "libxcb-render0": "1.10-2ubuntu1" + "libgflags2": "2.0-1.1ubuntu1" + "xserver-xorg-input-evdev-dbg": "1:2.8.2-1ubuntu2" + "libqttest4-perl": "4:4.13.0-0ubuntu1" + "libupower-glib-dev": "0.9.23-2ubuntu1" + "language-pack-tr-base": "1:14.04+20140410" + "libreoffice-help-es": "1:4.2.3~rc3-0ubuntu1" + "python3-aptdaemon": "1.1.1-1ubuntu5" + "ibus-pinyin": "1.5.0-1ubuntu1" + "libpolkit-backend-1-0": "0.105-4ubuntu2" + "localechooser-data": "2.49ubuntu5" + "python-hp3parclient": "3.0.0-0ubuntu1" + "libgrail6": "3.1.0daily13.06.05-0ubuntu1" + "lxc-dev": "1.0.3-0ubuntu3" + "xserver-xorg-video-openchrome-lts-saucy-dbg": "3:5" + "language-pack-gnome-ps": "1:14.04+20140410" + "libmono-i18n-mideast4.0-cil": "3.2.8+dfsg-4ubuntu1" + "mono-gac": "3.2.8+dfsg-4ubuntu1" + "libgl1-mesa-dri-lts-saucy": "3:5" + "libipc-sharelite-perl": "0.17-3build1" + "python3-pyqt5.qtsvg": "5.2.1+dfsg-1ubuntu1" + "libatomic1-armhf-cross": "4.8.2-16ubuntu4cross0.11" + "libextutils-installpaths-perl": "0.010-1" + "python-testresources": "0.2.7-1ubuntu2" + "libgl1-mesa-glx-lts-saucy-dbg": "3:5" + "libmirplatformgraphics-mesa": "0.1.8+14.04.20140411-0ubuntu1" + "libpurple-bin": "1:2.10.9-0ubuntu3" + "python3-six": "1.5.2-1" + "libopenvg1-mesa-dev-lts-quantal": "3:5" + "python3-sip": "4.15.5-1build1" + "testrepository": "0.0.18-1ubuntu1" + "udev": "204-5ubuntu20" + "language-pack-gnome-dz": "1:14.04+20140410" + "rsyslog-doc": "7.4.4-1ubuntu2" + "twisted-doc": "13.2.0-1ubuntu1" + "libdb5.3-dev": "5.3.28-3ubuntu3" + "libedata-book1.2-dev": "3.10.4-0ubuntu1" + "language-pack-am": "1:14.04+20140410" + "python-six": "1.5.2-1" + "libwhoopsie-preferences-dev": "0.12" + "odbcinst1debian2": "2.2.14p2-5ubuntu5" + "libxcb-xf86dri0": "1.10-2ubuntu1" + "logrotate": "3.8.7-1ubuntu1" + "python-cairo": "1.8.8-1ubuntu5" + "language-pack-bs-base": "1:14.04+20140410" + "libmono-webmatrix-data4.0-cil": "3.2.8+dfsg-4ubuntu1" + "insserv": "1.14.0-5ubuntu2" + "libgbm1-lts-quantal": "3:5" + "libmysqlclient18": "5.5.35+dfsg-1ubuntu1" + "libkhtml5": "4:4.13.0-0ubuntu1" + "libopenvg1-mesa-lts-quantal-dbg": "3:5" + "libqt5scintilla2-11": "2.8.1-2" + "swig2.0": "2.0.11-1ubuntu2" + "gccgo-4.7-doc": "4.7.3-12ubuntu1" + "krb5-locales": "1.12+dfsg-2ubuntu4" + "language-pack-ber": "1:14.04+20140410" + "gfxboot": "4.5.1-3ubuntu1" + "libbabl-0.1-0-dbg": "0.1.10-1ubuntu2" + "libregexp-java": "1.5-3build1" + "libevent-core-2.0-5": "2.0.21-stable-1ubuntu1" + "libsqlite3-dev": "3.8.2-1ubuntu2" + "libpath-class-perl": "0.33-1" + "ruby-dev": "1:1.9.3.4" + "ubuntuone-client-data": "13.05-0ubuntu1" + "libp11-kit0": "0.20.2-2ubuntu2" + "libicu52": "52.1-3" + "libphonon-dev": "4:4.7.1-0ubuntu8" + "libppl-c4": "1:1.1-1ubuntu1" + "language-pack-os-base": "1:14.04+20140410" + "gnupg2": "2.0.22-3ubuntu1" + "gtk-im-libthai": "0.2.1-4ubuntu1" + "libavahi-qt4-1": "0.6.31-4ubuntu1" + "libgcrypt11-dbg": "1.5.3-2ubuntu4" + "mozvoikko": "2.0.1-0ubuntu1" + "neutron-plugin-linuxbridge": "1:2014.1-0ubuntu1" + "python3-pylibacl": "0.5.1-1.1build4" + "libmono-system-web-mvc1.0-cil": "3.2.8+dfsg-4ubuntu1" + "libreoffice-dev-doc": "1:4.2.3~rc3-0ubuntu2" + "libept-dev": "1.0.12" + "linux-image-3.13.0-32-generic": "3.13.0-32.57" + "linux-firmware": "1.127.5" + "libwmf0.2-7": "0.2.8.4-10.3ubuntu1" + "language-pack-hi-base": "1:14.04+20140410" + "sphinx-doc": "1.2.2+dfsg-1ubuntu1" + "libterm-size-perl": "0.207-1build1" + "linux-tools-lts-trusty": "3.13.0.24.28" + "libgstreamer0.10-dev": "0.10.36-1.2ubuntu3" + "thunderbird-locale-fr": "1:24.4.0+build1-0ubuntu1" + "grub-legacy-ec2": "0.7.5-0ubuntu1.1" + "libsfgomp1-armhf-cross": "4.8.2-16ubuntu4cross0.11" + "libxml-sax-base-perl": "1.07-1" + "python-nova": "1:2014.1-0ubuntu1" + "libx86-dbg": "1.1+ds1-10" + "postgresql-9.3-dbg": "9.3.4-1" + "python-gobject-2-dbg": "2.28.6-12build1" + "ure-dbg": "4.2.3~rc3-0ubuntu2" + "language-pack-wae-base": "1:14.04+20140410" + "libreoffice-l10n-nso": "1:4.2.3~rc3-0ubuntu1" + "printer-driver-sag-gdi": "0.1-3" + "e2fslibs-dev": "1.42.9-3ubuntu1" + "gnutls-bin": "3.0.11+really2.12.23-12ubuntu2" + "gcc-4.8-arm-linux-gnueabihf": "4.8.2-16ubuntu4cross0.11" + "libvala-0.18-0": "0.18.1-0ubuntu11" + "libreoffice-l10n-pa-in": "1:4.2.3~rc3-0ubuntu1" + "python-routes": "2.0-1build1" + "xfonts-base": "1:1.0.3" + "libgtk2.0-0-dbg": "2.24.23-0ubuntu1" + "linux-tools-generic-lts-saucy": "3.13.0.24.28" + "dejagnu": "1.5-3build1" + "ibus-table-yong": "1.4.6-Source-1" + "syslinux-themes-ubuntu-oneiric": "8" + "qtdeclarative5-dev-tools": "5.2.1-3ubuntu15" + "libqt5scintilla2-l10n": "2.8.1-2" + "bsdutils": "1:2.20.1-5.1ubuntu20.1" + "libjson-c2-dbg": "0.11-3ubuntu1" + "libnux-4.0-dev": "4.0.6+14.04.20140409-0ubuntu1" + "libqt5positioning5-plugins": "5.2.1-1ubuntu2" + "language-pack-gnome-ur-base": "1:14.04+20140410" + "lib32stdc++-4.8-dev": "4.8.2-19ubuntu1" + "libboost1.54-dbg": "1.54.0-4ubuntu3" + "libopencryptoki0": "2.3.1+dfsg-3ubuntu5" + "tmake": "1.8-1.1" + "zlib1g": "1:1.2.8.dfsg-1ubuntu1" + "linux-doc": "3.13.0-24.46" + "texlive-lang-german": "2013.20140215-1" + "gnupg": "1.4.16-1ubuntu2.1" + "libqtdbusmock1-dev": "0.2+14.04.20140304-0ubuntu1" + "sasl2-bin": "2.1.25.dfsg1-17build1" + "libcdparanoia-dev": "3.10.2+debian-11" + "libplatform-api1-doc": "0.20+14.04.20140411-0ubuntu1" + "libbonobo2-0": "2.32.1-0ubuntu5" + "strongswan-plugin-mysql": "5.1.2-0ubuntu2" + "libgdk-pixbuf2.0-common": "2.30.7-0ubuntu1" + "overlayroot": "0.25ubuntu1" + "cu": "1.07-20.1" + "erlang-webtool": "1:16.b.3-dfsg-1ubuntu2" + "libjson-xs-perl": "2.340-1build1" + "libthumbnailer-dev": "1.1+14.04.20140401.1-0ubuntu1" + "thunderbird-locale-hy": "1:24.4.0+build1-0ubuntu1" + "language-pack-es-base": "1:14.04+20140410" + "language-pack-lt": "1:14.04+20140410" + "libmono-web4.0-cil": "3.2.8+dfsg-4ubuntu1" + "erlang-runtime-tools": "1:16.b.3-dfsg-1ubuntu2" + "libgles1-mesa": "10.1.0-4ubuntu5" + "language-pack-fil-base": "1:14.04+20140410" + "libreoffice-l10n-xh": "1:4.2.3~rc3-0ubuntu1" + "apache2-data": "2.4.7-1ubuntu4" + "cdparanoia-dbg": "3.10.2+debian-11" + "lbdb": "0.38ubuntu1" + "libegl1-mesa-dev": "10.1.0-4ubuntu5" + "libpackagekit-glib2-16": "0.8.12-1ubuntu5" + "python-netifaces": "0.8-3build1" + "gimp-data": "2.8.10-0ubuntu1" + "screen-resolution-extra": "0.17.1" + "thunderbird-locale-pt-br": "1:24.4.0+build1-0ubuntu1" + "gstreamer0.10-tools": "0.10.36-1.2ubuntu3" + "libboost-system-dev": "1.54.0.1ubuntu1" + "libreoffice-l10n-or": "1:4.2.3~rc3-0ubuntu1" + "x11proto-core-dev": "7.0.24-1" + "libqt5script5": "5.2.1+dfsg-1ubuntu1" + "texlive-pstricks": "2013.20140215-2" + "libaccounts-glib0": "1.15+14.04.20131126.2-0ubuntu3" + "qt4-demos-dbg": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "pidgin-dev": "1:2.10.9-0ubuntu3" + "gir1.2-ido3-0.1": "13.10.0+14.04.20140407-0ubuntu1" + "libaudio-dev": "1.9.4-1" + "mknbi": "1.4.4-10" + "libgupnp-doc": "0.20.10-1ubuntu1" + "libmono-i18n4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libreoffice-java-common": "1:4.2.3~rc3-0ubuntu2" + "libqtdbustest1": "0.2+14.04.20140325-0ubuntu1" + "python-numpy": "1:1.8.1-1ubuntu1" + "ubuntu-desktop": "1.325" + "freeglut3-dbg": "2.8.1-1" + "libledit-ocaml-dev": "2.03-2build1" + "libmagickwand5": "8:6.7.7.10-6ubuntu3" + "libqtuitools4-perl": "4:4.13.0-0ubuntu1" + "python2.7": "2.7.6-8" + "lib64asan0-powerpc-cross": "4.8.2-16ubuntu3cross0.11" + "libmono-system-ldap-protocols4.0-cil": "3.2.8+dfsg-4ubuntu1" + "dwarves": "1.10-2" + "libopts25": "1:5.18-2ubuntu2" + "python-openssl-dbg": "0.13-2ubuntu6" + "xserver-xorg-input-void-lts-quantal": "3:5" + "libc6-dev-armel-armhf-cross": "2.19-0ubuntu2cross1.104" + "jade": "1.2.1-47.3ubuntu1" + "libneon27-dbg": "0.30.0-1ubuntu1" + "ltspfs": "1.3-1" + "openssh-sftp-server": "1:6.6p1-2ubuntu2" + "libdevel-symdump-perl": "2.11-2" + "libldb1-dbg": "1:1.1.16-1" + "libnepomuk4": "4:4.13.0-0ubuntu1" + "libplist++1": "1.10-1" + "dh-migrations": "0.2.1" + "hunspell-ne": "1:4.2.1-0ubuntu1" + "grub-efi-ia32-bin": "2.02~beta2-9" + "grub-pc-bin": "2.02~beta2-9ubuntu1" + "network-manager-dev": "0.9.8.8-0ubuntu7" + "python-wnck": "2.32.0+dfsg-3" + "python3-netifaces": "0.8-3build1" + "autoconf": "2.69-6" + "cloud-guest-utils": "0.27-0ubuntu9" + "libmono-simd4.0-cil": "3.2.8+dfsg-4ubuntu1" + "python-pocketsphinx-dbg": "0.8.0+real-0ubuntu6" + "python-pycurl": "7.19.3-0ubuntu3" + "fonts-sil-abyssinica": "1.200-6" + "python-requests": "2.2.1-1" + "grub2-common": "2.02~beta2-9" + "libdbus-cpp-dev": "2.0.0+14.04.20140326-0ubuntu1" + "xserver-xorg-input-evdev-lts-raring-dbg": "3:5" + "language-pack-an-base": "1:14.04+20140410" + "acl": "2.2.52-1" + "augeas-tools": "1.2.0-0ubuntu1" + "libsystemd-journal-dev": "204-5ubuntu20" + "libxtst6-dbg": "2:1.2.2-1" + "libreoffice-l10n-ne": "1:4.2.3~rc3-0ubuntu1" + "base-passwd": "3.5.33" + "comerr-dev": "2.1-1.42.9-3ubuntu1" + "ebtables": "2.0.10.4-3ubuntu1" + "libheartbeat2-dev": "1:3.0.5-3.2" + "apport-gtk": "2.14.1-0ubuntu3" + "mono-devel": "3.2.8+dfsg-4ubuntu1" + "lib32quadmath0": "4.8.2-19ubuntu1" + "libopenvg1-mesa-lts-saucy-dbg": "3:5" + "openvswitch-dbg": "2.0.1+git20140120-0ubuntu2" + "libsfasan0-armhf-cross": "4.8.2-16ubuntu4cross0.11" + "libcupsimage2": "1.7.2-0ubuntu1" + "ruby2.0": "2.0.0.484-1ubuntu2" + "python-egenix-mxtools-doc": "3.2.7-1build1" + "libx32go5-dbg": "4.9-20140406-0ubuntu1" + "python-all": "2.7.5-5ubuntu3" + "ruby-rspec-core": "2.14.7-2" + "libmx-1.0-2": "1.4.7-0ubuntu3" + "python-pyxattr": "0.5.1-1.1build4" + "libcrmcommon3": "1.1.10+git20130802-1ubuntu2" + "libcrmservice1-dev": "1.1.10+git20130802-1ubuntu2" + "libphonon4qt5-4": "4:4.7.1-0ubuntu8" + "libqt5designer5": "5.2.1-8build1" + "thunderbird-locale-sq": "1:24.4.0+build1-0ubuntu1" + "python3-tk-dbg": "3.4.0-0ubuntu1" + "qemu-utils": "2.0.0~rc1+dfsg-0ubuntu3" + "language-pack-pl-base": "1:14.04+20140410" + "brltty": "5.0-2ubuntu2" + "libbogl0": "0.1.18-9ubuntu1" + "libossp-uuid-dev": "1.6.2-1.3ubuntu1" + "python-ceph": "0.79-0ubuntu1" + "fonts-ipafont-mincho": "00303-12ubuntu1" + "libmono-sqlite4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libmono-system-ldap4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libgd-gd2-perl": "1:2.46-3.1build1" + "libqt4-script": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "dovecot-dbg": "1:2.2.9-1ubuntu2" + "iptables": "1.4.21-1ubuntu1" + "libcurl4-gnutls-dev": "7.35.0-1ubuntu2" + "libxcb-util0-dev": "0.3.8-2ubuntu1" + "xserver-xorg-video-vesa-lts-quantal": "3:5" + "myspell-nn": "2.0.10-5.1" + "ruby-instantiator": "0.0.6+git9cbbe70-2" + "thunderbird-locale-sv-se": "1:24.4.0+build1-0ubuntu1" + "libbluetooth3": "4.101-0ubuntu13" + "libxp6": "1:1.0.2-1ubuntu1" + "firefox-locale-da": "28.0+build2-0ubuntu2" + "gir1.2-xkl-1.0": "5.4-0ubuntu1" + "libnet-xwhois-perl": "0.90-4" + "bacula-fd": "5.2.6+dfsg-9.1ubuntu3" + "libid3tag0-dev": "0.15.1b-10ubuntu1" + "libqt4-sql": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "thunderbird-locale-he": "1:24.4.0+build1-0ubuntu1" + "ibus-table-cangjie5": "1.4.6-Source-1" + "cron": "3.0pl1-124ubuntu2" + "libharfbuzz0b": "0.9.27-1" + "libxcb-record0-dbg": "1.10-2ubuntu1" + "valac-0.18": "0.18.1-0ubuntu11" + "gir1.2-gssdp-1.0": "0.14.7-1ubuntu1" + "msr-tools": "1.3-2" + "srvadmin-omacore": "7.1.0-5" + "apparmor-notify": "2.8.95~2430-0ubuntu5" + "hyphen-te": "0.7.0-1" + "libglibmm-2.4-1c2a": "2.39.93-0ubuntu1" + "nagios-plugins": "1.5-3ubuntu1" + "puppetmaster": "3.4.3-1" + "default-jre-headless": "2:1.7-51" + "libanthy0": "9100h-23ubuntu2" + "libportaudiocpp0": "19+svn20140130-1" + "iasl": "20140214-1ubuntu1" + "language-pack-gnome-wo": "1:14.04+20140410" + "quilt": "0.61-1" + "lib32go5-dbg": "4.9-20140406-0ubuntu1" + "srvadmin-all": "7.1.0-3" + "binutils-multiarch-dev": "2.24-5ubuntu3" + "language-pack-or-base": "1:14.04+20140410" + "firefox-locale-sl": "28.0+build2-0ubuntu2" + "freerdp-x11": "1.0.2-2ubuntu1" + "libqt4-designer-dbg": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "ocaml-base": "4.01.0-3ubuntu3" + "language-pack-gnome-aa": "1:14.04+20140410" + "libxcursor1": "1:1.1.14-1" + "spamc": "3.4.0-1ubuntu1" + "xserver-xorg-video-intel-lts-raring": "3:5" + "libcogl-gles2-15": "1.16.2-1" + "libustr-1.0-1": "1.0.4-3ubuntu2" + "libxmlunit-java": "1.5-1" + "xvfb": "2:1.15.1-0ubuntu2" + "hspell": "1.2-2" + "lib32bz2-1.0": "1.0.6-5" + "srvadmin-idracadm": "7.1.0-2" + "strongswan-plugin-eap-mschapv2": "5.1.2-0ubuntu2" + "language-pack-gd": "1:14.04+20140410" + "gir1.2-coglpango-1.0": "1.16.2-1" + "gstreamer1.0-plugins-good-dbg": "1.2.3-1ubuntu2" + "libkrossui4": "4:4.13.0-0ubuntu1" + "python-cupshelpers": "1.4.3+20140219-0ubuntu2" + "python-greenlet-dbg": "0.4.2-1build1" + "system-config-printer-udev": "1.4.3+20140219-0ubuntu2" + "libboost1.54-dev": "1.54.0-4ubuntu3" + "libsmbsharemodes-dev": "2:4.1.6+dfsg-1ubuntu2" + "libclass-factory-util-perl": "1.7-2" + "libfile-listing-perl": "6.04-1" + "libtest-checkdeps-perl": "0.010-1" + "libvte-2.90-doc": "1:0.34.9-1ubuntu1" + "squid-langpack": "20121005-1" + "libsmokeqtxmlpatterns4-3": "4:4.13.0-0ubuntu1" + "python3-pyqt5.qtmultimedia-dbg": "5.2.1+dfsg-1ubuntu1" + "language-pack-gnome-dv": "1:14.04+20140410" + "libmono-messaging-rabbitmq2.0-cil": "3.2.8+dfsg-4ubuntu1" + "dovecot-pop3d": "1:2.2.9-1ubuntu2" + "libhx28": "3.15-2ubuntu1" + "libpulse0-dbg": "1:4.0-0ubuntu11" + "texlive": "2013.20140215-1" + "libart-2.0-dev": "2.3.21-2" + "libxatracker2-dbg": "10.1.0-4ubuntu5" + "printer-driver-splix": "2.0.0+svn315-2fakesync1" + "unity-webapps-qml": "0.1+14.04.20140408-0ubuntu1" + "cmake-data": "2.8.12.2-0ubuntu3" + "python3-webob": "1.3.1-1" + "libmount-dev": "2.20.1-5.1ubuntu20" + "libsecret-1-dev": "0.16-0ubuntu1" + "libsoup2.4-dbg": "2.44.2-1ubuntu2" + "gimp-help-pl": "2.6.1-1" + "language-pack-sl-base": "1:14.04+20140410" + "libjson-glib-1.0-common": "0.16.2-1ubuntu1" + "xchat-gnome-common": "1:0.30.0~git20131003.d20b8d+really20110821-0.2ubuntu12" + "thunderbird-locale-pt": "1:24.4.0+build1-0ubuntu1" + "debian-installer": "20101020ubuntu318" + "libegl1-mesa-drivers-lts-quantal-dbg": "3:5" + "libnm-util2": "0.9.8.8-0ubuntu7" + "aptitude-common": "0.6.8.2-1ubuntu4" + "language-pack-en-base": "1:14.04+20140410" + "libgphoto2-l10n": "2.5.3.1-1ubuntu2" + "python-werkzeug-doc": "0.9.4+dfsg-1.1ubuntu1" + "x11proto-xf86dri-dev": "2.1.1-2" + "libqt5webkit5-dev": "5.1.1-1ubuntu8" + "strongswan-plugin-pkcs11": "5.1.2-0ubuntu2" + "unity-gtk-module-common": "0.0.0+14.04.20140403-0ubuntu1" + "xfonts-mathml": "6ubuntu1" + "libchewing3-dev": "0.3.5-4build1" + "libqt5network5": "5.2.1+dfsg-1ubuntu14" + "thunderbird-locale-pa-in": "1:24.4.0+build1-0ubuntu1" + "bacula-traymonitor-dbg": "5.2.6+dfsg-9.1ubuntu3" + "libbasicobjects-dev": "0.3.0.1-4" + "libegl1-mesa-lts-quantal": "3:5" + "language-pack-gnome-nan-base": "1:14.04+20140410" + "libgomp1-arm64-cross": "4.8.2-13ubuntu1cross0.11" + "monodoc-webkit-manual": "0.3-6" + "python3-examples": "3.4.0-0ubuntu2" + "gir1.2-harfbuzz-0.0": "0.9.27-1" + "python3": "3.4.0-0ubuntu2" + "libreoffice-l10n-om": "1:4.2.3~rc3-0ubuntu1" + "python-problem-report": "2.14.1-0ubuntu3" + "libhud-client2": "13.10.1+14.04.20140402-0ubuntu1" + "libitm1": "4.8.2-19ubuntu1" + "libsvn1": "1.8.8-1ubuntu3" + "glance-registry": "1:2014.1-0ubuntu1" + "lsb-base": "4.1+Debian11ubuntu6" + "unifont": "1:6.3.20131221-1" + "gir1.2-gtksource-3.0": "3.10.2-0ubuntu1" + "libwmf-bin": "0.2.8.4-10.3ubuntu1" + "icedtea-plugin": "1.5-1ubuntu1" + "zsh-doc": "5.0.2-3ubuntu6" + "python-hplefthandclient": "1.0.1-1ubuntu1" + "python-sqlalchemy": "0.8.4-1build1" + "libxml2": "2.9.1+dfsg1-3ubuntu4" + "python-flask-doc": "0.10.1-2build1" + "gcc-doc": "4:4.8.2-1ubuntu6" + "liblrmd1": "1.1.10+git20130802-1ubuntu2" + "libnl-genl-3-dev": "3.2.21-1" + "python3-renderpm": "3.0-1build1" + "xserver-xorg-video-siliconmotion": "1:1.7.7-2build1" + "popularity-contest": "1.57ubuntu1" + "cdebconf": "0.187ubuntu1" + "dovecot-dev": "1:2.2.9-1ubuntu2" + "gir1.2-polkit-1.0": "0.105-4ubuntu2" + "linux-generic": "3.13.0.32.38" + "libvte-dev": "1:0.28.2-5ubuntu1" + "ienglish-common": "3.3.02-6" + "libreoffice-l10n-ko": "1:4.2.3~rc3-0ubuntu1" + "libedataserver1.2-dev": "3.10.4-0ubuntu1" + "libfakeroot": "1.20-3ubuntu2" + "libt1-dev": "5.1.2-3.6ubuntu1" + "libgdk-pixbuf2.0-doc": "2.30.7-0ubuntu1" + "libgstreamer-plugins-base0.10-0": "0.10.36-1.1ubuntu2" + "nagios-nrpe-server": "2.15-0ubuntu1" + "libextutils-depends-perl": "0.305-1" + "preview-latex-style": "11.87-1ubuntu2" + "libcmis-dev": "0.4.1-3ubuntu4" + "libsystemd-login-dev": "204-5ubuntu20" + "tokyocabinet-doc": "1.4.48-2" + "qt4-linguist-tools": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "printer-driver-gutenprint": "5.2.10~pre2-0ubuntu2" + "xsltproc": "1.1.28-2build1" + "lib64stdc++6-powerpc-cross": "4.8.2-16ubuntu3cross0.11" + "libapache-pom-java": "10-2build1" + "linuxdoc-tools-latex": "0.9.69-2" + "python-croniter": "0.3.4-0ubuntu1" + "telepathy-gabble-dbg": "0.18.2-1" + "locales": "2.13+git20120306-12.1" + "openstack-dashboard": "1:2014.1-0ubuntu1" + "python-oslo.sphinx": "2.0-0ubuntu2" + "libhyphen-dev": "2.8.6-3ubuntu2" + "lib32ncursesw5-dev": "5.9+20140118-1ubuntu1" + "obexd-client": "0.46-1ubuntu7" + "gir1.2-accounts-1.0": "1.15+14.04.20131126.2-0ubuntu3" + "kdelibs5-dev": "4:4.13.0-0ubuntu1" + "lsb-languages": "4.1+Debian11ubuntu6" + "account-plugin-google": "0.11+14.04.20140409.1-0ubuntu1" + "language-pack-gnome-mg-base": "1:14.04+20140410" + "libgl1-mesa-glx-dbg": "10.1.0-4ubuntu5" + "libqt5multimediawidgets5": "5.2.1-0ubuntu5" + "update-notifier": "0.154.1" + "xserver-xorg-video-siliconmotion-lts-saucy": "3:5" + "docbook-dsssl": "1.79-7ubuntu1" + "language-pack-gnome-nds": "1:14.04+20140410" + "sessioninstaller": "0.20+bzr141-0ubuntu4" + "libcanberra-pulse-dbg": "0.30-0ubuntu3" + "libdbusmenu-gtk-dev": "12.10.3+14.04.20140319-0ubuntu1" + "language-pack-gnome-tr-base": "1:14.04+20140410" + "libconfig-auto-perl": "0.42-1" + "python-html5lib": "0.999-2" + "libmount1": "2.20.1-5.1ubuntu20" + "libneon27": "0.30.0-1ubuntu1" + "librabbitmq1": "0.4.1-1" + "libnet-ip-perl": "1.26-1" + "dictfmt": "1.12.1+dfsg-2" + "libcanberra-gtk3-0-dbg": "0.30-0ubuntu3" + "libdbi1-dbg": "0.9.0-1" + "libhx-dev": "3.15-2ubuntu1" + "php5-xmlrpc": "5.5.9+dfsg-1ubuntu4" + "libgd2-xpm-dev": "2.1.0-3" + "ruby-diff-lcs": "1.2.4-1" + "landscape-client-ui": "14.01-0ubuntu3" + "libgnomecanvas2-dev": "2.30.3-2" + "libxvmc1-dbg": "2:1.0.8-1ubuntu1" + "x11proto-print-dev": "1.0.5-2" + "libreoffice-calc": "1:4.2.3~rc3-0ubuntu2" + "srvadmin-sysfsutils": "7.1.0-2" + "wvdial": "1.61-4.1" + "evolution-data-server-online-accounts": "3.10.4-0ubuntu1" + "libandroid-properties-dev": "0.1.0+git20131207+e452e83-0ubuntu12" + "libboost-date-time-dev": "1.54.0.1ubuntu1" + "libgnutlsxx27": "2.12.23-12ubuntu2" + "libgstreamer-plugins-good1.0-dev": "1.2.3-1ubuntu2" + "libnetcf1": "1:0.2.3-4ubuntu1" + "sshfs": "2.5-1ubuntu1" + "language-pack-mhr": "1:14.04+20140410" + "mariadb-client": "5.5.38+maria-1~trusty" + "cython-dbg": "0.20.1+git90-g0e6e38e-1ubuntu2" + "gir1.2-freedesktop": "1.40.0-1" + "libglew1.10": "1.10.0-3" + "libsmokeqimageblitz3": "4:4.13.0-0ubuntu1" + "icon-naming-utils": "0.8.90-2" + "language-pack-gnome-el": "1:14.04+20140410" + "bacula-traymonitor": "5.2.6+dfsg-9.1ubuntu3" + "drbd8-utils": "2:8.4.4-1ubuntu1" + "gir1.2-upstart-app-launch-2": "0.3+14.04.20140411-0ubuntu1" + "python3-dbus-dbg": "1.2.0-2build2" + "autofs5": "5.0.7-3ubuntu3" + "firefox-locale-gd": "28.0+build2-0ubuntu2" + "gir1.2-messagingmenu-1.0": "13.10.1+14.04.20140410-0ubuntu1" + "librados-dev": "0.79-0ubuntu1" + "libunwind-setjmp0-dev": "1.1-2.2ubuntu3" + "libwmf-doc": "0.2.8.4-10.3ubuntu1" + "libdbd-mysql-perl": "4.025-1" + "qtdeclarative5-dbg": "5.2.1-3ubuntu15" + "auctex": "11.87-1ubuntu2" + "initramfs-tools": "0.103ubuntu4.2" + "libzephyr4": "3.1.2-1" + "account-plugin-twitter": "0.11+14.04.20140409.1-0ubuntu1" + "language-pack-gnome-gd-base": "1:14.04+20140410" + "openstack-dashboard-ubuntu-theme": "1:2014.1-0ubuntu1" + "libflac8": "1.3.0-2" + "libgssapi3-heimdal": "1.6~git20131207+dfsg-1ubuntu1" + "ntfs-3g-dbg": "1:2013.1.13AR.1-2ubuntu2" + "language-pack-sv": "1:14.04+20140410" + "libfile-copy-recursive-perl": "0.38-1" + "pppoeconf": "1.20ubuntu1" + "libqpdf-dev": "5.1.1-1" + "libtommath-dev": "0.42.0-1build1" + "libunity-gtk2-parser-dev": "0.0.0+14.04.20140403-0ubuntu1" + "libbrasero-media3-dev": "3.10.0-0ubuntu1" + "libgl1-mesa-dri-lts-raring-dbg": "3:5" + "libsss-nss-idmap-dev": "1.11.5-1ubuntu3" + "libconvert-binhex-perl": "1.123-1" + "libow-util-ant-tasks-java-doc": "1.3.2-4build1" + "puppetmaster-common": "3.4.3-1" + "firefox-locale-id": "28.0+build2-0ubuntu2" + "kdelibs-bin": "4:4.13.0-0ubuntu1" + "libecj-java": "3.9.0-1" + "gir1.2-totem-1.0": "3.10.1-1ubuntu4" + "python3-reportlab-accel-dbg": "3.0-1build1" + "qtfeedback5-dev": "5.0~git20130529-0ubuntu3" + "libbabl-0.1-0": "0.1.10-1ubuntu2" + "libffado-dev": "2.1.0+svn2240-1ubuntu3" + "libpeas-1.0-0": "1.8.1-2ubuntu2" + "libvala-0.18-0-dbg": "0.18.1-0ubuntu11" + "realpath": "1.19" + "fonts-tlwg-garuda": "1:0.5.1-3" + "libreoffice-l10n-oc": "1:4.2.3~rc3-0ubuntu1" + "ubuntu-system-service": "0.2.5build1" + "libqt5versit5": "5.0~git20140203~e0c5eebe-0ubuntu2" + "librsvg2-dbg": "2.40.2-1" + "java-wrappers": "0.1.27" + "libdrm-dev-lts-quantal": "3:5" + "libimobiledevice4": "1.1.5+git20140313.bafe6a9e-0ubuntu1" + "libsmokeqsci3": "4:4.13.0-0ubuntu1" + "clamav-base": "0.98.1+dfsg-4ubuntu1" + "python-blinker": "1.3.dfsg1-1ubuntu2" + "beanstalkd": "1.9-2ubuntu1" + "libparams-classify-perl": "0.013-4build2" + "cli-common": "0.9" + "libtest-simple-perl": "1.001002-1" + "qemu-common": "2.0.0~rc1+dfsg-0ubuntu3" + "libplatform-api-headers": "0.20+14.04.20140411-0ubuntu1" + "libsphinxbase-dev": "0.8-0ubuntu10" + "libmono-c5-1.1-cil": "3.2.8+dfsg-4ubuntu1" + "libpixman-1-dev": "0.30.2-2ubuntu1" + "ocaml-findlib": "1.4-2" + "srvadmin-rac4-populator": "7.1.0-3" + "hyphen-kn": "0.7.0-2" + "libtest-tester-perl": "0.109-1" + "firefox-locale-sv": "28.0+build2-0ubuntu2" + "libopenexr-dev": "1.6.1-7ubuntu1" + "libpng12-0": "1.2.50-1ubuntu2" + "libiec61883-dev": "1.2.0-0.1ubuntu3" + "python-mysqldb-dbg": "1.2.3-2ubuntu1" + "python3-newt": "0.52.15-2ubuntu5" + "language-pack-eo-base": "1:14.04+20140410" + "libcommons-parent-java": "22-2build1" + "libreoffice-l10n-it": "1:4.2.3~rc3-0ubuntu1" + "sgmlspl": "1.03ii-32" + "g++-4.8-multilib-powerpc-linux-gnu": "4.8.2-16ubuntu3cross0.11" + "libjarjar-java": "1.4+svn142-3" + "libreoffice-l10n-kmr-latn": "1:4.2.3~rc3-0ubuntu1" + "g++-4.8-powerpc64le-linux-gnu": "4.8.2-16ubuntu4cross0.4" + "libclutter-gtk-1.0-dev": "1.4.4-3ubuntu2" + "libcrypt-openssl-bignum-perl": "0.04-4build1" + "deja-dup-backend-gvfs": "30.0-0ubuntu4" + "language-pack-mg": "1:14.04+20140410" + "libmono-i18n-west4.0-cil": "3.2.8+dfsg-4ubuntu1" + "python-keystoneclient": "1:0.7.1-ubuntu1" + "tk8.6-doc": "8.6.1-3ubuntu2" + "libffi6-dbg": "3.1~rc1+r3.0.13-12" + "libgles2-mesa-dev-lts-quantal": "3:5" + "python-gst0.10-dev": "0.10.22-3ubuntu2" + "python3-zope.interface-dbg": "4.0.5-1ubuntu4" + "libpocketsphinx-dev": "0.8.0+real-0ubuntu6" + "librrd-dev": "1.4.7-2ubuntu5" + "ant": "1.9.3-2build1" + "fonts-arphic-gbsn00lp": "2.11-13" + "python-cherrypy3": "3.2.2-4ubuntu5" + "python-taskflow": "0.1.3-0ubuntu3" + "libgl1-mesa-dev-lts-quantal": "3:5" + "libreoffice-draw": "1:4.2.3~rc3-0ubuntu2" + "libterm-ui-perl": "0.42-1" + "myspell-af": "1:4.2.1-0ubuntu1" + "firefox-locale-si": "28.0+build2-0ubuntu2" + "libandroid-properties1": "0.1.0+git20131207+e452e83-0ubuntu12" + "libnm-glib-vpn-dev": "0.9.8.8-0ubuntu7" + "libclutter-gtk-1.0-doc": "1.4.4-3ubuntu2" + "freeipmi-tools": "1.1.5-3ubuntu3" + "libpangomm-1.4-dbg": "2.34.0-1ubuntu1" + "libvncserver-config": "0.9.9+dfsg-1ubuntu1" + "python-pygresql": "1:4.0-3build3" + "dmz-cursor-theme": "0.4.4ubuntu1" + "language-pack-gnome-uk": "1:14.04+20140410" + "language-pack-ka": "1:14.04+20140410" + "python-jsonschema": "2.3.0-1build1" + "libconfig9": "1.4.9-2" + "python3-pyxattr-dbg": "0.5.1-1.1build4" + "srvadmin-storelib-sysfs": "7.1.0-1" + "libunity-2d-private-dev": "7.2.0+14.04.20140416-0ubuntu1" + "linux-cloud-tools-common": "3.13.0-24.46" + "erlang-public-key": "1:16.b.3-dfsg-1ubuntu2" + "libegl1-mesa": "10.1.0-4ubuntu5" + "libnautilus-extension1a": "1:3.10.1-0ubuntu8" + "fonts-tlwg-norasi": "1:0.5.1-3" + "libreoffice-l10n-si": "1:4.2.3~rc3-0ubuntu1" + "lib32ncurses5-dev": "5.9+20140118-1ubuntu1" + "libhesiod-dev": "3.2.1-2" + "libclass-tiny-perl": "0.012-1" + "libxml++2.6-doc": "2.36.0-2ubuntu1" + "python3-libapparmor": "2.8.95~2430-0ubuntu5" + "rasqal-utils": "0.9.32-1" + "screen": "4.1.0~20120320gitdb59704-9" + "python-ntdb-dbg": "1.0-2ubuntu1" + "language-pack-gnome-ko": "1:14.04+20140410" + "mysql-client": "5.5.35+dfsg-1ubuntu1" + "dialog": "1.2-20130928-1" + "libgphoto2-dev": "2.5.3.1-1ubuntu2" + "hunspell-de-de": "20120607-1" + "ruby-rspec": "2.14.1-1" + "libdb5.3": "5.3.28-3ubuntu3" + "libudf-dev": "0.83-4.1ubuntu1" + "gir1.2-gexiv2-0.10": "0.10.0-1ubuntu1" + "libxcb-res0-dev": "1.10-2ubuntu1" + "libdbus-1-3": "1.6.18-0ubuntu4.1" + "libmtp-dev": "1.1.6-20-g1b9f164-1ubuntu2" + "libsnmp-dev": "5.7.2~dfsg-8.1ubuntu3" + "freetds-common": "0.91-5" + "python-stevedore-doc": "0.14.1-1" + "qtmultimedia5-doc": "5.2.1-0ubuntu5" + "bacula-fd-dbg": "5.2.6+dfsg-9.1ubuntu3" + "lib32readline5": "5.2+dfsg-2" + "libxml2-dev": "2.9.1+dfsg1-3ubuntu4.3" + "python3-pyqt5.qtsensors": "5.2.1+dfsg-1ubuntu1" + "libgsettings-qt-dev": "0.1+14.04.20140408-0ubuntu1" + "libreoffice-l10n-km": "1:4.2.3~rc3-0ubuntu1" + "whoopsie": "0.2.24.5" + "libmono-debugger-soft2.0a-cil": "3.2.8+dfsg-4ubuntu1" + "libopenvg1-mesa": "10.1.0-4ubuntu5" + "python-hdate": "1.6-2ubuntu3" + "tcl8.6-dev": "8.6.1-4ubuntu1" + "libtelepathy-glib0": "0.22.1-1ubuntu2" + "libxcb-sync1-dbg": "1.10-2ubuntu1" + "python3-genshi": "0.7-3" + "apt-doc": "1.0.1ubuntu2" + "libmono-system-reactive-experimental2.2-cil": "3.2.8+dfsg-4ubuntu1" + "bacula-director-common": "5.2.6+dfsg-9.1ubuntu3" + "binutils-powerpc64le-linux-gnu": "2.24-2ubuntu3cross0.4" + "libgladeui-dev": "3.16.1-0ubuntu2" + "emacsen-common": "2.0.7" + "language-pack-gnome-en": "1:14.04+20140410" + "libc6-armel-cross": "2.19-0ubuntu2cross1.104" + "gir1.2-gsf-1": "1.14.27-2ubuntu2" + "libgnome2.24-cil": "2.24.2-3" + "intltool": "0.50.2-2" + "libaudit1": "1:2.3.2-2ubuntu1" + "libtelepathy-logger3": "0.8.0-3" + "postgresql-server-dev-9.3": "9.3.4-1" + "vino": "3.8.1-0ubuntu1" + "friends-flickr": "0.2.0+14.04.20140217.1-0ubuntu1" + "libdbd-sqlite3-perl": "1.40-3" + "reiser4progs": "1.0.7-6.3fakesync2" + "language-pack-ka-base": "1:14.04+20140410" + "libxcb-render-util0": "0.3.8-1.1ubuntu1" + "procmail": "3.22-21" + "srvadmin-idracadm7": "7.1.0-2" + "libcanberra-gtk0": "0.30-0ubuntu3" + "libquorum-dev": "2.3.3-1ubuntu1" + "libstrigihtmlgui0": "0.7.8-1ubuntu2" + "libuninameslist-dev": "0.3.20130501-3" + "python-gconf": "2.28.1+dfsg-1ubuntu2" + "libreoffice-l10n-he": "1:4.2.3~rc3-0ubuntu1" + "libenchant-voikko": "1.6.0-10ubuntu1" + "language-pack-gnome-ve-base": "1:14.04+20140410" + "libsuitesparse-doc": "1:4.2.1-3ubuntu1" + "python-repoze.lru": "0.6-4" + "firefox-locale-lt": "28.0+build2-0ubuntu2" + "python-apt": "0.9.3.5" + "libdatetime-locale-perl": "1:0.45-2" + "libreoffice-help-tr": "1:4.2.3~rc3-0ubuntu1" + "python-oslotest": "0.1-1ubuntu3" + "apparmor-utils": "2.8.95~2430-0ubuntu5" + "libdw1": "0.158-0ubuntu5" + "lib32gcc-4.7-dev": "4.7.3-12ubuntu1" + "libraptor1-dev": "1.4.21-10" + "firefox-locale-de": "28.0+build2-0ubuntu2" + "libcdb1": "0.78" + "libsensors4-dev": "1:3.3.4-2ubuntu1" + "python-httplib2": "0.8-2build1" + "qtgraphicaleffects5-doc": "5.2.1-1" + "libtest-leaktrace-perl": "0.14-1build3" + "printer-driver-min12xxw": "0.0.9-8ubuntu1" + "libmtdev1": "1.1.4-1ubuntu1" + "libvformat0": "1.13-10" + "libxml2": "2.9.1+dfsg1-3ubuntu4.3" + "php5-recode": "5.5.9+dfsg-1ubuntu4" + "irda-utils": "0.9.18-12ubuntu1" + "libgnumail-java-doc": "1.1.2-9ubuntu3" + "libnice-doc": "0.1.4-1" + "libperl4-corelibs-perl": "0.003-1" + "python3-roman": "2.0.0-1" + "bacula-sd-mysql-dbg": "5.2.6+dfsg-9.1ubuntu3" + "language-pack-wae": "1:14.04+20140410" + "libjson-glib-1.0-0": "0.16.2-1ubuntu1" + "libsubunit-dev": "0.0.18-0ubuntu7" + "pidgin": "1:2.10.9-0ubuntu3" + "blt": "2.4z-7ubuntu2" + "libpangox-1.0-dev": "0.0.2-4ubuntu1" + "libtelepathy-glib0-dbg": "0.22.1-1ubuntu2" + "libinline-perl": "0.53-1" + "nginx-doc": "1.4.6-1ubuntu3" + "python3-checkbox-ng": "0.3-2" + "python3-imaging-sane-dbg": "2.3.0-1ubuntu3" + "ubuntu-sso-client": "13.10-0ubuntu6" + "language-pack-hy": "1:14.04+20140410" + "python-fixtures": "0.3.14-1ubuntu2" + "libnetcf-dev": "1:0.2.3-4ubuntu1" + "perl-base": "5.18.2-2ubuntu1" + "xserver-xorg-video-ati-lts-saucy": "3:5" + "ruby-hashie": "2.0.3-1" + "libfriends-gtk0": "0.1.2+14.04.20131108.1-0ubuntu1" + "libharfbuzz-icu0": "0.9.27-1" + "libqjson0": "0.8.1-3" + "libruby1.9.1-dbg": "1.9.3.484-2ubuntu1" + "libspeechd2": "0.8-5ubuntu1" + "libxatracker1-lts-saucy-dbg": "3:5" + "dupload": "2.7.0ubuntu1" + "libdbusmenu-glib-doc": "12.10.3+14.04.20140319-0ubuntu1" + "libglib2.0-data": "2.40.0-2" + "python-httpretty": "0.8.0-0ubuntu3" + "libheimbase1-heimdal": "1.6~git20131207+dfsg-1ubuntu1" + "libmono-rabbitmq4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libc6-dev": "2.19-0ubuntu6" + "libmysqlcppconn7": "1.1.3-5" + "vblade": "20-1ubuntu2" + "nova-cert": "1:2014.1-0ubuntu1" + "locales": "2.13+git20120306-12" + "python3-repoze.lru": "0.6-4" + "grub-efi": "2.02~beta2-9" + "libgimp2.0": "2.8.10-0ubuntu1" + "language-pack-gnome-pl": "1:14.04+20140410" + "libgeis-dev": "2.2.16+14.04.20140303-0ubuntu1" + "language-pack-gnome-he": "1:14.04+20140410" + "bdfresize": "1.5-8" + "libegl1-mesa-dev-lts-quantal": "3:5" + "libimobiledevice-dev": "1.1.5+git20140313.bafe6a9e-0ubuntu1" + "thunderbird-locale-vi": "1:24.4.0+build1-0ubuntu1" + "fonts-wqy-zenhei": "0.9.45-5ubuntu1" + "grub-xen": "2.02~beta2-9" + "libept1.4.12": "1.0.12" + "xserver-xorg-input-evdev-lts-saucy-dbg": "3:5" + "mawk": "1.3.3-17ubuntu2" + "patch": "2.7.1-4ubuntu1" + "python-pymongo": "2.6.3-1build1" + "language-pack-he-base": "1:14.04+20140410" + "python-mako": "0.9.1-1" + "python-ufw": "0.34~rc-0ubuntu2" + "firefox-locale-ro": "28.0+build2-0ubuntu2" + "libaprutil1-dev": "1.5.3-1" + "unity-control-center-signon": "0.1.7~+14.04.20140211.2-0ubuntu4" + "libopenhpi-dev": "2.14.1-1.3ubuntu2" + "libqmi-glib0-dbg": "1.4.0-1" + "libvisual-0.4-plugins": "0.4.0.dfsg.1-7build1" + "apport-symptoms": "0.20" + "libfont-afm-perl": "1.20-1" + "libgcc1-powerpc-cross": "1:4.8.2-16ubuntu3cross0.11" + "build-essential": "11.6ubuntu6" + "libjbig2dec0-dev": "0.11+20120125-1ubuntu1" + "libwhoopsie0": "0.2.24.5" + "python-pil-dbg": "2.3.0-1ubuntu3" + "qt-at-spi": "0.3.1-4fakesync1" + "language-pack-gnome-ne-base": "1:14.04+20140410" + "libavahi-core-dev": "0.6.31-4ubuntu1" + "libcolumbus1-dev": "1.1.0+14.04.20140325.3-0ubuntu1" + "libssl1.0.0-dbg": "1.0.1f-1ubuntu2" + "xserver-xorg-video-savage-lts-raring": "3:5" + "python3-markupsafe-dbg": "0.18-1build2" + "schroot": "1.6.8-1ubuntu1" + "libsysfs2": "2.1.0+repack-3ubuntu1" + "python-gtk2-dbg": "2.24.0-3ubuntu3" + "thunderbird-locale-br": "1:24.4.0+build1-0ubuntu1" + "libmonoboehm-2.0-1": "3.2.8+dfsg-4ubuntu1" + "libspeexdsp1": "1.2~rc1.1-1ubuntu1" + "linux-libc-dev-arm64-cross": "3.13.0-12.32cross0.10" + "python-gobject-2-dev": "2.28.6-12build1" + "avahi-dbg": "0.6.31-4ubuntu1" + "libdbd-mysql": "0.9.0-2ubuntu2" + "libfftw3-dev": "3.3.3-7ubuntu3" + "libsoup2.4-dev": "2.44.2-1ubuntu2" + "samba-common-bin": "2:4.1.6+dfsg-1ubuntu2" + "language-pack-gnome-fi": "1:14.04+20140410" + "libmono-windowsbase3.0-cil": "3.2.8+dfsg-4ubuntu1" + "libtest-warn-perl": "0.24-1" + "x11proto-present-dev": "1.0-1" + "libplist-dev": "1.10-1" + "portaudio19-doc": "19+svn20140130-1" + "python3-ipaddr": "2.1.10-1" + "thunderbird-locale-zh-tw": "1:24.4.0+build1-0ubuntu1" + "gnome-settings-daemon": "3.8.6.1-0ubuntu11" + "libatm1": "1:2.5.1-1.5" + "libavahi-compat-libdnssd1": "0.6.31-4ubuntu1" + "libgbm1-lts-saucy": "3:5" + "libvotequorum6": "2.3.3-1ubuntu1" + "libmono-corlib4.5-cil": "3.2.8+dfsg-4ubuntu1" + "libmono-tasklets4.0-cil": "3.2.8+dfsg-4ubuntu1" + "cpp-4.8-aarch64-linux-gnu": "4.8.2-13ubuntu1cross0.11" + "libappindicator3-1": "12.10.1+13.10.20130920-0ubuntu4" + "python3-sane-dbg": "2.3.0-1ubuntu3" + "libwebkit2gtk-3.0-25-dbg": "2.4.0-1ubuntu2" + "libxcb-present0": "1.10-2ubuntu1" + "thunderbird-locale-bn": "1:24.4.0+build1-0ubuntu1" + "language-pack-am-base": "1:14.04+20140410" + "python-networkx-doc": "1.8.1-0ubuntu3" + "strongswan": "5.1.2-0ubuntu2" + "libprotoc-dev": "2.5.0-9ubuntu1" + "libsaxon-java-gcj": "1:6.5.5-10" + "libegl1-mesa-drivers-lts-raring": "3:5" + "bzr-doc": "2.6.0+bzr6593-1ubuntu1" + "libqt5svg5-private-dev": "5.2.1-1" + "libubuntu-location-service0": "0.0.2+14.04.20140307-0ubuntu1" + "php5-dev": "5.5.9+dfsg-1ubuntu4" + "policykit-1-gnome": "0.105-1ubuntu4" + "myspell-sv-se": "1.51-1" + "libasprintf-dev": "0.18.3.1-1ubuntu2" + "gutenprint-doc": "5.2.10~pre2-0ubuntu2" + "language-pack-gnome-cy": "1:14.04+20140410" + "libcanberra-gtk-module-dbg": "0.30-0ubuntu3" + "libkrb5-dev": "1.12+dfsg-2ubuntu4" + "bacula-director-sqlite3-dbg": "5.2.6+dfsg-9.1ubuntu3" + "libasm1": "0.158-0ubuntu5" + "libopenobex1": "1.5-2.1" + "fonts-dejavu-extra": "2.34-1ubuntu1" + "chrpath": "0.14-3ubuntu1" + "libopenvg1-mesa-lts-quantal": "3:5" + "python-pam": "0.4.2-13.1ubuntu3" + "qtbase5-dbg": "5.2.1+dfsg-1ubuntu14" + "libdbd-sqlite3": "0.9.0-2ubuntu2" + "libmono-ldap4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libgeoip1": "1.6.0-1" + "libwibble-dev": "1.1-1" + "python3-xdg": "0.25-4" + "libperlio-gzip-perl": "0.18-1build3" + "qmlscene": "5.2.1-3ubuntu15" + "signon-ui": "0.16+14.04.20140304.is.0.15+14.04.20140313-0ubuntu1" + "x11-xserver-utils-lts-saucy": "3:5" + "ldap-auth-config": "0.5.3" + "libjs-yui3-common": "3.5.1-1ubuntu3" + "libmono-system-web-http-webhost4.0-cil": "3.2.8+dfsg-4ubuntu1" + "puppet-common": "3.4.3-1" + "libmagickcore5": "8:6.7.7.10-6ubuntu3" + "libregexp-java-doc": "1.5-3build1" + "gir1.2-grip": "0.3.7+14.04.20140303-0ubuntu1" + "libasprintf0c2": "0.18.3.1-1ubuntu2" + "thermald": "1.1~rc2-11" + "libcpan-changes-perl": "0.27-1" + "liboro-java-doc": "2.0.8a-9" + "gcc-4.8-powerpc64le-linux-gnu-base": "4.8.2-16ubuntu4cross0.4" + "gcj-4.8-jre-headless": "4.8.2-19ubuntu1" + "libqtscript4-perl": "4:4.13.0-0ubuntu1" + "hyphen-as": "0.7.0-1" + "language-pack-gnome-kl": "1:14.04+20140410" + "bzip2": "1.0.6-5" + "python-adns": "1.2.1-5build3" + "xserver-xorg-core-lts-saucy-dbg": "3:5" + "libconfig-general-perl": "2.52-1" + "libdb5.3-java": "5.3.28-3ubuntu3" + "libjs-jquery-resize-doc": "8-2" + "libmono-system-transactions4.0-cil": "3.2.8+dfsg-4ubuntu1" + "python-concurrent.futures": "2.1.6-3" + "libdrm-dev": "2.4.52-1" + "liborc-0.4-dev": "1:0.4.18-1ubuntu1" + "fonts-kacst-one": "5.0+svn11846-7" + "libreoffice-help-et": "1:4.2.3~rc3-0ubuntu1" + "swift-container": "1.13.1-0ubuntu1" + "landscape-client": "14.01-0ubuntu3" + "libatspi2.0-0": "2.10.2.is.2.10.1-0ubuntu1" + "libgnome-desktop-3-7": "3.8.4-0ubuntu3" + "libldap2-dev": "2.4.31-1+nmu2ubuntu8" + "samba-vfs-modules": "2:4.1.6+dfsg-1ubuntu2" + "firefox-locale-bs": "28.0+build2-0ubuntu2" + "libxcb-record0-dev": "1.10-2ubuntu1" + "libzeitgeist-2.0-0": "0.9.14-0ubuntu4" + "linux-image-server": "3.13.0.24.28" + "alembic": "0.6.2+ds-1" + "python-tempita": "0.5.2-1build1" + "libkdesu5": "4:4.13.0-0ubuntu1" + "liblightdm-gobject-1-0": "1.10.0-0ubuntu3" + "librasqal3-dev": "0.9.32-1" + "libbabl-doc": "0.1.10-1ubuntu2" + "python-setuptools": "3.3-1ubuntu1" + "ubuntu-sounds": "0.13" + "libmono-tasklets2.0-cil": "3.2.8+dfsg-4ubuntu1" + "ucf": "3.0027+nmu1" + "libmonoboehm-2.0-1-dbg": "3.2.8+dfsg-4ubuntu1" + "xaw3dg": "1.5+E-18.2" + "python-egenix-mxqueue-doc": "3.2.7-1build1" + "dconf-service": "0.20.0-1" + "gir1.2-accountplugin-1.0": "0.1.7~+14.04.20140211.2-0ubuntu4" + "linux-headers-3.13.0-30-generic": "3.13.0-30.55" + "python-reportlab-accel": "3.0-1build1" + "glibc-doc-reference": "2.19-0ubuntu1" + "mauve": "20120103-1" + "mousetweaks": "3.8.0-2" + "gstreamer0.10-pulseaudio": "0.10.31-3+nmu1ubuntu5" + "libgtop2-7": "2.28.5-2" + "python-libxml2-dbg": "2.9.1+dfsg1-3ubuntu4" + "autotools-dev": "20130810.1" + "language-pack-ps-base": "1:14.04+20140410" + "cython3": "0.20.1+git90-g0e6e38e-1ubuntu2" + "libacl1-dev": "2.2.52-1" + "libxres-dev": "2:1.0.7-1" + "hunspell-ar": "3.2-1" + "quagga-doc": "0.99.22.4-3ubuntu1" + "samba-dev": "2:4.1.6+dfsg-1ubuntu2" + "reiserfsprogs": "1:3.6.24-1" + "xserver-xorg-input-void-lts-raring": "3:5" + "language-pack-ks-base": "1:14.04+20140410" + "ruby-safe-yaml": "1.0.1-1" + "acct": "6.5.5-1ubuntu5" + "alsa-utils": "1.0.27.2-1ubuntu2" + "grep": "2.16-1" + "libxcb-shm0-dev": "1.10-2ubuntu1" + "libxcb-xevie0-dbg": "1.10-2ubuntu1" + "python-greenlet": "0.4.2-1build1" + "language-pack-te": "1:14.04+20140410" + "mir-doc": "0.1.8+14.04.20140411-0ubuntu1" + "myspell-en-us": "1:4.2.1-0ubuntu1" + "gcj-jre-headless": "4:4.8.2-1ubuntu6" + "libfarstream-0.2-dev": "0.2.3-1ubuntu2" + "python3-numpy-dbg": "1:1.8.1-1ubuntu1" + "libmono-system-net-http-webrequest4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libreoffice-style-human": "1:4.2.3~rc3-0ubuntu2" + "libgles1-mesa-lts-saucy": "3:5" + "libtext-csv-xs-perl": "1.02-1" + "libxcb-randr0-dbg": "1.10-2ubuntu1" + "example-content": "48" + "language-pack-oc-base": "1:14.04+20140410" + "python-jsonpatch": "1.3-4" + "libpython3.4": "3.4.0-2ubuntu1" + "overlay-scrollbar-gtk2": "0.2.16+r359+14.04.20131129-0ubuntu1" + "alien": "8.90" + "language-pack-gnome-ca-base": "1:14.04+20140410" + "libtelepathy-glib-doc": "0.22.1-1ubuntu2" + "python3-distupgrade": "1:0.220.2" + "libisl-dev": "0.12.2-1" + "libsamplerate0": "0.1.8-7" + "glance": "1:2014.1-0ubuntu1" + "libreoffice-help-hi": "1:4.2.3~rc3-0ubuntu1" + "hv-kvp-daemon-init": "3.13.0.24.28" + "libgmp10": "2:5.1.3+dfsg-1ubuntu1" + "libisofs-dbg": "1.3.4-0ubuntu1" + "adium-theme-ubuntu": "0.3.4-0ubuntu1" + "language-pack-gnome-pap-base": "1:14.04+20140410" + "libjs-underscore": "1.4.4-2ubuntu1" + "firefox-locale-ar": "28.0+build2-0ubuntu2" + "file-roller": "3.10.2.1-0ubuntu4" + "libgsl0-dbg": "1.16+dfsg-1ubuntu1" + "qtdbustest-runner": "0.2+14.04.20140325-0ubuntu1" + "branding-ubuntu": "0.8" + "hardening-includes": "2.5ubuntu2" + "language-pack-gnome-mai-base": "1:14.04+20140410" + "language-pack-gnome-zh-hant-base": "1:14.04+20140410" + "erlang-ssh": "1:16.b.3-dfsg-1ubuntu2" + "installation-guide-i386": "20100518ubuntu10" + "python-numpy-doc": "1:1.8.1-1ubuntu1" + "x11proto-randr-dev": "1.4.0+git20120101.is.really.1.4.0-0ubuntu1" + "lib32z1": "1:1.2.8.dfsg-1ubuntu1" + "librest-extras-0.7-0": "0.7.90-0ubuntu1" + "libmono-system-json-microsoft4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libgnome-keyring0-dbg": "3.8.0-2" + "libiec61883-0": "1.2.0-0.1ubuntu3" + "xserver-xorg-input-synaptics-lts-quantal": "3:5" + "zsh-dev": "5.0.2-3ubuntu6" + "idle-python3.4": "3.4.0-2ubuntu1" + "libmono-system-web-routing4.0-cil": "3.2.8+dfsg-4ubuntu1" + "geoclue-examples": "0.12.99-3ubuntu1" + "libdatrie1": "0.2.8-1" + "libgcrypt11": "1.5.3-2ubuntu4" + "wfaroese": "0.4.2-1" + "libdjvulibre-dev": "3.5.25.4-3" + "libsubunit0": "0.0.18-0ubuntu7" + "libxkbcommon-x11-dev": "0.4.1-0ubuntu1" + "libgtksourceview-3.0-common": "3.10.2-0ubuntu1" + "phonon-backend-gstreamer1.0-dbg": "4:4.7.1+git20140403-0ubuntu1" + "bacula-common-mysql-dbg": "5.2.6+dfsg-9.1ubuntu3" + "gir1.2-colorhug-1.0": "1.0.6-1" + "libiodbc2": "3.52.7-3.1" + "libplist-dbg": "1.10-1" + "libgtest-dev": "1.6.0-1ubuntu6" + "libreoffice-common": "1:4.2.3~rc3-0ubuntu2" + "libreoffice-l10n-uz": "1:4.2.3~rc3-0ubuntu1" + "myspell-el-gr": "0.8-2" + "pkg-kde-tools": "0.15.12ubuntu1" + "librarian-dev": "0.8.1-5ubuntu1" + "libunbound-dev": "1.4.22-1ubuntu4" + "language-pack-gnome-ml-base": "1:14.04+20140410" + "myspell-st": "20070206-4" + "python-gnome2-doc": "2.28.1+dfsg-1ubuntu2" + "rabbitmq-server": "3.3.4-1" + "exim4-dev": "4.82-3ubuntu2" + "udisks2-doc": "2.1.3-1" + "libpython2.7-dbg": "2.7.6-8" + "libsocket6-perl": "0.25-1" + "libapt-pkg4.12": "1.0.1ubuntu2" + "libhud-gtk1-dev": "13.10.1+14.04.20140402-0ubuntu1" + "libmdb2": "0.7.1-1ubuntu1" + "language-pack-vi": "1:14.04+20140410" + "libclass-accessor-perl": "0.34-1" + "libcwidget-doc": "0.5.16-3.5ubuntu1" + "texlive-science-doc": "2013.20140215-2" + "xorg-docs-core": "1:1.7-1" + "libwebkit-dev": "2.4.0-1ubuntu2" + "python-cl": "0.0.3-1" + "libkmod2": "15-0ubuntu6" + "xmlto": "0.0.25-2" + "biosdevname": "0.4.1-0ubuntu6" + "liblttng-ust0": "2.4.0-4ubuntu1" + "libqt5svg5-dev": "5.2.1-1" + "fltk1.1-doc": "1.1.10-17" + "im-config": "0.24-1ubuntu4" + "language-pack-gnome-gu": "1:14.04+20140410" + "language-pack-mhr-base": "1:14.04+20140410" + "libvigraimpex-doc": "1.10.0+dfsg-3ubuntu2" + "libupstart1": "1.12.1-0ubuntu4" + "language-pack-gnome-rw-base": "1:14.04+20140410" + "lsb-cxx": "4.1+Debian11ubuntu6" + "qt4-bin-dbg": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "thunderbird-locale-bn-bd": "1:24.4.0+build1-0ubuntu1" + "libfcgi-dev": "2.4.0-8.1ubuntu5" + "python-tk": "2.7.5-1ubuntu1" + "language-pack-gnome-tt": "1:14.04+20140410" + "language-pack-gnome-hr-base": "1:14.04+20140410" + "ruby1.9.1": "1.9.3.484-2ubuntu1" + "w3m": "0.5.3-15" + "xserver-xorg-video-openchrome-lts-raring": "3:5" + "libcommons-compress-java": "1.6-1" + "munin-plugins-core": "2.0.19-3" + "genext2fs": "1.4.1-4build1" + "gstreamer-tools": "0.10.36-1.2ubuntu3" + "language-pack-gnome-ko-base": "1:14.04+20140410" + "libapache2-mod-auth-plain": "2.0.52" + "gir1.2-glib-2.0": "1.40.0-1" + "libblkid1": "2.20.1-5.1ubuntu20.1" + "libdrm-radeon1": "2.4.52-1" + "srvadmin-xmlsup": "7.1.0-2" + "xserver-xorg-dev-lts-saucy": "3:5" + "language-pack-nn": "1:14.04+20140410" + "language-pack-tl": "1:14.04+20140410" + "libipc-signal-perl": "1.00-6" + "firefox-locale-gu": "28.0+build2-0ubuntu2" + "gstreamer1.0-plugins-base-dbg": "1.2.3-1" + "sssd-ldap": "1.11.5-1ubuntu3" + "time": "1.7-24" + "xserver-xorg-input-mouse-lts-saucy": "3:5" + "language-pack-bem": "1:14.04+20140410" + "language-pack-gnome-lb-base": "1:14.04+20140410" + "liberror-perl": "0.17-1.1" + "python-urllib3": "1.7.1-1build1" + "linux-signed-image-generic-lts-saucy": "3.13.0.24.28" + "language-pack-gnome-bem-base": "1:14.04+20140410" + "python-secretstorage-doc": "2.0.0-1ubuntu1" + "librpmsign1": "4.11.1-3" + "python3-pyqt4.qtopengl-dbg": "4.10.4+dfsg-1ubuntu1" + "telepathy-gabble": "0.18.2-1" + "fonts-mgopen": "1.1-9" + "python-oauth": "1.0.1-3build2" + "libattica0.4": "0.4.2-1" + "libtag1-dev": "1.9.1-2" + "rbd-fuse": "0.79-0ubuntu1" + "libreoffice-l10n-ast": "1:4.2.3~rc3-0ubuntu1" + "apache2-mpm-worker": "2.4.7-1ubuntu4" + "python3-markupsafe": "0.18-1build2" + "libiw-dev": "30~pre9-8ubuntu1" + "libmono-microsoft-build-tasks-v4.0-4.0-cil": "3.2.8+dfsg-4ubuntu1" + "wmanx": "0.50-11" + "libaccounts-qt5-1": "1.11+14.04.20140410.1-0ubuntu1" + "libftdipp-dev": "0.20-1ubuntu1" + "libgcj-bc": "4.8.2-1ubuntu6" + "libhfsp-dev": "1.0.4-12.1" + "libstonith1-dev": "1.0.11+hg2754-1.1build1" + "libhogweed2": "2.7.1-1" + "libpoppler-qt5-1": "0.24.5-2ubuntu4" + "libspice-server-dev": "0.12.4-0nocelt2" + "language-pack-ug-base": "1:14.04+20140410" + "libexttextcat-data": "3.4.3-1ubuntu1" + "python-markdown": "2.4-1" + "libdb5.3-java-gcj": "5.3.28-3ubuntu3" + "libgpm-dev": "1.20.4-6.1" + "libxcb-util0": "0.3.8-2ubuntu1" + "remmina-plugin-vnc": "1.0.0-4ubuntu3" + "transmission-common": "2.82-1.1ubuntu3" + "libatk-wrapper-java-jni": "0.30.4-4" + "guile-2.0-doc": "2.0.9+1-1ubuntu1" + "valac-0.18-dbg": "0.18.1-0ubuntu11" + "python3-pyqt5.qtxmlpatterns": "5.2.1+dfsg-1ubuntu1" + "language-pack-se": "1:14.04+20140410" + "libgconf2.0-cil-dev": "2.24.2-3" + "bamfdaemon": "0.5.1+14.04.20140409-0ubuntu1" + "liblttng-ust-dev": "2.4.0-4ubuntu1" + "nagios3-core": "3.5.1-1ubuntu1" + "fonts-khmeros": "5.0-7ubuntu1" + "libldl2.1.0": "1:4.2.1-3ubuntu1" + "libpcre3-dev": "1:8.31-2ubuntu2" + "language-pack-gnome-ts": "1:14.04+20140410" + "firefox-locale-mn": "28.0+build2-0ubuntu2" + "gnome-system-log": "3.8.1-1svn1" + "libclick-0.4-0": "0.4.21.1" + "linux-signed-generic": "3.13.0.24.28" + "hunspell-ml": "0.1-2" + "python-apt-dev": "0.9.3.5" + "python-seamicroclient": "0.2.0-0ubuntu1" + "libapache2-mod-apparmor": "2.8.95~2430-0ubuntu5" + "libdjvulibre21": "3.5.25.4-3" + "language-pack-ms-base": "1:14.04+20140410" + "libwebkitgtk-1.0-common": "2.4.0-1ubuntu2" + "libmagic1": "1:5.14-2ubuntu3.1" + "libp11-kit-dev": "0.20.2-2ubuntu2" + "librdf0": "1.0.17-1" + "app-install-data-partner": "13.04" + "python-extras": "0.0.3-2ubuntu1" + "binutils-dev": "2.24-5ubuntu3" + "mtools": "4.0.18-1ubuntu1" + "python-qt4": "4.10.4+dfsg-1ubuntu1" + "language-pack-en": "1:14.04+20140707" + "klibc-utils": "2.0.3-0ubuntu1" + "rsync": "3.1.0-2ubuntu0.1" + "thunderbird-locale-mk": "1:24.4.0+build1-0ubuntu1" + "python-qt4-dbg": "4.10.4+dfsg-1ubuntu1" + "libxorg-gtest-dev": "0.7.1-0ubuntu1" + "python-happybase": "0.7-1build1" + "libassuan0-dbg": "2.1.1-1ubuntu1" + "libpengine4": "1.1.10+git20130802-1ubuntu2" + "libqt5quickparticles5": "5.2.1-3ubuntu15" + "libjbig2dec0": "0.11+20120125-1ubuntu1" + "libstonithd2": "1.1.10+git20130802-1ubuntu2" + "language-pack-gnome-ne": "1:14.04+20140410" + "language-pack-ia-base": "1:14.04+20140410" + "libhook-lexwrap-perl": "0.24-1" + "ttf-dejavu": "2.34-1ubuntu1" + "gir1.2-soup-2.4": "2.44.2-1ubuntu2" + "hunspell-be": "0.53-3" + "libtext-soundex-perl": "3.4-1build1" + "language-pack-gnome-kn-base": "1:14.04+20140410" + "libbonoboui2-common": "2.24.5-0ubuntu3" + "libedata-cal-1.2-23": "3.10.4-0ubuntu1" + "liblouis-dev": "2.5.3-2ubuntu1" + "libnatpmp1": "20110808-3ubuntu2" + "language-pack-gnome-ms-base": "1:14.04+20140410" + "notify-osd-icons": "0.8+14.04.20131204-0ubuntu1" + "libdbus-1-dev": "1.6.18-0ubuntu4" + "ceilometer-api": "2014.1-0ubuntu1" + "language-pack-nl-base": "1:14.04+20140410" + "strace": "4.8-1ubuntu5" + "python-utidylib": "0.2-9build1" + "apache2.2-bin": "2.4.7-1ubuntu4" + "libgdk-pixbuf2.0-0-dbg": "2.30.7-0ubuntu1" + "libroken18-heimdal": "1.6~git20131207+dfsg-1ubuntu1" + "libsasl2-modules": "2.1.25.dfsg1-17build1" + "linux-tools-3.13.0-24-generic": "3.13.0-24.46" + "python3-yaml": "3.10-4build4" + "fonts-takao-pgothic": "003.02.01-9ubuntu2" + "language-pack-gnome-eo-base": "1:14.04+20140410" + "libclutter-1.0-doc": "1.16.4-0ubuntu2" + "libelf1": "0.158-0ubuntu5" + "libp11-2-dbg": "0.2.8-3ubuntu1" + "python-eventlet": "0.13.0-1ubuntu2" + "libzeitgeist-2.0-0-dbg": "0.9.14-0ubuntu4" + "python-ogg": "1.3+repack-5ubuntu2" + "ocfs2console": "1.6.4-3ubuntu1" + "yelp": "3.10.2-0ubuntu1" + "docutils-common": "0.11-3" + "language-pack-gnome-lo": "1:14.04+20140410" + "libio-stringy-perl": "2.110-5" + "libdee-qt4-dev": "3.3+14.04.20140317-0ubuntu1" + "libmount1": "2.20.1-5.1ubuntu20.1" + "libmono-cscompmgd8.0-cil": "3.2.8+dfsg-4ubuntu1" + "cpp": "4:4.8.2-1ubuntu6" + "lib32gfortran3-dbg": "4.8.2-19ubuntu1" + "libmono-2.0-dev": "3.2.8+dfsg-4ubuntu1" + "texlive-metapost-doc": "2013.20140215-1" + "firefox-locale-vi": "28.0+build2-0ubuntu2" + "dbus-x11": "1.6.18-0ubuntu4" + "liblircclient-dev": "0.9.0-0ubuntu5" + "python-all-dev": "2.7.5-5ubuntu3" + "libregexp-common-perl": "2013031301-1" + "libexempi-dev": "2.2.1-1ubuntu1" + "libvte-2.90-9": "1:0.34.9-1ubuntu1" + "lib32objc4-dbg": "4.8.2-19ubuntu1" + "libncursesw5": "5.9+20140118-1ubuntu1" + "libnspr4-dbg": "2:4.10.2-1ubuntu1" + "libqt4-declarative": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "linux-image-generic-lts-saucy": "3.13.0.24.28" + "ant-optional": "1.9.3-2build1" + "python-htmlgen": "2.2.2-12.1ubuntu1" + "firefox-locale-lv": "28.0+build2-0ubuntu2" + "libavahi-core7": "0.6.31-4ubuntu1" + "netbase": "5.2" + "libblkid-dev": "2.20.1-5.1ubuntu20" + "gcj-4.8-source": "4.8.2-19ubuntu1" + "libxext-doc": "2:1.3.2-1" + "nabi": "1.0.0-1" + "python-aptdaemon.gtk3widgets": "1.1.1-1ubuntu5" + "python-paste": "1.7.5.1-6ubuntu3" + "libxt6-dbg": "1:1.1.4-1" + "sp": "1.3.4-1.2.1-47.3ubuntu1" + "language-pack-gnome-sd-base": "1:14.04+20140410" + "libapt-pkg-dev": "1.0.1ubuntu2" + "libatk-bridge2.0-0-dbg": "2.10.2-2ubuntu1" + "libnfsidmap-dev": "0.25-5" + "librbd-dev": "0.79-0ubuntu1" + "liblangtag1": "0.5.1-2" + "libsigc++-2.0-dev": "2.2.10-0.2ubuntu2" + "shotwell-dbg": "0.18.0-0ubuntu4" + "language-pack-rw-base": "1:14.04+20140410" + "language-pack-shs-base": "1:14.04+20140410" + "ssh": "1:6.6p1-2ubuntu2" + "evolution-plugins": "3.10.4-0ubuntu1" + "libboost-chrono-dev": "1.54.0.1ubuntu1" + "gir1.2-telepathylogger-0.2": "0.8.0-3" + "libcdr-doc": "0.0.15-1ubuntu1" + "libfile-mimeinfo-perl": "0.22-1" + "libgcc-4.8-dev-armhf-cross": "4.8.2-16ubuntu4cross0.11" + "libraptor2-doc": "2.0.13-1" + "devio": "1.2-1build2" + "rhythmbox-plugin-zeitgeist": "3.0.2-0ubuntu1" + "xserver-xorg-video-cirrus-lts-raring": "3:5" + "libxmu-headers": "2:1.1.1-1" + "ttf-wqy-microhei": "0.2.0-beta-2" + "dnsmasq-base": "2.68-1" + "icedtea-7-jre-jamvm": "7u51-2.4.6-1ubuntu4" + "postfix-pgsql": "2.11.0-1" + "libreoffice-l10n-ru": "1:4.2.3~rc3-0ubuntu1" + "libgpod4-nogtk": "0.8.3-4ubuntu3" + "libxkbcommon-dev": "0.4.1-0ubuntu1" + "sunpinyin-utils": "2.0.3+git20130507-1ubuntu1" + "xserver-xorg-video-dummy-lts-raring": "3:5" + "grub": "0.97-29ubuntu66" + "sqlite3": "3.8.2-1ubuntu2" + "ufw": "0.34~rc-0ubuntu2" + "libgtkspell3-3-dev": "3.0.4-1" + "libstreams0": "0.7.8-1ubuntu2" + "libreoffice-l10n-en-gb": "1:4.2.3~rc3-0ubuntu1" + "libgstreamer-plugins-good1.0-0": "1.2.3-1ubuntu2" + "libindicator7": "12.10.2+14.04.20140402-0ubuntu1" + "libitm1-dbg": "4.8.2-19ubuntu1" + "python-cxx-dev": "6.2.5-1ubuntu2" + "libgfortran-4.7-dev": "4.7.3-12ubuntu1" + "python-egenix-mxurl": "3.2.7-1build1" + "latex-xcolor": "2.11-1.1" + "libreoffice-l10n-zh-tw": "1:4.2.3~rc3-0ubuntu1" + "grub2-common": "2.02~beta2-9ubuntu1" + "libbsd0-dbg": "0.6.0-2ubuntu1" + "language-pack-ts": "1:14.04+20140410" + "libmono-system-servicemodel4.0a-cil": "3.2.8+dfsg-4ubuntu1" + "x11proto-fonts-dev": "2.1.2-1" + "libgee2-dbg": "0.6.8-1ubuntu1" + "thunderbird-locale-ka": "1:24.4.0+build1-0ubuntu1" + "xserver-xorg-video-s3-lts-saucy": "3:5" + "libc6-dev-armhf-cross": "2.19-0ubuntu2cross1.104" + "texlive-humanities-doc": "2013.20140215-2" + "libunity-webapps0": "2.5.0~+14.04.20140409-0ubuntu1" + "libxcb-sync1": "1.10-2ubuntu1" + "thunderbird-locale-nb": "1:24.4.0+build1-0ubuntu1" + "docbook-xsl": "1.78.1+dfsg-1" + "libcapture-tiny-perl": "0.24-1" + "liblingua-en-inflect-perl": "1.895-1" + "libmagickcore5-extra": "8:6.7.7.10-6ubuntu3" + "language-pack-aa-base": "1:14.04+20140410" + "language-pack-gnome-sk": "1:14.04+20140410" + "libfolks25": "0.9.5-1ubuntu5" + "libtcmalloc-minimal4": "2.1-2ubuntu1" + "python-greenlet-dev": "0.4.2-1build1" + "language-pack-gnome-si-base": "1:14.04+20140410" + "python-celery": "3.1.6-1ubuntu1" + "libtasn1-6": "3.4-3" + "qtbase5-examples-dbg": "5.2.1+dfsg-1ubuntu14" + "raptor2-utils": "2.0.13-1" + "libdevel-stacktrace-perl": "1.3000-1" + "libprobe-perl-perl": "0.03-1" + "libfreetype6": "2.5.2-1ubuntu2" + "language-pack-gnome-csb-base": "1:14.04+20140410" + "language-pack-gnome-kw-base": "1:14.04+20140410" + "python-polib-doc": "1.0.4-1" + "libreoffice-l10n-dz": "1:4.2.3~rc3-0ubuntu1" + "crda": "1.1.2-1ubuntu2" + "libvdpau1": "0.7-1" + "xserver-xorg-video-modesetting-lts-quantal": "3:5" + "language-pack-gnome-vi": "1:14.04+20140410" + "cyrus-sasl2-heimdal-dbg": "2.1.25.dfsg1-17build1" + "printer-driver-hpcups": "3.14.3-0ubuntu3" + "libcglib-java-doc": "2.2.2+dfsg-5" + "libmono-ldap2.0-cil": "3.2.8+dfsg-4ubuntu1" + "bsdutils": "1:2.20.1-5.1ubuntu20" + "drac-dev": "1.12-8build1" + "libasn1-8-heimdal": "1.6~git20131207+dfsg-1ubuntu1" + "libmono-system-servicemodel-web4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libgutenprint-dev": "5.2.10~pre2-0ubuntu2" + "libice6": "2:1.0.8-2" + "libtimezonemap1": "0.4.1" + "sgml-base": "1.26+nmu4ubuntu1" + "libclutter-gtk-1.0-dbg": "1.4.4-3ubuntu2" + "libdee-qt5-3": "3.3+14.04.20140317-0ubuntu1" + "libpam-krb5": "4.6-2" + "libqtwebkit4-perl": "4:4.13.0-0ubuntu1" + "libmono-relaxng4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libdb5.3-java-dev": "5.3.28-3ubuntu3" + "gcc-4.7-multilib": "4.7.3-12ubuntu1" + "libunity-misc-dev": "4.0.5+14.04.20140115-0ubuntu1" + "rsync": "3.1.0-2" + "language-pack-gnome-ig-base": "1:14.04+20140410" + "language-pack-mi": "1:14.04+20140410" + "libjs-sphinxdoc": "1.2.2+dfsg-1ubuntu1" + "libreoffice-l10n-ml": "1:4.2.3~rc3-0ubuntu1" + "erlang-edoc": "1:16.b.3-dfsg-1ubuntu2" + "socat": "1.7.2.3-1" + "language-pack-ga-base": "1:14.04+20140410" + "libcdparanoia0": "3.10.2+debian-11" + "libqt4-dev-bin": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "xserver-xorg-video-ati-lts-quantal": "3:5" + "thunderbird-locale-sv": "1:24.4.0+build1-0ubuntu1" + "language-pack-gnome-am": "1:14.04+20140410" + "language-pack-ps": "1:14.04+20140410" + "gcj-jre": "4:4.8.2-1ubuntu6" + "libqt5opengl5": "5.2.1+dfsg-1ubuntu14" + "nfs-common": "1:1.2.8-6ubuntu1" + "latex-beamer": "3.24-1" + "python3-jinja2": "2.7.2-2" + "myspell-pt-pt": "20091013-4" + "prosper": "1.00.4+cvs.2007.05.01-4" + "libsmokeqtuitools4-3": "4:4.13.0-0ubuntu1" + "libasm3-java": "3.3.2-2" + "libboost-thread1.54.0": "1.54.0-4ubuntu3.1" + "language-pack-gnome-de": "1:14.04+20140410" + "firefox-locale-gl": "28.0+build2-0ubuntu2" + "indicator-appmenu": "13.01.0+14.04.20140404-0ubuntu1" + "libgail-common": "2.24.23-0ubuntu1" + "qtxmlpatterns5-dbg": "5.2.1-3" + "bsh": "2.0b4-15" + "libmono-system-serviceprocess4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libarchive-dev": "3.1.2-7ubuntu2" + "postgresql-plperl-9.3": "9.3.4-1" + "libreoffice-help-sv": "1:4.2.3~rc3-0ubuntu1" + "ubuntu-docs": "14.04.3" + "android-tools-fsutils": "4.2.2+git20130218-3ubuntu23" + "libgvnc-1.0-0-dbg": "0.5.3-0ubuntu2" + "libxmuu-dev": "2:1.1.1-1" + "language-pack-ia": "1:14.04+20140410" + "libgconf2-doc": "3.2.6-0ubuntu2" + "logstash-contrib": "1.4.2-1-efd53ef" + "fonts-tlwg-mono": "1:0.5.1-3" + "dvd+rw-tools": "7.1-10build1" + "libdecoration0": "1:0.9.11+14.04.20140409-0ubuntu1" + "libmpdec-dev": "2.4.0-6" + "libpisock-dev": "0.12.5-6ubuntu2" + "libstax-java": "1.2.0-3build1" + "libsmokeqtsvg4-3": "4:4.13.0-0ubuntu1" + "python-twisted-runner": "13.2.0-1ubuntu1" + "libjson-c-doc": "0.11-3ubuntu1" + "firefox-locale-km": "28.0+build2-0ubuntu2" + "bin86": "0.16.17-3.1ubuntu3" + "kexec-tools": "1:2.0.6-0ubuntu2" + "resource-agents": "1:3.9.3+git20121009-3ubuntu2" + "diveintopython-zh": "5.4b-1" + "fonts-pagul": "1.0-7" + "language-pack-gnome-zh-hans": "1:14.04+20140410" + "libdpkg-perl": "1.17.5ubuntu5" + "libpango1.0-doc": "1.36.3-1ubuntu1" + "srvadmin-tomcat": "7.1.0-5" + "dh-make": "0.63" + "libqt4-sql-sqlite": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "libstartup-notification0-dev": "0.12-3ubuntu1" + "php5-curl": "5.5.9+dfsg-1ubuntu4" + "zerofree": "1.0.2-1ubuntu1" + "libappindicator0.1-cil-dev": "12.10.1+13.10.20130920-0ubuntu4" + "python-decorator": "3.4.0-2build1" + "libxml2-utils-dbg": "2.9.1+dfsg1-3ubuntu4" + "libibverbs1": "1.1.7-1ubuntu1" + "libpcrecpp0": "1:8.31-2ubuntu2" + "libunity-action-qt1-dev": "1.1.0+14.04.20140304-0ubuntu1" + "idle3": "3.4.0-0ubuntu2" + "openjdk-7-doc": "7u51-2.4.6-1ubuntu4" + "texlive-generic-recommended": "2013.20140215-1" + "libgpod4": "0.8.3-4ubuntu3" + "libgraphite2-3": "1.2.4-1ubuntu1" + "ltsp-server-standalone": "5.5.1-1ubuntu2" + "python3-problem-report": "2.14.1-0ubuntu3" + "libjson-perl": "2.61-1" + "language-pack-gnome-wo-base": "1:14.04+20140410" + "libpython3.4-stdlib": "3.4.0-2ubuntu1" + "xserver-xorg-input-wacom-lts-quantal-dbg": "3:5" + "python-curtin": "0.1.0~bzr126-0ubuntu1" + "libxapian22": "1.2.16-2ubuntu1" + "rdiff": "0.9.7-10" + "junit-doc": "3.8.2-8build1" + "enchant": "1.6.0-10ubuntu1" + "gvfs-dbg": "1.20.1-1ubuntu1" + "libkdeclarative5": "4:4.13.0-0ubuntu1" + "liblightdm-qt5-3-dev": "1.10.0-0ubuntu3" + "libfs-dev": "2:1.0.5-1" + "libreadonly-xs-perl": "1.05-1" + "libsmokeqtopengl4-3": "4:4.13.0-0ubuntu1" + "thunderbird-locale-sk": "1:24.4.0+build1-0ubuntu1" + "camlp4": "4.01.0-3ubuntu3" + "fetchmail": "6.3.26-1" + "gvfs-daemons": "1.20.1-1ubuntu1" + "libidn11-dev": "1.28-1ubuntu2" + "php5-snmp": "5.5.9+dfsg-1ubuntu4" + "wcatalan": "0.20111230b-4" + "liblwres90": "1:9.9.5.dfsg-3" + "rrdtool-tcl": "1.4.7-2ubuntu5" + "language-pack-ar-base": "1:14.04+20140410" + "libcommons-logging-java-doc": "1.1.3-1" + "squid3-common": "3.3.8-1ubuntu6" + "libgstreamer-plugins-base1.0-0": "1.2.3-1" + "libxklavier-dev": "5.4-0ubuntu1" + "totem-dbg": "3.10.1-1ubuntu4" + "libdatrie-doc": "0.2.8-1" + "powernap-server": "2.18-0ubuntu2" + "cpp-4.8-arm-linux-gnueabihf": "4.8.2-16ubuntu4cross0.11" + "cracklib-runtime": "2.9.1-1build1" + "libgtkmm-3.0-1": "3.10.1-0ubuntu2" + "libmono-system-data-datasetextensions4.0-cil": "3.2.8+dfsg-4ubuntu1" + "myspell-es": "1.11-4" + "libslang2-pic": "2.2.4-15ubuntu1" + "libxcb-glx0-dev": "1.10-2ubuntu1" + "hunspell-br": "0.11-1" + "binutils-source": "2.24-5ubuntu3" + "ppp-dev": "2.4.5-5.1ubuntu2" + "sssd-ad": "1.11.5-1ubuntu3" + "libdrm2-dbg": "2.4.52-1" + "libwind0-heimdal": "1.6~git20131207+dfsg-1ubuntu1" + "xfsdump": "3.1.1ubuntu2" + "language-pack-gnome-ky-base": "1:14.04+20140410" + "python-debian": "0.1.21+nmu2ubuntu2" + "python-oslosphinx": "2.0-0ubuntu2" + "wamerican-insane": "7.1-1" + "libpangocairo-1.0-0": "1.36.3-1ubuntu1" + "guile-2.0-libs": "2.0.9+1-1ubuntu1" + "libboost-filesystem1.54.0": "1.54.0-4ubuntu3" + "libxaw7": "2:1.0.12-1" + "default-jdk-doc": "0.51" + "hevea": "2.09-2" + "language-pack-ht-base": "1:14.04+20140410" + "language-pack-uk-base": "1:14.04+20140410" + "myspell-pt": "20091013-4" + "python-ldap": "2.4.10-1build1" + "language-pack-gnome-pa-base": "1:14.04+20140410" + "firefox-locale-eo": "28.0+build2-0ubuntu2" + "gnome-icon-theme": "3.10.0-0ubuntu2" + "myspell-hr": "20060617-2.4" + "libtotem0": "3.10.1-1ubuntu4" + "libdatetime-timezone-perl": "1:1.63-1+2013h" + "gettext-base": "0.18.3.1-1ubuntu2" + "gir1.2-totem-plparser-1.0": "3.10.2-0ubuntu1" + "libboost-dev": "1.54.0.1ubuntu1" + "unity-webapps-qml-examples": "0.1+14.04.20140408-0ubuntu1" + "language-pack-ss-base": "1:12.04+20120417" + "libxml-filter-buffertext-perl": "1.01-5" + "libido3-0.1-0": "13.10.0+14.04.20140407-0ubuntu1" + "libxcomposite-dev": "1:0.4.4-1" + "openjdk-7-jre-headless": "7u51-2.4.6-1ubuntu4" + "hunspell-de-ch": "20120607-1" + "language-pack-fur": "1:14.04+20140410" + "gir1.2-gnomebluetooth-1.0": "3.8.2.1-0ubuntu4" + "libframe-dev": "2.5.0daily13.06.05-0ubuntu1" + "libxpm4-dbg": "1:3.5.10-1" + "libstring-format-perl": "1.17-1" + "libsss-idmap0": "1.11.5-1ubuntu3" + "thunderbird-locale-zh-hans": "1:24.4.0+build1-0ubuntu1" + "libvala-0.18-dev": "0.18.1-0ubuntu11" + "libgsf-1-common": "1.14.27-2ubuntu2" + "libtest-pod-coverage-perl": "1.08-4" + "printer-driver-foo2zjs-common": "20140209dfsg0-1ubuntu1" + "python-prettytable": "0.7.2-2ubuntu2" + "python-pycadf": "0.4.1-0ubuntu1" + "ubiquity-slideshow-ubuntu": "83" + "libapt-pkg4.12": "1.0.1ubuntu2.1" + "libglapi-mesa-lts-raring": "3:5" + "libxp6-dbg": "1:1.0.2-1ubuntu1" + "xserver-xorg-input-wacom-lts-saucy-dbg": "3:5" + "linux-generic-lts-raring": "3.13.0.24.28" + "aptdaemon": "1.1.1-1ubuntu5" + "python-netaddr-docs": "0.7.10-1build1" + "default-jre": "2:1.7-51" + "libgl1-mesa-dev-lts-raring": "3:5" + "libgweather-3-6": "3.10.2-0ubuntu1" + "libatomic1-ppc64el-cross": "4.8.2-16ubuntu4cross0.4" + "myspell-bg": "4.1-3ubuntu1" + "mythes-ne": "1:4.2.1-0ubuntu1" + "libisl10": "0.12.2-1" + "thunderbird-locale-af": "1:24.4.0+build1-0ubuntu1" + "firefox-locale-kk": "28.0+build2-0ubuntu2" + "libxmu6-dbg": "2:1.1.1-1" + "lshw": "02.16-2ubuntu1" + "opencryptoki-dbg": "2.3.1+dfsg-3ubuntu5" + "python3-simplejson-dbg": "3.3.1-1ubuntu6" + "python-egenix-mx-base-dev": "3.2.7-1build1" + "openvswitch-controller": "2.0.1+git20140120-0ubuntu2" + "thunderbird-locale-ro": "1:24.4.0+build1-0ubuntu1" + "librrd4": "1.4.7-2ubuntu5" + "xserver-xorg-video-dummy-lts-saucy": "3:5" + "libnet-cidr-perl": "0.17-1" + "python-neutronclient": "1:2.3.4-0ubuntu1" + "libsybdb5": "0.91-5" + "libpod-readme-perl": "0.11-1" + "vim-gui-common": "2:7.4.052-1ubuntu3" + "gvfs": "1.20.1-1ubuntu1" + "glib-networking-common": "2.40.0-1" + "python-serial": "2.6-1build1" + "libfontforge1": "20120731.b-5" + "libnss-mdns": "0.10-6" + "libprelude2-dbg": "1.0.0-11ubuntu4" + "libreoffice-voikko": "4.0-1" + "language-pack-gnome-ff": "1:14.04+20140410" + "language-pack-gnome-mt-base": "1:14.04+20140410" + "swig2.0-examples": "2.0.11-1ubuntu2" + "libknewstuff3-4": "4:4.13.0-0ubuntu1" + "liblangtag-gobject0": "0.5.1-2" + "python-samba": "2:4.1.6+dfsg-1ubuntu2" + "fontforge-nox": "20120731.b-5" + "gtk-3-examples": "3.10.8-0ubuntu1" + "libavahi-common-dev": "0.6.31-4ubuntu1" + "libcwidget-dev": "0.5.16-3.5ubuntu1" + "libppl-dev": "1:1.1-1ubuntu1" + "libxcb-keysyms1": "0.3.9-1ubuntu1" + "linux-libc-dev": "3.13.0-24.46" + "python-ldb": "1:1.1.16-1" + "gimp-help-sv": "2.6.1-1" + "libthai-doc": "0.1.20-3" + "grub-efi-amd64-dbg": "2.02~beta2-9" + "libgail-dev": "2.24.23-0ubuntu1" + "libmedia1": "0.1.0+git20131207+e452e83-0ubuntu12" + "libblas-doc": "1.2.20110419-7" + "python-cliff": "1.4.5-1ubuntu2" + "indicator-messages": "13.10.1+14.04.20140410-0ubuntu1" + "libfriends-dev": "0.1.2+14.04.20131108.1-0ubuntu1" + "language-pack-pa": "1:14.04+20140410" + "software-properties-common": "0.92.37.1" + "update-notifier-common": "0.154.1" + "hyphen-pl": "1:3.0a-4" + "libsub-uplevel-perl": "0.2400-1" + "devscripts": "2.14.1" + "libgtkspell-dev": "2.0.16-1ubuntu7" + "libpython2.7-dev": "2.7.6-8" + "php5-dbg": "5.5.9+dfsg-1ubuntu4" + "fonts-nanum-coding": "2.0-6" + "libvirt-doc": "1.2.2-0ubuntu13" + "python-scripttest": "1.2-1build1" + "libclone-perl": "0.36-1" + "unity-scope-chromiumbookmarks": "0.1+13.10.20130723-0ubuntu1" + "libspeechd-dev": "0.8-5ubuntu1" + "nova-compute-kvm": "1:2014.1-0ubuntu1" + "bacula-console-qt": "5.2.6+dfsg-9.1ubuntu3" + "xserver-xorg-input-vmmouse-lts-saucy": "3:5" + "libxatracker1-lts-quantal": "3:5" + "ubiquity": "2.18.7" + "language-pack-gnome-os-base": "1:14.04+20140410" + "libbcmail-java-doc": "1.49+dfsg-2" + "sgml-data": "2.0.9-1" + "libqimageblitz-dev": "1:0.0.6-4build1" + "libqtnetwork4-perl": "4:4.13.0-0ubuntu1" + "click-dev": "0.4.21.1" + "info": "5.2.0.dfsg.1-2" + "libaccounts-qt-dev": "1.11+14.04.20140410.1-0ubuntu1" + "libdmraid1.0.0.rc16": "1.0.0.rc16-4.2ubuntu3" + "libx32quadmath0": "4.8.2-19ubuntu1" + "strongswan-plugin-gmp": "5.1.2-0ubuntu2" + "language-pack-gnome-fil-base": "1:14.04+20140410" + "language-pack-yi": "1:14.04+20140410" + "mythes-en-us": "1:4.2.1-0ubuntu1" + "python-nose-testconfig": "0.9-1" + "gir1.2-dbusmenu-glib-0.4": "12.10.3+14.04.20140319-0ubuntu1" + "sssd-ad-common": "1.11.5-1ubuntu3" + "iproute2-doc": "3.12.0-2" + "language-pack-kw": "1:14.04+20140410" + "language-pack-sc": "1:14.04+20140410" + "datefudge": "1.18ubuntu3" + "python-thrift": "0.9.0-1build1" + "libreoffice-l10n-nl": "1:4.2.3~rc3-0ubuntu1" + "postgresql-pltcl-9.3": "9.3.4-1" + "libleveldb1": "1.15.0-2" + "liblttng-ust-ctl2": "2.4.0-4ubuntu1" + "libaudiofile1": "0.3.6-2" + "linux-generic-lts-trusty": "3.13.0.24.28" + "thunderbird-locale-ta": "1:24.4.0+build1-0ubuntu1" + "aspell-en": "7.1-0-1" + "imagemagick-common": "8:6.7.7.10-6ubuntu3" + "language-pack-gnome-rw": "1:14.04+20140410" + "flac": "1.3.0-2" + "gstreamer1.0-x": "1.2.3-1" + "libxcb-doc": "1.10-2ubuntu1" + "libcanberra-gtk3-module": "0.30-0ubuntu3" + "libglew-dev": "1.10.0-3" + "python3-pymongo": "2.6.3-1build1" + "libdevel-cycle-perl": "1.11-2" + "ibmasm-utils": "3.0-1ubuntu11" + "libnet-dns-perl": "0.68-1.2build1" + "libmono-data-tds2.0-cil": "3.2.8+dfsg-4ubuntu1" + "ibus-gtk3": "1.5.5-1ubuntu3" + "libxapian-dev": "1.2.16-2ubuntu1" + "libfreerdp1": "1.0.2-2ubuntu1" + "libplatform-hardware-api-headers": "0.20+14.04.20140411-0ubuntu1" + "libsignon-qt5-1": "8.56+14.04.20140307-0ubuntu2" + "iproute": "1:3.12.0-2" + "language-pack-ar": "1:14.04+20140410" + "libcommons-logging-java": "1.1.3-1" + "libmono-system-reactive-debugger2.2-cil": "3.2.8+dfsg-4ubuntu1" + "python3-germinate": "2.16" + "libunbound2": "1.4.22-1ubuntu4" + "libgmp-dev": "2:5.1.3+dfsg-1ubuntu1" + "libsmokeqtdbus4-3": "4:4.13.0-0ubuntu1" + "lib32z1-dev": "1:1.2.8.dfsg-1ubuntu1" + "libkpty4": "4:4.13.0-0ubuntu1" + "libqt4-xmlpatterns-dbg": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "awstats": "7.2+dfsg-1" + "libstdc++-4.8-dev-powerpc-cross": "4.8.2-16ubuntu3cross0.11" + "spamassassin": "3.4.0-1ubuntu1" + "ubuntu-defaults-builder": "0.49" + "expect": "5.45-5ubuntu1" + "python3-pil.imagetk-dbg": "2.3.0-1ubuntu3" + "xapian-examples": "1.2.16-2ubuntu1" + "language-pack-sv-base": "1:14.04+20140410" + "g++": "4:4.8.2-1ubuntu6" + "gir1.2-evince-3.0": "3.10.3-0ubuntu10" + "gir1.2-gtk-3.0": "3.10.8-0ubuntu1" + "diffutils": "1:3.3-1" + "libavahi-compat-libdnssd-dev": "0.6.31-4ubuntu1" + "libdb5.3-sql": "5.3.28-3ubuntu3" + "lightdm": "1.10.0-0ubuntu3" + "python3-pyqt5.qtopengl": "5.2.1+dfsg-1ubuntu1" + "hunspell-sh": "1:3.3.0-2ubuntu3" + "language-pack-is": "1:14.04+20140410" + "libjs-jquery": "1.7.2+dfsg-2ubuntu1" + "libmspub-dev": "0.0.6-1ubuntu2" + "libpulse-dev": "1:4.0-0ubuntu11" + "python-sphinxbase-dbg": "0.8-0ubuntu10" + "libgegl-doc": "0.2.0-4ubuntu1" + "lsb": "4.1+Debian11ubuntu6" + "python-oslo.config": "1:1.2.1-0ubuntu2" + "wireless-regdb": "2013.02.13-1ubuntu1" + "libmdbsql2": "0.7.1-1ubuntu1" + "console-setup": "1.70ubuntu8" + "language-pack-so": "1:13.04+20130418" + "libreoffice-help-ca": "1:4.2.3~rc3-0ubuntu1" + "libopenvg1-mesa-lts-raring-dbg": "3:5" + "libx11-xcb-dev": "2:1.6.2-1ubuntu2" + "librest-doc": "0.7.90-0ubuntu1" + "mysql-server": "5.5.35+dfsg-1ubuntu1" + "vim-doc": "2:7.4.052-1ubuntu3" + "libcdio13": "0.83-4.1ubuntu1" + "libytnef0": "1.5-6" + "language-pack-hr-base": "1:14.04+20140410" + "libreoffice-help-de": "1:4.2.3~rc3-0ubuntu1" + "python-qt4-phonon-dbg": "4.10.4+dfsg-1ubuntu1" + "totem-mozilla": "3.10.1-1ubuntu4" + "friendly-recovery": "0.2.25" + "firefox-locale-ru": "28.0+build2-0ubuntu2" + "libqt53d5": "5.0~git20130731-0ubuntu5" + "linux-signed-image-3.13.0-24-generic": "3.13.0-24.46" + "language-pack-cv": "1:14.04+20140410" + "language-pack-km": "1:14.04+20140410" + "openssh-blacklist": "0.4.1+nmu1" + "libegl1-mesa-lts-saucy": "3:5" + "libobjc4-dbg": "4.8.2-19ubuntu1" + "xserver-xorg-video-intel-lts-quantal-dbg": "3:5" + "language-pack-gnome-fo": "1:14.04+20140410" + "libglm-dev": "0.9.5.1-1" + "xul-ext-mozvoikko": "2.0.1-0ubuntu1" + "gnome-session-canberra": "0.30-0ubuntu3" + "libcrmcommon3-dev": "1.1.10+git20130802-1ubuntu2" + "libfolks-eds-dbg": "0.9.5-1ubuntu5" + "linux-generic-lts-saucy": "3.13.0.24.28" + "util-linux": "2.20.1-5.1ubuntu20.1" + "libreoffice-l10n-mn": "1:4.2.3~rc3-0ubuntu1" + "python-hplefthandclient-doc": "1.0.1-1ubuntu1" + "erlang-gs": "1:16.b.3-dfsg-1ubuntu2" + "gir1.2-signon-1.0": "1.10daily13.06.25-0ubuntu2" + "libpopt0": "1.16-8ubuntu1" + "apt-clone": "0.3.1~ubuntu11" + "libreoffice-help-sk": "1:4.2.3~rc3-0ubuntu1" + "libreoffice-l10n-sr": "1:4.2.3~rc3-0ubuntu1" + "libgphoto2-dev-doc": "2.5.3.1-1ubuntu2" + "libsnmp-base": "5.7.2~dfsg-8.1ubuntu3" + "libtiff-doc": "4.0.3-7" + "libgirepository-1.0-1": "1.40.0-1" + "xserver-xorg-video-s3-lts-quantal": "3:5" + "libreoffice-l10n-da": "1:4.2.3~rc3-0ubuntu1" + "pastebinit": "1.4-3" + "gstreamer0.10-plugins-base-apps": "0.10.36-1.1ubuntu2" + "firefox-locale-ms": "28.0+build2-0ubuntu2" + "jigit": "1.19-2" + "librhythmbox-core8": "3.0.2-0ubuntu1" + "openstack-pkg-tools": "8" + "python-paramiko": "1.10.1-1git1build1" + "tcl-doc": "8.6.0+6ubuntu3" + "erlang-mnesia": "1:16.b.3-dfsg-1ubuntu2" + "firefox-globalmenu": "28.0+build2-0ubuntu2" + "hunspell-an": "0.2-1" + "libcommons-httpclient-java": "3.1-10.2" + "linux-virtual": "3.13.0.24.28" + "python-gpgme-dbg": "0.3-0ubuntu3" + "python-sip": "4.15.5-1build1" + "libterm-readkey-perl": "2.31-1" + "fonts-tlwg-typo": "1:0.5.1-3" + "libstdc++-4.8-dev-arm64-cross": "4.8.2-13ubuntu1cross0.11" + "python-gobject-dbg": "3.12.0-1" + "liblrmd1-dev": "1.1.10+git20130802-1ubuntu2" + "libqtdbusmock1": "0.2+14.04.20140304-0ubuntu1" + "ibus-anthy-dev": "1.5.4-2" + "libglewmx-dbg": "1.10.0-3" + "libxrandr-dev-lts-raring": "3:5" + "usbutils": "1:007-2ubuntu1" + "indicator-datetime": "13.10.0+14.04.20140415.3-0ubuntu1" + "libgbm1-lts-quantal-dbg": "3:5" + "lockfile-progs": "0.1.17" + "python-simplejson": "3.3.1-1ubuntu6" + "sosreport": "3.1-1ubuntu2" + "libisofs6": "1.3.4-0ubuntu1" + "python3-minimal": "3.4.0-0ubuntu2" + "language-selector-common": "0.129" + "libgmime-2.6-doc": "2.6.20-0ubuntu1" + "libmono-microsoft-build-framework4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libmono-system-web-dynamicdata4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libgtkmm-2.4-dev": "1:2.24.4-1ubuntu1" + "libipa-hbac-dev": "1.11.5-1ubuntu3" + "php5-pspell": "5.5.9+dfsg-1ubuntu4" + "libreoffice-impress": "1:4.2.3~rc3-0ubuntu2" + "odbcinst": "2.2.14p2-5ubuntu5" + "python-bs4": "4.2.1-1ubuntu2" + "gir1.2-cogl-1.0": "1.16.2-1" + "libgif4": "4.1.6-11" + "libgpod-cil-dev": "0.8.3-4ubuntu3" + "libklibc": "2.0.3-0ubuntu1" + "libpng12-dev": "1.2.50-1ubuntu2" + "xserver-xorg-video-r128-lts-saucy": "3:5" + "libjsch-java": "0.1.50-1ubuntu1" + "libnet-snmp-perl": "6.0.1-2" + "libqtgui4-perl": "4:4.13.0-0ubuntu1" + "u-boot-tools": "2013.10-3" + "pkg-create-dbgsym": "0.64" + "cups-filters": "1.0.52-0ubuntu1" + "libdb5.3-dbg": "5.3.28-3ubuntu3" + "libopenipmi0": "2.0.18-0ubuntu7" + "thunderbird-locale-cs": "1:24.4.0+build1-0ubuntu1" + "language-pack-cy-base": "1:14.04+20140410" + "libsvn-doc": "1.8.8-1ubuntu3" + "myspell-nb": "2.0.10-5.1" + "compiz-core": "1:0.9.11+14.04.20140409-0ubuntu1" + "libxrandr2": "2:1.4.2-1" + "openssl": "1.0.1f-1ubuntu2.4" + "gnomine": "1:3.10.1-0ubuntu1" + "intel-gpu-tools": "1.3-0ubuntu2" + "libdbus-glib-1-2": "0.100.2-1" + "firefox-locale-ka": "28.0+build2-0ubuntu2" + "linux-libc-dev-armel-cross": "3.13.0-12.32cross1.104" + "libisl-dbg": "0.12.2-1" + "libuninameslist0": "0.3.20130501-3" + "libwebkit2gtk-3.0-dev": "2.4.0-1ubuntu2" + "libfindlib-ocaml-dev": "1.4-2" + "libnm-glib-dev": "0.9.8.8-0ubuntu7" + "nbd-server": "1:3.7-1" + "obex-data-server": "0.4.6-0ubuntu2" + "python-gtk2": "2.24.0-3ubuntu3" + "language-pack-ig": "1:14.04+20140410" + "gir1.2-notify-0.7": "0.7.6-1ubuntu3" + "php5-sqlite": "5.5.9+dfsg-1ubuntu4" + "cinder-api": "1:2014.1-0ubuntu1" + "libjakarta-taglibs-standard-java": "1.1.2-2ubuntu1" + "sunpinyin-data": "0.1.22+20120112-1" + "libedata-book-1.2-20": "3.10.4-0ubuntu1" + "exim4": "4.82-3ubuntu2" + "libfile-basedir-perl": "0.03-1fakesync1" + "libwpd-doc": "0.9.9-1" + "ruby-indentation": "0.1.1-1" + "bluez": "4.101-0ubuntu13" + "libkemoticons4": "4:4.13.0-0ubuntu1" + "libmonoboehm-2.0-dev": "3.2.8+dfsg-4ubuntu1" + "libx32readline6": "6.3-4ubuntu2" + "python-gnome2-desktop-dev": "2.32.0+dfsg-3" + "qtmultimedia5-doc-html": "5.2.1-0ubuntu5" + "lib32stdc++6-4.7-dev": "4.7.3-12ubuntu1" + "libdebconfclient0-dev": "0.187ubuntu1" + "libhybris": "0.1.0+git20131207+e452e83-0ubuntu12" + "linux-tools-3.13.0-24-lowlatency": "3.13.0-24.46" + "python-rrdtool": "1.4.7-2ubuntu5" + "python3-coverage-dbg": "3.7.1+dfsg.1-1ubuntu2" + "sbsigntool": "0.6-0ubuntu7" + "xserver-xorg-video-glamoregl": "0.6.0-0ubuntu4" + "libgdata-common": "0.14.1-1" + "python3-aptdaemon.gtk3widgets": "1.1.1-1ubuntu5" + "libcheese-gtk-dev": "3.10.2-0ubuntu2" + "libdbusmenu-glib4": "12.10.3+14.04.20140319-0ubuntu1" + "libnss3-dbg": "2:3.15.4-1ubuntu7" + "grub-gfxpayload-lists": "0.6" + "libchewing3-dbg": "0.3.5-4build1" + "python-pyao-dbg": "0.82-5build1" + "wget": "1.15-1ubuntu1" + "libgdata-dev": "0.14.1-1" + "libphonon4qt5experimental-dev": "4:4.7.1-0ubuntu8" + "libumockdev0": "0.8.1-1" + "fonts-tlwg-typewriter": "1:0.5.1-3" + "gnome-terminal-data": "3.6.2-0ubuntu1" + "language-pack-tt": "1:14.04+20140410" + "php5": "5.5.9+dfsg-1ubuntu4" + "g++-powerpc-linux-gnu": "4:4.8.2-1" + "erlang-snmp": "1:16.b.3-dfsg-1ubuntu2" + "libidl0": "0.8.14-0.2ubuntu4" + "xserver-xorg-video-sis": "1:0.10.7-0ubuntu6" + "grub-pc": "2.02~beta2-9ubuntu1" + "upstart": "1.12.1-0ubuntu4" + "bind9-doc": "1:9.9.5.dfsg-3" + "fonts-sil-nuosusil": "2.1.1-7" + "libcommons-pool-java": "1.6-2" + "qtx11extras5-doc": "5.2.1-1" + "gcc-multilib": "4:4.8.2-1ubuntu6" + "libbcprov-java": "1.49+dfsg-2" + "exim4-dbg": "4.82-3ubuntu2" + "qtpim5-dev": "5.0~git20140203~e0c5eebe-0ubuntu2" + "libart2.0-cil": "2.24.2-3" + "ttf-punjabi-fonts": "1:0.5.14ubuntu1" + "x11proto-xf86dga-dev": "2.1-3" + "libsdl1.2-dev": "1.2.15-8ubuntu1" + "libmpc-dev": "1.0.1-1ubuntu1" + "libstdc++6-armhf-cross": "4.8.2-16ubuntu4cross0.11" + "python-boto": "2.20.1-2ubuntu2" + "libclick-0.4-dev": "0.4.21.1" + "libnewt0.52": "0.52.15-2ubuntu5" + "python-libxslt1-dbg": "1.1.28-2build1" + "libberkeleydb-perl": "0.54-1" + "libgl1-mesa-glx-lts-saucy": "3:5" + "liblqr-1-0": "0.4.1-2ubuntu1" + "diffutils-doc": "1:3.3-1" + "python-dbus-dev": "1.2.0-2build2" + "python-roman": "2.0.0-1" + "python3-doc": "3.4.0-0ubuntu2" + "gir1.2-gxps-0.1": "0.2.2-2ubuntu2" + "libxatracker-dev-lts-raring": "3:5" + "libmono-i18n-west2.0-cil": "3.2.8+dfsg-4ubuntu1" + "maas-dns": "1.5+bzr2252-0ubuntu1" + "cups-pk-helper": "0.2.5-0ubuntu1" + "python-pyxattr-dbg": "0.5.1-1.1build4" + "dh-python": "1.20140128-1ubuntu8" + "libreoffice-l10n-te": "1:4.2.3~rc3-0ubuntu1" + "wbritish": "7.1-1" + "at-spi2-core": "2.10.2.is.2.10.1-0ubuntu1" + "libmilter-dev": "8.14.4-4.1ubuntu1" + "gnome-doc-utils": "0.20.10-1build1" + "libconfig-inifiles-perl": "2.82-1" + "language-pack-gnome-sv": "1:14.04+20140410" + "language-pack-ur-base": "1:14.04+20140410" + "libphonon-perl": "4:4.13.0-0ubuntu1" + "libxinerama1-dbg": "2:1.1.3-1" + "language-pack-gnome-wa": "1:14.04+20140410" + "lmodern": "2.004.4-3" + "libref-array-dev": "0.3.0.1-4" + "language-pack-gl-base": "1:14.04+20140410" + "libv4l-dev": "1.0.1-1" + "libxml-libxslt-perl": "1.84-1" + "ceilometer-collector": "2014.1-0ubuntu1" + "python-unit": "1.4.1-16.1" + "texlive-latex-recommended-doc": "2013.20140215-1" + "libnspr4-dev": "2:4.10.2-1ubuntu1" + "xserver-xorg-input-wacom-dbg": "1:0.23.0-0ubuntu2" + "language-pack-gnome-bem": "1:14.04+20140410" + "libnet-server-perl": "2.007-3" + "unity-scope-gdrive": "0.9+13.10.20130723-0ubuntu1" + "ccache": "3.1.9-1" + "libcogl-pango15-dbg": "1.16.2-1" + "strongswan-tnc-base": "5.1.2-0ubuntu2" + "gir1.2-umockdev-1.0": "0.8.1-1" + "libsbc1": "1.1-2ubuntu2" + "libsignon-plugins-common1": "8.56+14.04.20140307-0ubuntu2" + "libvigraimpex-dev": "1.10.0+dfsg-3ubuntu2" + "libxml-commons-external-java-doc": "1.4.01-2build1" + "libdconf-dbus-1-dbg": "0.20.0-1" + "librrd-ruby1.9.1": "1.4.7-2ubuntu5" + "language-pack-mg-base": "1:14.04+20140410" + "libassuan0": "2.1.1-1ubuntu1" + "linux-image-generic": "3.13.0.24.28" + "optipng": "0.6.4-1build1" + "subversion-dbg": "1.8.8-1ubuntu3" + "python-egenix-mxdatetime-doc": "3.2.7-1build1" + "python3-jsonschema": "2.3.0-1build1" + "python3-testscenarios": "0.4-2ubuntu2" + "libgs9": "9.10~dfsg-0ubuntu10" + "python-apt-dbg": "0.9.3.5" + "python3-psycopg2-dbg": "2.4.5-1build5" + "grub-legacy-doc": "0.97-29ubuntu66" + "imagemagick-doc": "8:6.7.7.10-6ubuntu3" + "language-pack-ha": "1:14.04+20140410" + "libmono-i18n2.0-cil": "3.2.8+dfsg-4ubuntu1" + "libcupsmime1-dev": "1.7.2-0ubuntu1" + "mdbtools": "0.7.1-1ubuntu1" + "hunspell-en-us": "20070829-4ubuntu3" + "shunit2": "2.1.6-1" + "libcogl-dev": "1.16.2-1" + "libgtk-3-0-dbg": "3.10.8-0ubuntu1" + "language-pack-crh": "1:14.04+20140410" + "libevince-dev": "3.10.3-0ubuntu10" + "libgpod-dev": "0.8.3-4ubuntu3" + "tcl": "8.6.0+6ubuntu3" + "xserver-xorg-video-modesetting": "0.8.1-1build1" + "libatomic1-powerpc-cross": "4.8.2-16ubuntu3cross0.11" + "libmono-system-servicemodel-routing4.0-cil": "3.2.8+dfsg-4ubuntu1" + "python-dogpile.core": "0.4.1-0ubuntu3" + "libaccountsservice-dev": "0.6.35-0ubuntu7" + "rrdtool-dbg": "1.4.7-2ubuntu5" + "xserver-xorg-video-mach64-lts-saucy-dbg": "3:5" + "libmono-xbuild-tasks2.0-cil": "3.2.8+dfsg-4ubuntu1" + "libfreetype6-dev": "2.5.2-1ubuntu2" + "libglib2.0-dev": "2.40.0-2" + "libosmesa6-dev": "10.1.0-4ubuntu5" + "qtsensors5-examples": "5.2.1+dfsg-2ubuntu2" + "language-pack-gnome-be-base": "1:14.04+20140410" + "libpath-isdev-perl": "1.000002-1" + "libnspr4": "2:4.10.2-1ubuntu1.1" + "libpam-pwquality": "1.2.3-1ubuntu1" + "command-not-found-data": "0.3ubuntu12" + "lsb-multimedia": "4.1+Debian11ubuntu6" + "strongswan-plugin-eap-md5": "5.1.2-0ubuntu2" + "language-pack-gnome-so": "1:13.04+20130418" + "python3-cliff": "1.4.5-1ubuntu2" + "texlive-fonts-recommended": "2013.20140215-1" + "x11proto-xcmisc-dev": "1.2.2-1" + "autogen": "1:5.18-2ubuntu2" + "libmono-system2.0-cil": "3.2.8+dfsg-4ubuntu1" + "libgl1-mesa-dri-lts-saucy-dbg": "3:5" + "libparse-yapp-perl": "1.05-12" + "firefox-dev": "28.0+build2-0ubuntu2" + "python-simplejson-dbg": "3.3.1-1ubuntu6" + "python3-pyqt5.qtmultimedia": "5.2.1+dfsg-1ubuntu1" + "nova-doc": "1:2014.1-0ubuntu1" + "libxcb-icccm4-dev": "0.4.1-1ubuntu1" + "postfix-pcre": "2.11.0-1" + "python-pastedeploy": "1.5.2-1" + "freeradius-common": "2.1.12+dfsg-1.2ubuntu8" + "language-pack-ve": "1:14.04+20140410" + "account-plugin-aim": "3.8.6-0ubuntu9" + "libproxy1": "0.4.11-0ubuntu4" + "python-sip-dbg": "4.15.5-1build1" + "idle": "2.7.5-5ubuntu3" + "lib32gcc1-dbg": "1:4.9-20140406-0ubuntu1" + "libboost-regex1.54-dev": "1.54.0-4ubuntu3" + "libreoffice-l10n-fi": "1:4.2.3~rc3-0ubuntu1" + "libgcj14-dbg": "4.8.2-19ubuntu1" + "libtheora-dbg": "1.1.1+dfsg.1-3.2" + "open-vm-tools": "2:9.4.0-1280544-5ubuntu6" + "growisofs": "7.1-10build1" + "libconfig++-dbg": "1.4.9-2" + "libhdate1": "1.6-2ubuntu3" + "libraw-doc": "0.15.4-1" + "gstreamer0.10-x": "0.10.36-1.1ubuntu2" + "libclucene-core1": "2.3.3.4-4build1" + "libgnomecanvas2-dbg": "2.30.3-2" + "openipmi": "2.0.18-0ubuntu7" + "libbsf-java": "1:2.4.0-5build1" + "open-iscsi-utils": "2.0.873-3ubuntu9" + "libopus-dev": "1.1-0ubuntu1" + "xutils-dev": "1:7.7~1ubuntu6" + "python-dogpile.cache": "0.5.1-0ubuntu2" + "xserver-xorg-input-evdev": "1:2.8.2-1ubuntu2" + "gcc-powerpc-linux-gnu": "4:4.8.2-1" + "libjpeg62-dev": "6b1-4ubuntu1" + "libkrb5support0": "1.12+dfsg-2ubuntu4" + "binutils-doc": "2.24-5ubuntu3" + "python3-update-manager": "1:0.196.11" + "lxc": "1.0.4-0ubuntu0.1" + "fonts-freefont-ttf": "20120503-4" + "erlang-percept": "1:16.b.3-dfsg-1ubuntu2" + "python-django-horizon": "1:2014.1-0ubuntu1" + "google-mock": "1.6.0+svn437-0ubuntu5" + "python3-dev": "3.4.0-0ubuntu2" + "xserver-xorg-input-vmmouse-lts-raring": "3:5" + "qtserialport5-dbg": "5.2.1-1" + "t1utils": "1.37-2ubuntu1" + "gcc-4.8-source": "4.8.2-19ubuntu1" + "libhtml-tagset-perl": "3.20-2" + "libmeanwhile-dev": "1.0.2-4.1ubuntu1" + "libxcb-randr0-dev": "1.10-2ubuntu1" + "libxcb1-dev": "1.10-2ubuntu1" + "wdiff": "1.2.1-2" + "language-pack-gnome-cv": "1:14.04+20140410" + "libmono-system-componentmodel-dataannotations4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libreoffice-help-hu": "1:4.2.3~rc3-0ubuntu1" + "recode-doc": "3.6-21" + "xfonts-encodings": "1:1.0.4-1ubuntu1" + "python3-cairo": "1.10.0+dfsg-3ubuntu2" + "strongswan-plugin-ldap": "5.1.2-0ubuntu2" + "libasm4-java": "4.1-3" + "maas-dhcp": "1.5+bzr2252-0ubuntu1" + "munin-doc": "2.0.19-3" + "binfmt-support": "2.1.4-1" + "libpkcs11-helper1-dbg": "1.11-1" + "libmono-system-net-http4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libfftw3-single3": "3.3.3-7ubuntu3" + "libfolks-dev": "0.9.5-1ubuntu5" + "qttools5-examples-dbg": "5.2.1-8build1" + "bbswitch-dkms": "0.7-2ubuntu1" + "glib-networking-dbg": "2.40.0-1" + "libebook-contacts1.2-dev": "3.10.4-0ubuntu1" + "libsystemd-daemon0": "204-5ubuntu20.3" + "libpocketsphinx1": "0.8.0+real-0ubuntu6" + "libtiff5-dev": "4.0.3-7" + "libxcb-image0": "0.3.9-1ubuntu2" + "ntfs-3g": "1:2013.1.13AR.1-2ubuntu2" + "simple-scan-dbg": "3.12.0-0ubuntu1" + "language-pack-de": "1:14.04+20140410" + "language-pack-gnome-li": "1:14.04+20140410" + "python-testrepository": "0.0.18-1ubuntu1" + "python3-imaging-sane": "2.3.0-1ubuntu3" + "fonts-navilu": "1.2-2" + "libaccountsservice0": "0.6.35-0ubuntu7" + "libqt4-webkit-dbg": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "libthreadweaver4": "4:4.13.0-0ubuntu1" + "linux-cloud-tools-3.13.0-24-lowlatency": "3.13.0-24.46" + "language-pack-gnome-nb-base": "1:14.04+20140410" + "language-pack-gnome-yo-base": "1:14.04+20140410" + "bacula-director-common-dbg": "5.2.6+dfsg-9.1ubuntu3" + "python-gst0.10": "0.10.22-3ubuntu2" + "python-pytyrant": "1.1.17-1ubuntu2" + "libbsd-resource-perl": "1.2907-1build1" + "libcanberra-dev": "0.30-0ubuntu3" + "libtk8.6-dbg": "8.6.1-3ubuntu2" + "sssd-tools": "1.11.5-1ubuntu3" + "dh-apport": "2.14.1-0ubuntu3" + "gem2deb": "0.6.1" + "python-astroid": "1.0.1-1" + "x11proto-render-dev": "2:0.11.1-2" + "evolution-data-server": "3.10.4-0ubuntu1" + "bcrelay": "1.3.4+27+gddb30f8-1ubuntu1" + "libqt5feedback5": "5.0~git20130529-0ubuntu3" + "gnome-user-guide": "3.8.2-1" + "libmono-system-management4.0-cil": "3.2.8+dfsg-4ubuntu1" + "librasqal3-doc": "0.9.32-1" + "libgoogle-glog-dev": "0.3.3-1" + "valgrind": "1:3.10~20140411-0ubuntu1" + "libcorosync-dev": "2.3.3-1ubuntu1" + "python-software-properties": "0.92.37.1" + "apache2": "2.4.7-1ubuntu4" + "libqt5webkit5": "5.1.1-1ubuntu8" + "python-pyruntest": "0.1+13.10.20130702-0ubuntu3" + "libglib2.0-0-dbg": "2.40.0-2" + "mountall": "2.53" + "xdg-user-dirs-gtk": "0.10-1ubuntu1" + "libatk-bridge2.0-0": "2.10.2-2ubuntu1" + "libuniconf4.6": "4.6.1-7" + "gpgv": "1.4.16-1ubuntu2" + "liblrm2": "1.0.11+hg2754-1.1build1" + "python-gi-dev": "3.12.0-1" + "powerwaked": "2.18-0ubuntu2" + "python3-apport": "2.14.1-0ubuntu3" + "thunderbird-locale-nb-no": "1:24.4.0+build1-0ubuntu1" + "g++-aarch64-linux-gnu": "4:4.8.2-1" + "gir1.2-hud-2": "13.10.1+14.04.20140402-0ubuntu1" + "language-pack-gnome-kw": "1:14.04+20140410" + "libreoffice-help-da": "1:4.2.3~rc3-0ubuntu1" + "libreoffice-help-zh-cn": "1:4.2.3~rc3-0ubuntu1" + "pyqt4-dev-tools": "4.10.4+dfsg-1ubuntu1" + "xserver-xorg-video-openchrome-lts-quantal": "3:5" + "libjsch-java-doc": "0.1.50-1ubuntu1" + "g++-4.8-multilib": "4.8.2-19ubuntu1" + "libdebian-installer4-dev": "0.88ubuntu4" + "libxcb-shm0": "1.10-2ubuntu1" + "xserver-xorg-input-synaptics-lts-saucy": "3:5" + "libdistro-info-perl": "0.12" + "freeglut3-dev": "2.8.1-1" + "libcanberra-gtk0-dbg": "0.30-0ubuntu3" + "libdbustest1-dev": "14.04.1+14.04.20140320-0ubuntu1" + "printer-driver-pxljr": "1.4+repack0-3" + "python-reportlab": "3.0-1build1" + "libp11-2": "0.2.8-3ubuntu1" + "libsvn-dev": "1.8.8-1ubuntu3" + "facter": "1.7.5-1ubuntu1" + "desktop-file-utils": "0.22-1ubuntu1" + "libgc-dev": "1:7.2d-5ubuntu2" + "openvswitch-switch": "2.0.1+git20140120-0ubuntu2" + "python3-dbus.mainloop.qt": "4.10.4+dfsg-1ubuntu1" + "radosgw": "0.79-0ubuntu1" + "aptitude-doc-en": "0.6.8.2-1ubuntu4" + "ubuntu-extras-keyring": "2010.09.27" + "gir1.2-secret-1": "0.16-0ubuntu1" + "heartbeat-dev": "1:3.0.5-3.2" + "libjson-glib-dev": "0.16.2-1ubuntu1" + "libmodule-build-perl": "0.420400-1" + "python-twisted-names": "13.2.0-1ubuntu1" + "g++-powerpc64le-linux-gnu": "4:4.8.2-1" + "libdatrie-dev": "0.2.8-1" + "libfreeipmi-dev": "1.1.5-3ubuntu3" + "libgtkspell0": "2.0.16-1ubuntu7" + "libnetfilter-conntrack3": "1.0.4-1" + "unity-lens-video": "0.3.15+13.10.20130920-0ubuntu1" + "maas-cli": "1.5+bzr2252-0ubuntu1" + "ruby-childprocess": "0.3.9-2" + "libpango1.0-dev": "1.36.3-1ubuntu1" + "squashfs-tools-dbg": "1:4.2+20130409-2" + "usb-modeswitch-data": "20140327-1" + "curl": "7.35.0-1ubuntu2" + "libbind9-90": "1:9.9.5.dfsg-3" + "d-shlibs": "0.54ubuntu1" + "libbareword-filehandles-perl": "0.003-1build1" + "libwayland-server0": "1.4.0-1ubuntu1" + "python3-dbus.mainloop.qt-dbg": "4.10.4+dfsg-1ubuntu1" + "xserver-xorg-input-synaptics": "1.7.4-0ubuntu1" + "language-pack-de-base": "1:14.04+20140410" + "debootstrap": "1.0.59ubuntu0.1" + "libxmlunit-java-doc": "1.5-1" + "libassuan-dev": "2.1.1-1ubuntu1" + "wireless-tools": "30~pre9-8ubuntu1" + "libqb-dev": "0.16.0.real-1ubuntu3" + "opensp": "1.5.2-10ubuntu3" + "xserver-xorg-core-lts-raring": "3:5" + "account-plugin-windows-live": "0.11+14.04.20140409.1-0ubuntu1" + "fonts-arabeyes": "2.1-3" + "gimp-help-ru": "2.6.1-1" + "libasound2-dbg": "1.0.27.2-3ubuntu7" + "libdbusmenu-glib-dev": "12.10.3+14.04.20140319-0ubuntu1" + "xserver-xorg-video-nouveau-lts-saucy": "3:5" + "libmono-system-messaging4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libreoffice-l10n-hr": "1:4.2.3~rc3-0ubuntu1" + "x11proto-composite-dev": "1:0.4.2-2" + "libmirclient-dev": "0.1.8+14.04.20140411-0ubuntu1" + "sssd-common": "1.11.5-1ubuntu3" + "libqtopengl4-perl": "4:4.13.0-0ubuntu1" + "libwebpmux1": "0.4.0-4" + "phonon": "4:4.7.1-0ubuntu8" + "libextutils-config-perl": "0.007-1" + "python3-louis": "2.5.3-2ubuntu1" + "libcpg4": "2.3.3-1ubuntu1" + "libgudev-1.0-dev": "1:204-5ubuntu20" + "libjpeg-turbo8-dev": "1.3.0-0ubuntu2" + "erlang-eunit": "1:16.b.3-dfsg-1ubuntu2" + "language-pack-gnome-ts-base": "1:14.04+20140410" + "libqmi-glib-doc": "1.4.0-1" + "libdbus-glib-1-dev": "0.100.2-1" + "libwhoopsie-preferences0": "0.12" + "mariadb-client-5.5": "5.5.38+maria-1~trusty" + "python3-click": "0.4.21.1" + "dh-translations": "121" + "libustr-doc": "1.0.4-3ubuntu2" + "postgresql-client": "9.3+154" + "libxcb-shape0": "1.10-2ubuntu1" + "libreoffice-l10n-id": "1:4.2.3~rc3-0ubuntu1" + "libunity-webapps-doc": "2.5.0~+14.04.20140409-0ubuntu1" + "gir1.2-timezonemap-1.0": "0.4.1" + "libical-dbg": "1.0-0ubuntu1" + "rsyslog": "7.4.4-1ubuntu2" + "libflac-doc": "1.3.0-2" + "gcc-4.7-doc": "4.7.3-12ubuntu1" + "libreoffice-help-zh-tw": "1:4.2.3~rc3-0ubuntu1" + "landscape-common": "14.01-0ubuntu3" + "liblightdm-qt-3-0": "1.10.0-0ubuntu3" + "firefox-locale-tr": "28.0+build2-0ubuntu2" + "libc-dev-bin": "2.19-0ubuntu6" + "libssh-4": "0.6.1-0ubuntu3" + "dictionaries-common": "1.20.5" + "libdb++-dev": "1:5.3.21~exp1ubuntu1" + "libgirepository-1.0-1": "1.40.0-1ubuntu0.1" + "python-egenix-mxstack": "3.2.7-1build1" + "libqtxml4-perl": "4:4.13.0-0ubuntu1" + "linux-headers-3.13.0-32-generic": "3.13.0-32.57" + "liblog4net1.2-cil": "1.2.10+dfsg-6" + "libxaw-doc": "2:1.0.12-1" + "python-simplestreams": "0.1.0~bzr341-0ubuntu1" + "libcephfs1-dbg": "0.79-0ubuntu1" + "libfilehandle-fmode-perl": "0.13-1build1" + "python-lxml-doc": "3.3.3-1" + "geoclue": "0.12.99-3ubuntu1" + "libreoffice-gnome": "1:4.2.3~rc3-0ubuntu2" + "language-pack-sl": "1:14.04+20140410" + "authbind": "2.1.1" + "libxcb-present-dev": "1.10-2ubuntu1" + "python-pylibacl-dbg": "0.5.1-1.1build4" + "quagga-dbg": "0.99.22.4-3ubuntu1" + "libcanberra-doc": "0.30-0ubuntu3" + "python-imaging-sane-dbg": "2.3.0-1ubuntu3" + "dash": "0.5.7-4ubuntu1" + "gcc-4.8-powerpc-linux-gnu-base": "4.8.2-16ubuntu3cross0.11" + "libsbuild-dev": "1.6.8-1ubuntu1" + "lib32gfortran-4.7-dev": "4.7.3-12ubuntu1" + "libc6-i386": "2.19-0ubuntu6" + "qemu-system": "2.0.0~rc1+dfsg-0ubuntu3" + "libmono-system-web2.0-cil": "3.2.8+dfsg-4ubuntu1" + "python3-tz": "2012c-1build1" + "firefox-locale-af": "28.0+build2-0ubuntu2" + "g++-4.8-multilib-arm-linux-gnueabihf": "4.8.2-16ubuntu4cross0.11" + "html2text": "1.3.2a-17" + "srvadmin-omcommon": "7.1.0-2" + "libvncserver0-dbg": "0.9.9+dfsg-1ubuntu1" + "libfile-find-rule-perl": "0.33-1" + "openoffice.org-hyphenation": "0.7" + "python3-py": "1.4.20-1" + "yapps2": "2.1.1-17.2ubuntu1" + "libqt5contacts5": "5.0~git20140203~e0c5eebe-0ubuntu2" + "make": "3.81-8.2ubuntu3" + "python3-gpgme-dbg": "0.3-0ubuntu3" + "emacs24-common": "24.3+1-2ubuntu1" + "lynx": "2.8.8pre4-1" + "python-suds": "0.4.1-11build1" + "unicode-data": "6.3.0-2" + "groff-base": "1.22.2-5" + "language-pack-gnome-ja": "1:14.04+20140410" + "language-pack-gnome-sk-base": "1:14.04+20140410" + "libeasymock-java": "2.5.2+ds-1" + "libxcb-present0-dbg": "1.10-2ubuntu1" + "xserver-xorg-video-tdfx-lts-saucy": "3:5" + "python-amqp-doc": "1.3.3-1ubuntu1" + "bacula-common-dbg": "5.2.6+dfsg-9.1ubuntu3" + "libmx-dev": "1.4.7-0ubuntu3" + "libreoffice-pdfimport": "1:4.2.3~rc3-0ubuntu2" + "language-pack-gnome-lv": "1:14.04+20140410" + "nova-scheduler": "1:2014.1-0ubuntu1" + "libdbusmenu-jsonloader4": "12.10.3+14.04.20140319-0ubuntu1" + "man-db": "2.6.7.1-1" + "checksecurity": "2.0.14ubuntu1" + "libgoa-1.0-common": "3.10.3-0ubuntu1" + "libjpeg8": "8c-2ubuntu8" + "pidgin-dbg": "1:2.10.9-0ubuntu3" + "libedit2": "3.1-20130712-2" + "libjson0-dev": "0.11-3ubuntu1" + "libxcb-glx0-dbg": "1.10-2ubuntu1" + "bdf2psf": "1.70ubuntu8" + "language-pack-fr-base": "1:14.04+20140410" + "libmono-management4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libcomerr2-dbg": "1.42.9-3ubuntu1" + "libftdipp1-dbg": "0.20-1ubuntu1" + "libpurple-dev": "1:2.10.9-0ubuntu3" + "gir1.2-rest-extras-0.7": "0.7.90-0ubuntu1" + "unixodbc-dev": "2.2.14p2-5ubuntu5" + "libdist-checkconflicts-perl": "0.10-1" + "linux-libc-dev-powerpc-cross": "3.13.0-13.33cross1.1" + "media-player-info": "21-0ubuntu1" + "python-feedparser": "5.1.3-2" + "libxft2": "2.3.1-2" + "libgl1-mesa-dri-lts-quantal-dbg": "3:5" + "libgsl0-dev": "1.16+dfsg-1ubuntu1" + "libnotify-dev": "0.7.6-1ubuntu3" + "cheese-common": "3.10.2-0ubuntu2" + "language-pack-gnome-mai": "1:14.04+20140410" + "libreoffice-help-fr": "1:4.2.3~rc3-0ubuntu1" + "libvdpau-doc": "0.7-1" + "libavahi-ui-gtk3-dev": "0.6.31-4ubuntu1" + "libxcb-dpms0-dbg": "1.10-2ubuntu1" + "libtest-pod-perl": "1.48-1" + "vim-common": "2:7.4.052-1ubuntu3" + "unity-scope-tomboy": "0.1+13.10.20130723-0ubuntu1" + "ceph-common": "0.79-0ubuntu1" + "gdisk": "0.8.8-1build1" + "libhardware2": "0.1.0+git20131207+e452e83-0ubuntu12" + "python3-pyqt5.qtwebkit": "5.2.1+dfsg-1ubuntu1" + "libsemanage1": "2.2-1" + "base-files": "7.2ubuntu5" + "firefox-locale-cs": "28.0+build2-0ubuntu2" + "libdb-sql-dev": "1:5.3.21~exp1ubuntu1" + "libncurses5": "5.9+20140118-1ubuntu1" + "libpathplan4": "2.36.0-0ubuntu3" + "firefox-locale-es": "28.0+build2-0ubuntu2" + "qtfeedback5-dbg": "5.0~git20130529-0ubuntu3" + "libcommons-io-java": "2.4-2" + "python-tidylib": "0.2.1~dfsg-2ubuntu3" + "llvm-3.4-runtime": "1:3.4-1ubuntu3" + "bonnie++": "1.97.1" + "libgl1-mesa-dev": "10.1.0-4ubuntu5" + "language-pack-crh-base": "1:14.04+20140410" + "libhesiod0": "3.2.1-2" + "libx32tinfo-dev": "5.9+20140118-1ubuntu1" + "qt5-qmake": "5.2.1+dfsg-1ubuntu14" + "firefox-locale-oc": "28.0+build2-0ubuntu2" + "python3-gi-cairo": "3.12.0-1" + "python-maas-client": "1.5+bzr2252-0ubuntu1" + "libnih-dev": "1.0.3-4ubuntu25" + "python-openssl": "0.13-2ubuntu6" + "dictionaries-common-dev": "1.20.5" + "libfont-ttf-perl": "1.04-1" + "libfreerdp-plugins-standard": "1.0.2-2ubuntu1" + "libbz2-dev": "1.0.6-5" + "libvncserver-dev": "0.9.9+dfsg-1ubuntu1" + "language-pack-gnome-mr": "1:14.04+20140410" + "libhamcrest-java": "1.3-4" + "plainbox-provider-checkbox": "0.4-1" + "pulseaudio-module-gconf-dbg": "1:4.0-0ubuntu11" + "javascript-common": "11" + "language-pack-bo-base": "1:14.04+20140410" + "libgtkmm-3.0-doc": "3.10.1-0ubuntu2" + "libbonobo2-dev": "2.32.1-0ubuntu5" + "libperl5.18": "5.18.2-2ubuntu1" + "irqbalance": "1.0.6-2" + "libgrip-dev": "0.3.7+14.04.20140303-0ubuntu1" + "libgvc6": "2.36.0-0ubuntu3" + "libpwquality-dev": "1.2.3-1ubuntu1" + "strongswan-starter": "5.1.2-0ubuntu2" + "git-doc": "1:1.9.1-1" + "language-pack-ru": "1:14.04+20140410" + "libglapi-mesa-lts-quantal": "3:5" + "libxmltok1": "1.2-3build3" + "python-qt4-dbus": "4.10.4+dfsg-1ubuntu1" + "thunderbird-locale-de": "1:24.4.0+build1-0ubuntu1" + "xserver-xorg-input-synaptics-lts-raring-dbg": "3:5" + "libmail-dkim-perl": "0.40-1" + "xcursor-themes": "1.0.3-1" + "emacs24-nox-dbg": "24.3+1-2ubuntu1" + "grub-efi-ia32-dbg": "2.02~beta2-9" + "net-tools": "1.60-25ubuntu2" + "cloud-init": "0.7.5-0ubuntu1.1" + "libgnome-menu-3-0": "3.10.1-0ubuntu2" + "ruby1.9.1-dev": "1.9.3.484-2ubuntu1" + "swig": "2.0.11-1ubuntu2" + "xserver-xorg-video-vesa-lts-saucy": "3:5" + "libgstreamer0.10-0": "0.10.36-1.2ubuntu3" + "libasan0-armhf-cross": "4.8.2-16ubuntu4cross0.11" + "libgegl-0.2-0-dbg": "0.2.0-4ubuntu1" + "nvidia-settings-319-updates": "331.20-0ubuntu8" + "rackspace-monitoring-agent": "1.0.2-5" + "m17n-db": "1.6.4-1" + "python-imaging-tk-dbg": "2.3.0-1ubuntu3" + "quota": "4.01-3" + "qtdeclarative5-ubuntu-ui-extras-browser-plugin-assets": "0.23+14.04.20140414-0ubuntu1" + "thunderbird-locale-fy": "1:24.4.0+build1-0ubuntu1" + "libcommons-lang-java": "2.6-3ubuntu2" + "elasticsearch": "1.2.1" + "language-pack-be": "1:14.04+20140410" + "liblog4j1.2-java-doc": "1.2.17-4ubuntu3" + "libpwquality-common": "1.2.3-1ubuntu1" + "language-pack-csb-base": "1:14.04+20140410" + "libtry-tiny-perl": "0.19-1" + "python3-reportlab": "3.0-1build1" + "language-pack-gd-base": "1:14.04+20140410" + "libmono-system-windows-forms-datavisualization4.0a-cil": "3.2.8+dfsg-4ubuntu1" + "linux-generic": "3.13.0.24.28" + "linux-headers-3.13.0-24-generic": "3.13.0-24.46" + "python-libapparmor": "2.8.95~2430-0ubuntu5" + "cloop-utils": "2.6.39.2-1ubuntu3" + "libgcc-4.7-dev": "4.7.3-12ubuntu1" + "liblzma5": "5.1.1alpha+20120614-2ubuntu2" + "libpcre3": "1:8.31-2ubuntu2" + "libxcb-damage0": "1.10-2ubuntu1" + "xserver-xorg-video-vmware-lts-saucy": "3:5" + "libfreerdp-dev": "1.0.2-2ubuntu1" + "libxen-4.4": "4.4.0-0ubuntu5" + "open-iscsi": "2.0.873-3ubuntu9" + "perl-debug": "5.18.2-2ubuntu1" + "qtdeclarative5-accounts-plugin": "0.4+14.04.20140317-0ubuntu1" + "qtbase5-doc-html": "5.2.1+dfsg-1ubuntu14" + "libclutter-gst-2.0-dev": "2.0.8-1build1" + "linux-cloud-tools-virtual": "3.13.0.24.28" + "screen-dbg": "4.1.0~20120320gitdb59704-9" + "language-pack-mr-base": "1:14.04+20140410" + "libjline-java": "1.0-2" + "libtest-differences-perl": "0.61-1" + "python-dictdlib": "2.0.4.1+nmu1build1" + "libvirt0": "1.2.2-0ubuntu13" + "libgstreamer1.0-0": "1.2.3-1" + "libtdb1": "1.2.12-1" + "qt3d5-dbg": "5.0~git20130731-0ubuntu5" + "xserver-xorg-input-wacom-lts-saucy": "3:5" + "language-pack-yo-base": "1:14.04+20140410" + "libatk1.0-dev": "2.10.0-2ubuntu2" + "libx11-xcb1-dbg": "2:1.6.2-1ubuntu2" + "shim-signed": "1.6+0.4-0ubuntu4" + "language-pack-gnome-az": "1:14.04+20140410" + "libbcel-java": "5.2-9build1" + "xtrans-dev": "1.3.2-1" + "gnu-efi": "3.0u+debian-1ubuntu2" + "language-pack-gnome-gl": "1:14.04+20140410" + "gir1.2-wnck-1.0": "1:2.30.7-0ubuntu4" + "libao4": "1.1.0-2ubuntu2" + "libxau6-dbg": "1:1.0.8-1" + "libtidy-dev": "20091223cvs-1.2ubuntu1" + "libx32itm1": "4.8.2-19ubuntu1" + "samba-dsdb-modules": "2:4.1.6+dfsg-1ubuntu2" + "libmono-entityframework-sqlserver6.0-cil": "3.2.8+dfsg-4ubuntu1" + "libreoffice-l10n-lv": "1:4.2.3~rc3-0ubuntu1" + "gir1.2-peas-1.0": "1.8.1-2ubuntu2" + "lib32gomp1": "4.8.2-19ubuntu1" + "libfs6": "2:1.0.5-1" + "python3-plainbox": "0.5.3-2" + "swig2.0-doc": "2.0.11-1ubuntu2" + "libpython2.7-stdlib": "2.7.6-8" + "rpm": "4.11.1-3" + "graphviz-doc": "2.36.0-0ubuntu3" + "libsombok3": "2.3.1-2" + "libwbclient-dev": "2:4.1.6+dfsg-1ubuntu2" + "openssh-client": "1:6.6p1-2ubuntu2" + "fonts-nafees": "1.2-5ubuntu1" + "language-pack-om": "1:14.04+20140410" + "libipc-system-simple-perl": "1.25-2" + "gir1.2-ebook-1.2": "3.10.4-0ubuntu1" + "gcc-4.8-plugin-dev": "4.8.2-19ubuntu1" + "libecryptfs0": "104-0ubuntu1" + "libgupnp-1.0-4": "0.20.10-1ubuntu1" + "apache2-bin": "2.4.7-1ubuntu4" + "libflac++6": "1.3.0-2" + "libxatracker-dev-lts-saucy": "3:5" + "dict-gcide": "0.48.1" + "libgnutls-openssl27": "2.12.23-12ubuntu2" + "libmagic-dev": "1:5.14-2ubuntu3" + "libnl-3-200": "3.2.21-1" + "libxcb-xprint0-dev": "1.10-2ubuntu1" + "language-pack-gnome-sd": "1:14.04+20140410" + "firefox-locale-ca": "28.0+build2-0ubuntu2" + "libqt5multimediaquick-p5": "5.2.1-0ubuntu5" + "trousers": "0.3.11.2-1" + "language-pack-gnome-cv-base": "1:14.04+20140410" + "libgd-text-perl": "0.86-8" + "libxmlgraphics-commons-java": "1.5-4ubuntu1" + "libdbd-freetds": "0.9.0-2ubuntu2" + "compiz-plugins-main-dev": "1:0.9.11+14.04.20140409-0ubuntu1" + "elasticsearch": "1.2.2" + "libbsh-java": "2.0b4-15" + "nas-doc": "1.9.4-1" + "evolution-data-server-dev": "3.10.4-0ubuntu1" + "gccgo-4.8-doc": "4.8.2-19ubuntu1" + "libasan0-dbg": "4.8.2-19ubuntu1" + "libgexiv2-2-dbg": "0.10.0-1ubuntu1" + "libxcb-shape0-dbg": "1.10-2ubuntu1" + "python3-bson-ext": "2.6.3-1build1" + "libxfixes3": "1:5.0.1-1ubuntu1" + "nano": "2.2.6-1ubuntu1" + "python-rdflib": "2.4.2-3build1" + "libmono-wcf3.0a-cil": "3.2.8+dfsg-4ubuntu1" + "libppix-regexp-perl": "0.036-1" + "valac-0.18-vapi": "0.18.1-0ubuntu11" + "libavahi-ui-gtk3-0": "0.6.31-4ubuntu1" + "libunity9": "7.1.4+14.04.20140210-0ubuntu1" + "watershed": "7" + "dpkg": "1.17.5ubuntu5" + "libfontembed-dev": "1.0.52-0ubuntu1" + "libhybris-common-dev": "0.1.0+git20131207+e452e83-0ubuntu12" + "vim-tiny": "2:7.4.052-1ubuntu3" + "libdlmcontrol-dev": "4.0.1-0ubuntu1" + "libneon27-gnutls": "0.30.0-1ubuntu1" + "sysstat": "10.2.0-1" + "libgoa-backend-1.0-1": "3.10.3-0ubuntu1" + "mono-runtime-common": "3.2.8+dfsg-4ubuntu1" + "perlqt-dev": "4:4.13.0-0ubuntu1" + "xserver-xorg-video-openchrome-lts-quantal-dbg": "3:5" + "gcj-4.8": "4.8.2-19ubuntu1" + "libevolution": "3.10.4-0ubuntu1" + "libjson-c-dev": "0.11-3ubuntu1" + "libx11-dev": "2:1.6.2-1ubuntu2" + "pacemaker-cli-utils": "1.1.10+git20130802-1ubuntu2" + "libcolamd2.8.0": "1:4.2.1-3ubuntu1" + "libfontenc1": "1:1.1.2-1" + "python3-all": "3.4.0-0ubuntu2" + "syslinux-themes-ubuntu-raring": "8" + "libcommons-vfs-java": "2.0-3ubuntu1" + "libmx-common": "1.4.7-0ubuntu3" + "libegl1-mesa-drivers": "10.1.0-4ubuntu5" + "libgxps2": "0.2.2-2ubuntu2" + "tftpd-hpa": "5.2-7ubuntu3" + "libhtml-parser-perl": "3.71-1build1" + "libubuntu-application-api-mirclient1": "0.20+14.04.20140411-0ubuntu1" + "mscompress": "0.4-3" + "python-bzrlib": "2.6.0+bzr6593-1ubuntu1" + "srvadmin-idrac": "7.1.0-2" + "thunderbird-locale-si": "1:24.4.0+build1-0ubuntu1" + "konwert": "1.8-11.2build2" + "libcolord-dev": "1.0.6-1" + "libt1-5-dbg": "5.1.2-3.6ubuntu1" + "libusbredirhost-dev": "0.6-2ubuntu1" + "thunderbird-locale-ru": "1:24.4.0+build1-0ubuntu1" + "libexcalibur-logkit-java-doc": "2.0-10" + "gnupg-agent": "2.0.22-3ubuntu1" + "libcollection-dev": "0.3.0.1-4" + "python3-bsddb3-dbg": "6.0.1-1build1" + "thunderbird-locale-nl": "1:24.4.0+build1-0ubuntu1" + "language-pack-gnome-bn-base": "1:14.04+20140410" + "libgtkmm-2.4-doc": "1:2.24.4-1ubuntu1" + "libmono-system-componentmodel-composition4.0-cil": "3.2.8+dfsg-4ubuntu1" + "lib32gfortran3": "4.8.2-19ubuntu1" + "libdbi-perl": "1.630-1" + "ibus-chewing-dbg": "1.4.10.1-1" + "libkadm5srv-mit9": "1.12+dfsg-2ubuntu4" + "nfs-kernel-server": "1:1.2.8-6ubuntu1" + "libgusb-doc": "0.1.6-5" + "python2.7-examples": "2.7.6-8" + "libgtk-vnc-2.0-0": "0.5.3-0ubuntu2" + "libibus-1.0-dev": "1.5.5-1ubuntu3" + "linux-headers-3.13.0-24": "3.13.0-24.46" + "dictzip": "1.12.1+dfsg-2" + "erlang-megaco": "1:16.b.3-dfsg-1ubuntu2" + "gir1.2-gweather-3.0": "3.10.2-0ubuntu1" + "libxshmfence1": "1.1-2" + "language-pack-gnome-fo-base": "1:14.04+20140410" + "language-pack-gnome-pt-base": "1:14.04+20140410" + "gir1.2-atk-1.0": "2.10.0-2ubuntu2" + "language-pack-ks": "1:14.04+20140410" + "rhythmbox-doc": "3.0.2-0ubuntu1" + "swift-proxy": "1.13.1-0ubuntu1" + "libgsf-1-114": "1.14.27-2ubuntu2" + "libsbuild-doc": "1.6.8-1ubuntu1" + "heimdal-dev": "1.6~git20131207+dfsg-1ubuntu1" + "libgcr-3-dev": "3.10.1-1" + "libtk8.6": "8.6.1-3ubuntu2" + "valgrind-dbg": "1:3.10~20140411-0ubuntu1" + "libgrantlee-core0": "0.4.0-0ubuntu1" + "libwayland-cursor0-dbg": "1.4.0-1ubuntu1" + "libpangox-1.0-0": "0.0.2-4ubuntu1" + "hunspell-fr": "1:5.0.2-1" + "libplist-doc": "1.10-1" + "python-jabber": "0.5.0-1.5ubuntu1" + "joyent-mdata-client": "0.0.1-0ubuntu2" + "libgee-dev": "0.6.8-1ubuntu1" + "flex-doc": "2.5.35-10.1ubuntu2" + "libdevel-globaldestruction-perl": "0.12-1" + "liborc-0.4-0": "1:0.4.18-1ubuntu1" + "libsmokeqthelp4-3": "4:4.13.0-0ubuntu1" + "myspell-ns": "20070206-4ubuntu1" + "gcc-4.8-arm-linux-gnueabihf-base": "4.8.2-16ubuntu4cross0.11" + "libmetacity-private0a": "1:2.34.13-0ubuntu4" + "binutils-multiarch": "2.24-5ubuntu3" + "libattica-dev": "0.4.2-1" + "libxml++2.6-dev": "2.36.0-2ubuntu1" + "setserial": "2.17-48" + "python-debtagshw": "1.12ubuntu2" + "python-urlgrabber": "3.9.1-4ubuntu3" + "kbd": "1.15.5-1ubuntu1" + "linux-image-virtual": "3.13.0.24.28" + "sip-dev": "4.15.5-1build1" + "srvadmin-rac-components": "7.1.0-2" + "strongswan-plugin-unbound": "5.1.2-0ubuntu2" + "xserver-xorg-video-all-lts-saucy": "3:5" + "python-junitxml": "0.6-1.1build1" + "libatk-adaptor": "2.10.2-2ubuntu1" + "libmagic1": "1:5.14-2ubuntu3" + "libpe-status4": "1.1.10+git20130802-1ubuntu2" + "libudisks2-dev": "2.1.3-1" + "xserver-xorg-video-fbdev-lts-raring": "3:5" + "mysql-server-core-5.5": "5.5.35+dfsg-1ubuntu1" + "portaudio19-dev": "19+svn20140130-1" + "language-pack-bg": "1:14.04+20140410" + "language-pack-si": "1:14.04+20140410" + "libqscintilla2-l10n": "2.8.1-2" + "libssl1.0.0": "1.0.1f-1ubuntu2" + "libx86-1": "1.1+ds1-10" + "libgutenprint-doc": "5.2.10~pre2-0ubuntu2" + "python-formencode": "1.2.6-1ubuntu1" + "lib32objc4": "4.8.2-19ubuntu1" + "libnfsidmap2": "0.25-5" + "libgladeui-doc": "3.16.1-0ubuntu2" + "liblog4j1.2-java": "1.2.17-4ubuntu3" + "gcc-4.8-aarch64-linux-gnu-base": "4.8.2-13ubuntu1cross0.11" + "gir1.2-poppler-0.18": "0.24.5-2ubuntu4" + "libx32gfortran-4.8-dev": "4.8.2-19ubuntu1" + "libb-hooks-op-check-perl": "0.19-1build2" + "libxcb-render0-dev": "1.10-2ubuntu1" + "bbdb": "2.36-3ubuntu1" + "language-pack-gnome-es-base": "1:14.04+20140410" + "shtool": "2.0.8-6" + "xorg-sgml-doctools": "1:1.11-1" + "base-files": "7.2ubuntu5.1" + "libsasl2-dev": "2.1.25.dfsg1-17build1" + "uno-libs3-dbg": "4.2.3~rc3-0ubuntu2" + "libcogl-gles2-dev": "1.16.2-1" + "libgcc1": "1:4.9-20140406-0ubuntu1" + "m4": "1.4.17-2ubuntu1" + "texlive-luatex": "2013.20140215-1" + "x11proto-xext-dev": "7.3.0-1" + "linux-image-extra-3.13.0-24-generic": "3.13.0-24.46" + "qtscript5-dev": "5.2.1+dfsg-1ubuntu1" + "libreoffice-l10n-ku": "1:4.2.3~rc3-0ubuntu2" + "libsmokeqtxml4-3": "4:4.13.0-0ubuntu1" + "language-pack-ro": "1:14.04+20140410" + "libcommons-dbcp-java": "1.4-3ubuntu1" + "linux-source": "3.13.0.24.28" + "ssh": "1:6.6p1-2ubuntu1" + "cheese": "3.10.2-0ubuntu2" + "tomcat7-docs": "7.0.52-1" + "libpango-1.0-0": "1.36.3-1ubuntu1" + "python-pbr": "0.7.0-0ubuntu2" + "gnome-menus": "3.10.1-0ubuntu2" + "python-sane": "2.3.0-1ubuntu3" + "libxcb-render-util0-dev": "0.3.8-1.1ubuntu1" + "python3-psutil": "1.2.1-1ubuntu2" + "libcommons-codec-java": "1.9-1" + "genisoimage": "9:1.1.11-2ubuntu3" + "gir1.2-webkit-3.0": "2.4.0-1ubuntu2" + "gobjc-4.8": "4.8.2-19ubuntu1" + "libsndfile1": "1.0.25-7ubuntu2" + "language-pack-gnome-ti-base": "1:14.04+20140410" + "libplumbgpl2": "1.0.11+hg2754-1.1build1" + "python2.7-doc": "2.7.6-8" + "libiw30": "30~pre9-8ubuntu1" + "libxml++2.6-2": "2.36.0-2ubuntu1" + "systemd-shim": "6-2bzr1" + "libboost-dbg": "1.54.0.1ubuntu1" + "libtag1-vanilla": "1.9.1-2" + "activity-log-manager-control-center": "0.9.7-0ubuntu14" + "language-pack-sa": "1:14.04+20140410" + "libsfgcc1-armhf-cross": "1:4.8.2-16ubuntu4cross0.11" + "ldap-utils": "2.4.31-1+nmu2ubuntu8" + "libudisks2-0": "2.1.3-1" + "thunderbird-locale-gd": "1:24.4.0+build1-0ubuntu1" + "xserver-xorg-video-r128-lts-raring": "3:5" + "python3-cairo-doc": "1.10.0+dfsg-3ubuntu2" + "lynx-cur": "2.8.8pre4-1" + "python-xattr": "0.6.4-2build1" + "bacula-director-mysql": "5.2.6+dfsg-9.1ubuntu3" + "libgbm1-lts-raring": "3:5" + "language-pack-gnome-bs-base": "1:14.04+20140410" + "libwnck-3-common": "3.4.7-0ubuntu3" + "fbset": "2.1-27" + "libgmime-2.6-0-dbg": "2.6.20-0ubuntu1" + "libsmokeqt4-dev": "4:4.13.0-0ubuntu1" + "nautilus-data": "1:3.10.1-0ubuntu8" + "libsmokeqtsql4-3": "4:4.13.0-0ubuntu1" + "libreoffice-l10n-cs": "1:4.2.3~rc3-0ubuntu1" + "python-oneconf": "0.3.7" + "empathy-dbg": "3.8.6-0ubuntu9" + "squid3-dbg": "3.3.8-1ubuntu6" + "libsuper-perl": "1.20120705-1" + "nova-volume": "1:2014.1-0ubuntu1" + "firefox-locale-th": "28.0+build2-0ubuntu2" + "python-dev": "2.7.5-5ubuntu3" + "spell": "1.0-24" + "libpeas-doc": "1.8.1-2ubuntu2" + "upstart-app-launch-tools": "0.3+14.04.20140411-0ubuntu1" + "libxext6": "2:1.3.2-1" + "radvd": "1:1.9.1-1.1ubuntu2" + "language-pack-gnome-sr": "1:14.04+20140410" + "libmono-cecil-private-cil": "3.2.8+dfsg-4ubuntu1" + "python-distro-info": "0.12" + "libsignon-extension1": "8.56+14.04.20140307-0ubuntu2" + "libunistring-dev": "0.9.3-5ubuntu3" + "xserver-xorg-video-ati-dbg": "1:7.3.0-1ubuntu3" + "language-pack-gnome-lt": "1:14.04+20140410" + "libnm-gtk0": "0.9.8.8-0ubuntu4" + "libwvstreams-dev": "4.6.1-7" + "libxcomposite1": "1:0.4.4-1" + "smbclient": "2:4.1.6+dfsg-1ubuntu2" + "libconvert-tnef-perl": "0.18-1" + "libreoffice-l10n-gl": "1:4.2.3~rc3-0ubuntu1" + "libibverbs-dev": "1.1.7-1ubuntu1" + "librpmbuild3": "4.11.1-3" + "libxerces2-java": "2.11.0-7" + "qtwebkit5-doc-html": "5.1.1-1ubuntu8" + "libostyle1c2": "1.4devel1-21" + "libpackagekit-glib2-dev": "0.8.12-1ubuntu5" + "python-lxml-dbg": "3.3.3-1" + "cinder-backup": "1:2014.1-0ubuntu1" + "libmono-system-reactive-providers2.2-cil": "3.2.8+dfsg-4ubuntu1" + "munin-plugins-extra": "2.0.19-3" + "python3-docutils": "0.11-3" + "ecryptfs-utils-dbg": "104-0ubuntu1" + "libmono-i18n-other4.0-cil": "3.2.8+dfsg-4ubuntu1" + "python-ceilometerclient": "1.0.8-0ubuntu1" + "xserver-xorg-input-synaptics-dev-lts-quantal": "3:5" + "xserver-xorg-input-synaptics-lts-quantal-dbg": "3:5" + "libmm-glib-dev": "1.0.0-2ubuntu1" + "python3-cairo-dev": "1.10.0+dfsg-3ubuntu2" + "unity-scope-colourlovers": "0.1+13.10.20130723-0ubuntu1" + "python-netifaces-dbg": "0.8-3build1" + "python-gevent": "1.0-1ubuntu1" + "unity-scope-musicstores": "6.9.0+13.10.20131011-0ubuntu1" + "keyboard-configuration": "1.70ubuntu8" + "libgpod-doc": "0.8.3-4ubuntu3" + "exim4-daemon-light": "4.82-3ubuntu2" + "libapr1-dev": "1.5.0-1" + "libcap-ng-dev": "0.7.3-1ubuntu2" + "libgnome2-doc": "2.32.1-4ubuntu1" + "libxml2-doc": "2.9.1+dfsg1-3ubuntu4" + "libfreeradius-dev": "2.1.12+dfsg-1.2ubuntu8" + "python-pyorbit": "2.24.0-6ubuntu4" + "libapt-pkg-perl": "0.1.29build1" + "thunderbird-locale-sl": "1:24.4.0+build1-0ubuntu1" + "libfile-desktopentry-perl": "0.07-1" + "gtk2-engines-murrine": "0.98.2-0ubuntu2" + "pst-utils": "0.6.59-1build1" + "libconfig-tiny-perl": "2.20-1" + "libdatrie1-bin": "0.2.8-1" + "liblapack-dev": "3.5.0-2ubuntu1" + "libproperties-cpp-dev": "0.0.1+14.04.20140220-0ubuntu1" + "thunderbird-locale-ca": "1:24.4.0+build1-0ubuntu1" + "ubuntu-release-upgrader-gtk": "1:0.220.2" + "dovecot-managesieved": "1:2.2.9-1ubuntu2" + "libdbusmenu-gtk3-dev": "12.10.3+14.04.20140319-0ubuntu1" + "libxdamage1": "1:1.1.4-1ubuntu1" + "python3-lxml": "3.3.3-1" + "nginx": "1.4.6-1ubuntu3" + "dmsetup": "2:1.02.77-6ubuntu2" + "libgles2-mesa-lts-raring": "3:5" + "libvpx1-dbg": "1.3.0-2" + "libyaml-0-2-dbg": "0.1.4-3ubuntu3" + "patch": "2.7.1-4" + "python-gi-dbg": "3.12.0-1" + "hyphen-de": "1:4.2.1-0ubuntu1" + "python-pyudev": "0.16.1-2build1" + "corosync": "2.3.3-1ubuntu1" + "libshout3": "2.3.1-3" + "libxcb-xkb-dev": "1.10-2ubuntu1" + "cifs-utils": "2:6.0-1ubuntu2" + "smokegen-dbg": "4:4.13.0-0ubuntu1" + "libxau6": "1:1.0.8-1" + "libmono-microsoft8.0-cil": "3.2.8+dfsg-4ubuntu1" + "texlive-pstricks-doc": "2013.20140215-2" + "ttf-telugu-fonts": "1:0.5.14ubuntu1" + "libjson0": "0.11-3ubuntu1" + "libkrb5-26-heimdal": "1.6~git20131207+dfsg-1ubuntu1" + "unity-action-doc": "1.1.0+14.04.20140304-0ubuntu1" + "libjavascriptcoregtk-3.0-0-dbg": "2.4.0-1ubuntu2" + "libpam-ck-connector": "0.4.5-3.1ubuntu2" + "nut-snmp": "2.7.1-1ubuntu1" + "libmono-system-web-mvc3.0-cil": "3.2.8+dfsg-4ubuntu1" + "libtelepathy-farstream-doc": "0.6.1-0ubuntu1" + "mythes-ru": "1:4.2.1-0ubuntu1" + "python3-itsdangerous": "0.22+dfsg1-1build1" + "libfolks-eds25": "0.9.5-1ubuntu5" + "language-pack-gnome-oc-base": "1:14.04+20140410" + "libnih-dbus-dev": "1.0.3-4ubuntu25" + "libpixman-1-0": "0.30.2-2ubuntu1" + "libxxf86vm-dev": "1:1.1.3-1" + "tk8.6": "8.6.1-3ubuntu2" + "language-pack-ja-base": "1:14.04+20140410" + "python3-simplejson": "3.3.1-1ubuntu6" + "language-pack-pap-base": "1:14.04+20140410" + "libsfatomic1-armhf-cross": "4.8.2-16ubuntu4cross0.11" + "python-twisted-words": "13.2.0-1ubuntu1" + "tcl8.6-doc": "8.6.1-4ubuntu1" + "g++-4.8-arm-linux-gnueabihf": "4.8.2-16ubuntu4cross0.11" + "libxcb-xfixes0-dev": "1.10-2ubuntu1" + "pulseaudio-module-zeroconf": "1:4.0-0ubuntu11" + "xserver-xorg-core-lts-quantal-dbg": "3:5" + "language-pack-an": "1:14.04+20140410" + "language-pack-gnome-pap": "1:14.04+20140410" + "python-openstack-auth": "1.1.3-0ubuntu3" + "fontforge-dbg": "20120731.b-5" + "libgmp3-dev": "2:5.1.3+dfsg-1ubuntu1" + "libutempter-dev": "1.1.5-4build1" + "libmodule-refresh-perl": "0.17-1" + "haproxy": "1.4.24-2" + "libgflags-dev": "2.0-1.1ubuntu1" + "libpciaccess0": "0.13.2-1" + "libunity-gtk3-parser-dev": "0.0.0+14.04.20140403-0ubuntu1" + "libgoogle-glog-doc": "0.3.3-1" + "python-oops-wsgi": "0.0.10-0ubuntu2" + "crash": "7.0.3-3ubuntu2" + "gnome-disk-utility": "3.10.0-1ubuntu3" + "llvm-3.4": "1:3.4-1ubuntu3" + "qemu-system-ppc": "2.0.0~rc1+dfsg-0ubuntu3" + "language-pack-gnome-te-base": "1:14.04+20140410" + "libburn-doc": "1.3.4-0ubuntu1" + "libdate-manip-perl": "6.42-1" + "libcdb-dev": "0.78" + "libxdmcp-dev": "1:1.1.1-1" + "libfile-sharedir-install-perl": "0.07-1" + "libdotconf0": "1.3-0ubuntu2" + "liborc-0.4-0-dbg": "1:0.4.18-1ubuntu1" + "libxres1": "2:1.0.7-1" + "pidgin-libnotify": "0.14-9ubuntu2" + "fontconfig-config": "2.11.0-0ubuntu4" + "libfontenc1-dbg": "1:1.1.2-1" + "libsmokephonon3": "4:4.13.0-0ubuntu1" + "xchat-gnome-indicator": "0.3.11-0ubuntu4" + "udev": "204-5ubuntu20.3" + "libvte-2.90-common": "1:0.34.9-1ubuntu1" + "python-pastedeploy-tpl": "1.5.2-1" + "firefox-locale-ga": "28.0+build2-0ubuntu2" + "libcaca-dev": "0.99.beta18-1ubuntu5" + "libgstreamer1.0-dev": "1.2.3-1" + "libcrack2": "2.9.1-1build1" + "libglamor-ltss0": "3:5" + "libldns1": "1.6.17-1" + "libnl-nf-3-200": "3.2.21-1" + "libxfixes3-dbg": "1:5.0.1-1ubuntu1" + "python-xcbgen": "1.10-1" + "plymouth-theme-ubuntu-logo": "0.8.8-0ubuntu17" + "qtdeclarative5-particles-plugin": "5.2.1-3ubuntu15" + "bacula-common-mysql": "5.2.6+dfsg-9.1ubuntu3" + "firefox-locale-hy": "28.0+build2-0ubuntu2" + "libxvmc-dev": "2:1.0.8-1ubuntu1" + "texlive-binaries": "2013.20130729.30972-2build3" + "thunderbird-locale-da": "1:24.4.0+build1-0ubuntu1" + "libgmime2.6-cil-dev": "2.6.20-0ubuntu1" + "python-django-maas": "1.5+bzr2252-0ubuntu1" + "libcupsppdc1": "1.7.2-0ubuntu1" + "libqt5clucene5": "5.2.1-8build1" + "firefox-locale-br": "28.0+build2-0ubuntu2" + "libevent-pthreads-2.0-5": "2.0.21-stable-1ubuntu1" + "firefox-locale-bn": "28.0+build2-0ubuntu2" + "freerdp-dbg": "1.0.2-2ubuntu1" + "python-billiard": "3.3.0.15-1ubuntu1" + "language-pack-gnome-eo": "1:14.04+20140410" + "libostyle-dev": "1.4devel1-21" + "libreadline-gplv2-dev": "5.2+dfsg-2" + "xserver-xorg-input-vmmouse": "1:13.0.0-1build1" + "antlr-doc": "2.7.7+dfsg-5" + "libmono-system-drawing4.0-cil": "3.2.8+dfsg-4ubuntu1" + "erlang-eldap": "1:16.b.3-dfsg-1ubuntu2" + "libtelepathy-logger-dev": "0.8.0-3" + "libx32gcc-4.8-dev": "4.8.2-19ubuntu1" + "texlive-latex-base": "2013.20140215-1" + "erlang-parsetools": "1:16.b.3-dfsg-1ubuntu2" + "libqt5x11extras5-dev": "5.2.1-1" + "valac-0.22": "0.22.1-0ubuntu1" + "p11-kit": "0.20.2-2ubuntu2" + "python-librabbitmq": "1.0.3-0ubuntu1" + "libaccounts-qt-doc": "1.11+14.04.20140410.1-0ubuntu1" + "libprocess-cpp-doc": "1.0.0+14.04.20140328-0ubuntu1" + "gir1.2-mx-1.0": "1.4.7-0ubuntu3" + "gstreamer1.0-tools": "1.2.3-1" + "libglib2.0-cil": "2.12.10-5" + "libmono-system-windows4.0-cil": "3.2.8+dfsg-4ubuntu1" + "myspell-gd": "0.50-10" + "isc-dhcp-common": "4.2.4-7ubuntu12" + "packagekit-backend-aptcc": "0.8.12-1ubuntu5" + "python-gtk-vnc": "0.5.3-0ubuntu2" + "gnome-video-effects": "0.4.1-0ubuntu1" + "java-common": "0.51" + "libmono-system-reactive-linq2.2-cil": "3.2.8+dfsg-4ubuntu1" + "libdbusmenu-qt2": "0.9.3+14.04.20140314-0ubuntu1" + "libexiv2-12": "0.23-1ubuntu2" + "mythes-de-ch": "20120516-2" + "libnotify-bin": "0.7.6-1ubuntu3" + "libreoffice-presentation-minimizer": "1:4.2.3~rc3-0ubuntu2" + "unity-scope-yelp": "0.1+13.10.20130723-0ubuntu1" + "oxideqt-dbg": "1.0.0~bzr501-0ubuntu1" + "strongswan-plugin-eap-radius": "5.1.2-0ubuntu2" + "gir1.2-gupnp-1.0": "0.20.10-1ubuntu1" + "libcloog-ppl1": "0.16.1-5" + "libclutter-gst-2.0-0": "2.0.8-1build1" + "hyphen-mr": "0.7.0-1" + "language-pack-gnome-uz-base": "1:14.04+20140410" + "ldp-docbook-xsl": "0.0.20040321-2build1" + "libmono-codecontracts4.0-cil": "3.2.8+dfsg-4ubuntu1" + "pdksh": "46-2ubuntu3" + "libglu1-mesa": "9.0.0-2" + "libgsettings-qt1": "0.1+14.04.20140408-0ubuntu1" + "distro-info-data": "0.18" + "gstreamer1.0-plugins-base": "1.2.3-1" + "thunderbird-locale-et": "1:24.4.0+build1-0ubuntu1" + "xserver-xorg-input-mouse-lts-quantal": "3:5" + "fonts-wqy-microhei": "0.2.0-beta-2" + "python-piston-mini-client": "0.7.5-0ubuntu2" + "libqpdf13": "5.1.1-1" + "xdelta3": "3.0.7-dfsg-2" + "multipath-tools-boot": "0.4.9-3ubuntu7" + "casper": "1.340" + "libfl-dev": "2.5.35-10.1ubuntu2" + "libsp1-dev": "1.3.4-1.2.1-47.3ubuntu1" + "libwebkitgtk-3.0-0": "2.4.0-1ubuntu2" + "libreoffice-l10n-ar": "1:4.2.3~rc3-0ubuntu1" + "libldb1": "1:1.1.16-1" + "libsnappy-dev": "1.1.0-1ubuntu1" + "xfpt": "0.09-1" + "lib32asan0": "4.8.2-19ubuntu1" + "lib32stdc++6-4.8-dbg": "4.8.2-19ubuntu1" + "lxc-templates": "1.0.3-0ubuntu3" + "redland-utils": "1.0.17-1" + "strongswan-tnc-client": "5.1.2-0ubuntu2" + "python-moinmoin": "1.9.7-1ubuntu2" + "language-pack-gnome-ti": "1:14.04+20140410" + "libhtml-format-perl": "2.11-1" + "libmono-http4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libservlet3.0-java-doc": "7.0.52-1" + "libtomcat7-java": "7.0.52-1" + "hyphen-bn": "0.7.0-2" + "libmono-system-runtime4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libusb-0.1-4": "2:0.1.12-23.3ubuntu1" + "os-prober": "1.63ubuntu1" + "python-pisock": "0.12.5-6ubuntu2" + "python-quantumclient": "1:2.3.4-0ubuntu1" + "libcairo2": "1.13.0~20140204-0ubuntu1" + "language-pack-gnome-lo-base": "1:14.04+20140410" + "linux-signed-generic-lts-saucy-eol-upgrade": "3.13.0.24.28" + "signon-plugins-dev": "8.56+14.04.20140307-0ubuntu2" + "librados2-dbg": "0.79-0ubuntu1" + "xserver-xorg-video-openchrome-lts-raring-dbg": "3:5" + "libwww-perl": "6.05-2" + "unity-control-center": "14.04.3+14.04.20140410-0ubuntu1" + "libapt-inst1.5": "1.0.1ubuntu2.1" + "libindicator3-dev": "12.10.2+14.04.20140402-0ubuntu1" + "libtransitioner2": "1.1.10+git20130802-1ubuntu2" + "libnfnetlink-dev": "1.0.1-2" + "libsmokeqttest4-3": "4:4.13.0-0ubuntu1" + "qt4-default": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "postfix-dev": "2.11.0-1" + "unity-asset-pool": "0.8.24daily13.06.10-0ubuntu1" + "firefox-locale-fa": "28.0+build2-0ubuntu2" + "grub-ieee1275-bin": "2.02~beta2-9" + "libgcj14-awt": "4.8.2-19ubuntu1" + "ifenslave": "2.4ubuntu1" + "postgresql": "9.3+154" + "python3-dbusmock": "0.10.1-1" + "libgraphite2-3-dbg": "1.2.4-1ubuntu1" + "libxft2-dbg": "2.3.1-2" + "libmono-opensystem-c4.0-cil": "3.2.8+dfsg-4ubuntu1" + "miscfiles": "1.4.2.dfsg.1-9.1" + "xinetd": "1:2.3.15-3ubuntu1" + "python3-pyqt5.qtopengl-dbg": "5.2.1+dfsg-1ubuntu1" + "xserver-xorg-video-cirrus-lts-quantal": "3:5" + "xserver-xorg-video-intel-lts-quantal": "3:5" + "mythes-ro": "1:4.2.1-0ubuntu1" + "python3-software-properties": "0.92.36" + "libdatetime-perl": "2:1.06-1" + "libobjc-4.7-dev": "4.7.3-12ubuntu1" + "libprotoc8": "2.5.0-9ubuntu1" + "xserver-xorg-glamoregl-lts-saucy": "3:5" + "libjmock-java-doc": "1.2.0-2" + "gnupg": "1.4.16-1ubuntu2" + "gstreamer0.10-gconf": "0.10.31-3+nmu1ubuntu5" + "imagemagick-dbg": "8:6.7.7.10-6ubuntu3" + "python3-apt": "0.9.3.5" + "language-pack-lb-base": "1:14.04+20140410" + "libpam-systemd": "204-5ubuntu20" + "language-pack-ko": "1:14.04+20140410" + "libprocess-cpp1": "1.0.0+14.04.20140328-0ubuntu1" + "totem-plugins": "3.10.1-1ubuntu4" + "webaccounts-extension-common": "0.5-0ubuntu2" + "python3-extras": "0.0.3-2ubuntu1" + "libavahi-qt4-dev": "0.6.31-4ubuntu1" + "liblexical-sealrequirehints-perl": "0.007-1build1" + "libunwind8": "1.1-2.2ubuntu3" + "libxcb-randr0": "1.10-2ubuntu1" + "gstreamer0.10-plugins-good-doc": "0.10.31-3+nmu1ubuntu5" + "libreoffice-l10n-uk": "1:4.2.3~rc3-0ubuntu1" + "naturaldocs": "1:1.5.1-0ubuntu1" + "linux-firmware": "1.127" + "libmono-system-web-webpages-deployment2.0-cil": "3.2.8+dfsg-4ubuntu1" + "oem-config": "2.18.7" + "language-pack-gnome-mhr-base": "1:14.04+20140410" + "libgail-3-doc": "3.10.8-0ubuntu1" + "libmysqld-dev": "5.5.35+dfsg-1ubuntu1" + "libsoup2.4-1": "2.44.2-1ubuntu2" + "python-libxml2": "2.9.1+dfsg1-3ubuntu4" + "apport-retrace": "2.14.1-0ubuntu3" + "erlang-nox": "1:16.b.3-dfsg-1ubuntu2" + "jasper": "0.69" + "libunity-scopes-json-def-desktop": "7.1.4+14.04.20140210-0ubuntu1" + "libdrm-nouveau2": "2.4.52-1" + "postgresql-common": "154" + "xserver-common-lts-saucy": "3:5" + "acpica-tools": "20140214-1ubuntu1" + "libqt5widgets5": "5.2.1+dfsg-1ubuntu14" + "plymouth-theme-ubuntu-text": "0.8.8-0ubuntu17" + "libpod-plainer-perl": "1.03-1" + "librsync-dbg": "0.9.7-10" + "postfix-cdb": "2.11.0-1" + "ubuntu-ui-toolkit-theme": "0.1.46+14.04.20140408.1-0ubuntu1" + "gnome-sudoku": "1:3.10.2-0ubuntu2" + "lib32quadmath0-dbg": "4.8.2-19ubuntu1" + "liblua5.2-dev": "5.2.3-1" + "language-pack-xh": "1:14.04+20140410" + "libfile-slurp-perl": "9999.19-4" + "libx32objc-4.7-dev": "4.7.3-12ubuntu1" + "numlockx": "1.2-5" + "thunderbird-locale-ko": "1:24.4.0+build1-0ubuntu1" + "init-system-helpers": "1.14" + "deja-dup": "30.0-0ubuntu4" + "libnih1": "1.0.3-4ubuntu25" + "libpoppler-cpp0": "0.24.5-2ubuntu4" + "libsnmp30": "5.7.2~dfsg-8.1ubuntu3" + "bacula-director-pgsql-dbg": "5.2.6+dfsg-9.1ubuntu3" + "libapr1-dbg": "1.5.0-1" + "unity-scope-video-remote": "0.3.15+13.10.20130920-0ubuntu1" + "libdbus-glib-1-doc": "0.100.2-1" + "libvorbis-dev": "1.3.2-1.3ubuntu1" + "lupin-support": "0.55" + "language-pack-gnome-cy-base": "1:14.04+20140410" + "cpio": "2.11+dfsg-1ubuntu1" + "libopencc-dev": "0.4.3-2build1" + "libpthread-stubs0-dev": "0.3-4" + "thunderbird-locale-ja": "1:24.4.0+build1-0ubuntu1" + "libaccount-plugin-1.0-doc": "0.1.7~+14.04.20140211.2-0ubuntu4" + "libmono-system-xml-linq4.0-cil": "3.2.8+dfsg-4ubuntu1" + "iputils-arping": "3:20121221-4ubuntu1" + "libjte-dev": "1.19-2" + "python-pyinotify-doc": "0.9.4-1build1" + "python-rsvg": "2.32.0+dfsg-3" + "gnome-control-center-shared-data": "1:3.6.3-0ubuntu56" + "gsfonts-x11": "0.22" + "libreoffice-l10n-kk": "1:4.2.3~rc3-0ubuntu1" + "myspell-fo": "0.4.2-1" + "neutron-dhcp-agent": "1:2014.1-0ubuntu1" + "python-smbc": "1.0.14.1-0ubuntu2" + "xserver-xorg-video-modesetting-dbg": "0.8.1-1build1" + "libgles2-mesa-lts-saucy-dbg": "3:5" + "liblircclient0": "0.9.0-0ubuntu5" + "libstrigiqtdbusclient-dev": "0.7.8-1ubuntu2" + "libwebkitgtk-3.0-0-dbg": "2.4.0-1ubuntu2" + "nagios3-cgi": "3.5.1-1ubuntu1" + "linux-image-extra-3.13.0-30-generic": "3.13.0-30.55" + "xserver-xorg-input-all-lts-raring": "3:5" + "language-pack-gnome-oc": "1:14.04+20140410" + "chkrootkit": "0.49-4.1ubuntu1" + "libburn-dbg": "1.3.4-0ubuntu1" + "liblua5.2-rrd-dev": "1.4.7-2ubuntu5" + "libx32stdc++6": "4.8.2-19ubuntu1" + "libxrender1": "1:0.9.8-1" + "libcommons-net-java": "1.4.1-5build1" + "libhud-gtk1-doc": "13.10.1+14.04.20140402-0ubuntu1" + "libmagickcore-dev": "8:6.7.7.10-6ubuntu3" + "libpq-dev": "9.3.4-1" + "x11-xserver-utils": "7.7+2ubuntu1" + "evince-dbg": "3.10.3-0ubuntu10" + "geoclue-ubuntu-geoip": "1.0.2+14.04.20131125-0ubuntu2" + "libjavascriptcoregtk-1.0-dev": "2.4.0-1ubuntu2" + "libopenipmi-dev": "2.0.18-0ubuntu7" + "libstartup-notification0": "0.12-3ubuntu1" + "libsaxonb-java": "9.1.0.8+dfsg-1" + "ttf-dejavu-extra": "2.34-1ubuntu1" + "libccolamd2.8.0": "1:4.2.1-3ubuntu1" + "libgfortran3-dbg": "4.8.2-19ubuntu1" + "libreoffice-style-tango": "1:4.2.3~rc3-0ubuntu2" + "thunderbird-locale-en-gb": "1:24.4.0+build1-0ubuntu1" + "netpbm": "2:10.0-15ubuntu2" + "python-gd": "0.56+dfsg-4build1" + "strongswan-pt-tls-client": "5.1.2-0ubuntu2" + "python3.4-dev": "3.4.0-2ubuntu1" + "uuid-dev": "2.20.1-5.1ubuntu20" + "python3-imaging-tk-dbg": "2.3.0-1ubuntu3" + "bacula-common-pgsql-dbg": "5.2.6+dfsg-9.1ubuntu3" + "firefox-locale-eu": "28.0+build2-0ubuntu2" + "lib32bz2-dev": "1.0.6-5" + "libxatracker1-lts-raring": "3:5" + "libboost-python-dev": "1.54.0.1ubuntu1" + "libegl1-mesa-lts-raring-dbg": "3:5" + "libmythes-dev": "2:1.2.2-1ubuntu2" + "libtest-without-module-perl": "0.17-1" + "myspell-hy": "0.20.0-2" + "liblua5.2-0": "5.2.3-1" + "unity-services": "7.2.0+14.04.20140416-0ubuntu1" + "fonts-sil-ezra": "2.51-8" + "libc6-dev-ppc64el-cross": "2.19-0ubuntu2cross0.2" + "libebook-contacts-1.2-0": "3.10.4-0ubuntu1" + "libopenvg1-mesa-dev": "10.1.0-4ubuntu5" + "libssh-dev": "0.6.1-0ubuntu3" + "gnome-video-effects-dev": "0.4.1-0ubuntu1" + "language-pack-bho-base": "1:14.04+20140410" + "libdpkg-perl": "1.17.5ubuntu5.3" + "libx32z1-dev": "1:1.2.8.dfsg-1ubuntu1" + "language-pack-sd-base": "1:14.04+20140410" + "nbd-client": "1:3.7-1" + "python-gobject-2": "2.28.6-12build1" + "secureboot-db": "1.1" + "language-pack-dv-base": "1:14.04+20140410" + "software-center-aptdaemon-plugins": "0.1.6build1" + "libdbus-1-3": "1.6.18-0ubuntu4" + "telepathy-haze-dbg": "0.8.0-1" + "ruby1.9.1-examples": "1.9.3.484-2ubuntu1" + "tex-gyre": "2.004.2-4" + "libcephfs-jni-dbg": "0.79-0ubuntu1" + "libunicode-linebreak-perl": "0.0.20131101-1" + "qtdeclarative5-window-plugin": "5.2.1-3ubuntu15" + "libgnumail-java": "1.1.2-9ubuntu3" + "mime-support": "3.54ubuntu1" + "libgl1-mesa-glx-lts-quantal": "3:5" + "libsoprano-dbg": "2.9.4+dfsg1-0ubuntu2" + "heat-api": "2014.1-0ubuntu1" + "language-pack-sk": "1:14.04+20140410" + "libmono-sharpzip2.84-cil": "3.2.8+dfsg-4ubuntu1" + "libwebp5": "0.4.0-4" + "gnome-desktop3-data": "3.8.4-0ubuntu3" + "libavahi-common3": "0.6.31-4ubuntu1" + "qt4-designer": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "libxorg-gtest-doc": "0.7.1-0ubuntu1" + "qt-at-spi-doc": "0.3.1-4fakesync1" + "libedata-cal1.2-dev": "3.10.4-0ubuntu1" + "libgles2-mesa-lts-quantal-dbg": "3:5" + "libx86-dev": "1.1+ds1-10" + "docbook-xsl-ns": "1.78.1+dfsg-1" + "eglibc-source": "2.19-0ubuntu6" + "linux-headers-3.13.0-32": "3.13.0-32.57" + "xserver-common-lts-quantal": "3:5" + "language-pack-gnome-aa-base": "1:14.04+20140410" + "libxml-sax-writer-perl": "0.53-1" + "busybox-initramfs": "1:1.21.0-1ubuntu1" + "libstreams-dev": "0.7.8-1ubuntu2" + "libnl-cli-3-200": "3.2.21-1" + "oxideqt-codecs-extra": "1.0.0~bzr501-0ubuntu1" + "ruby-shadow": "2.2.0-1" + "indent-doc": "2.2.11-4" + "language-pack-eu": "1:14.04+20140410" + "libsaxonb-java-doc": "9.1.0.8+dfsg-1" + "python3-oneconf": "0.3.7" + "fuse-dbg": "2.9.2-4ubuntu4" + "language-pack-gnome-tk-base": "1:14.04+20140410" + "language-pack-lb": "1:14.04+20140410" + "libcpg-dev": "2.3.3-1ubuntu1" + "libcppunit-subunit0": "0.0.18-0ubuntu7" + "libgtksourceview-3.0-dev": "3.10.2-0ubuntu1" + "ibus": "1.5.5-1ubuntu3" + "libboost-program-options-dev": "1.54.0.1ubuntu1" + "libgnome2-bin": "2.32.1-4ubuntu1" + "libsoup-gnome2.4-dev": "2.44.2-1ubuntu2" + "libboost-test1.54-dev": "1.54.0-4ubuntu3" + "libneon27-gnutls-dev": "0.30.0-1ubuntu1" + "libsmokebase3": "4:4.13.0-0ubuntu1" + "libtasn1-6-dbg": "3.4-3" + "ntpdate": "1:4.2.6.p5+dfsg-3ubuntu2" + "nut-server": "2.7.1-1ubuntu1" + "language-pack-gnome-lg-base": "1:14.04+20140410" + "language-pack-sw-base": "1:14.04+20140410" + "libgcr-base-3-1": "3.10.1-1" + "liblvm2cmd2.02": "2.02.98-6ubuntu2" + "libustr-dev": "1.0.4-3ubuntu2" + "libatomic1": "4.8.2-19ubuntu1" + "libtalloc2": "2.1.0-1" + "libtspi1": "0.3.11.2-1" + "libunicode-utf8-perl": "0.59-1build1" + "thunderbird-locale-en": "1:24.4.0+build1-0ubuntu1" + "libarchive-zip-perl": "1.30-7" + "pidgin-data": "1:2.10.9-0ubuntu3" + "libglapi-mesa-lts-raring-dbg": "3:5" + "libgrantlee-gui0": "0.4.0-0ubuntu1" + "syslinux": "3:4.05+dfsg-6+deb8u1" + "neutron-plugin-metaplugin": "1:2014.1-0ubuntu1" + "postgresql-client-common": "154" + "g++-arm-linux-gnueabihf": "4:4.8.2-1" + "libcupscgi1": "1.7.2-0ubuntu1" + "qtbase5-examples": "5.2.1+dfsg-1ubuntu14" + "ibus-table-extraphrase": "1.2.0.20100305-1" + "libautodie-perl": "2.23-1" + "firefox-locale-en": "28.0+build2-0ubuntu2" + "libgoogle-perftools4-dbg": "2.1-2ubuntu1" + "gimp-help-nl": "2.6.1-1" + "libnm-glib4": "0.9.8.8-0ubuntu7" + "php5-mysql": "5.5.9+dfsg-1ubuntu4" + "docutils-doc": "0.11-3" + "ubuntu-settings": "14.04.5" + "geoip-bin": "1.6.0-1" + "libdb-java-dev": "1:5.3.21~exp1ubuntu1" + "libdlrestrictions-dev": "0.15.12ubuntu1" + "qemu-system-mips": "2.0.0~rc1+dfsg-0ubuntu3" + "sni-qt": "0.2.6-0ubuntu1" + "srvadmin-hapi": "7.1.0-3" + "libmono-simd2.0-cil": "3.2.8+dfsg-4ubuntu1" + "doxygen-dbg": "1.8.6-2" + "libcrmservice1": "1.1.10+git20130802-1ubuntu2" + "libquadmath0-dbg": "4.8.2-19ubuntu1" + "libtasn1-6-dev": "3.4-3" + "libgtk2.0-0": "2.24.23-0ubuntu1" + "packagekit-docs": "0.8.12-1ubuntu5" + "libcupsmime1": "1.7.2-0ubuntu1" + "gir1.2-gtkclutter-1.0": "1.4.4-3ubuntu2" + "gstreamer0.10-plugins-base-dbg": "0.10.36-1.1ubuntu2" + "libqt5sql5-sqlite": "5.2.1+dfsg-1ubuntu14" + "libxdmcp6-dbg": "1:1.1.1-1" + "nettle-dbg": "2.7.1-1" + "xserver-xorg-input-wacom-lts-raring": "3:5" + "libgtkmm-3.0-dbg": "3.10.1-0ubuntu2" + "liblapacke": "3.5.0-2ubuntu1" + "libqt5qml-graphicaleffects": "5.2.1-1" + "libxcb-dpms0-dev": "1.10-2ubuntu1" + "libxxf86dga1": "2:1.1.4-1" + "powernap": "2.18-0ubuntu2" + "libxfixes-dev": "1:5.0.1-1ubuntu1" + "python-minimal": "2.7.5-5ubuntu3" + "libfindlib-ocaml": "1.4-2" + "libgail-3-dev": "3.10.8-0ubuntu1" + "libsonic-dev": "0.1.18-0ubuntu1" + "gunicorn": "17.5-2build1" + "libmono-system-web-applicationservices4.0-cil": "3.2.8+dfsg-4ubuntu1" + "multiboot-doc": "0.97-29ubuntu66" + "erlang-dbg": "1:16.b.3-dfsg-1ubuntu2" + "erlang-inets": "1:16.b.3-dfsg-1ubuntu2" + "language-pack-gnome-wa-base": "1:14.04+20140410" + "evolution-dbg": "3.10.4-0ubuntu1" + "libmtdev-dev": "1.1.4-1ubuntu1" + "libxklavier16": "5.4-0ubuntu1" + "doxygen-latex": "1.8.6-2" + "gnome-control-center-data": "1:3.6.3-0ubuntu56" + "language-pack-gnome-af": "1:14.04+20140410" + "libatm1-dev": "1:2.5.1-1.5" + "libgl1-mesa-dri": "10.1.0-4ubuntu5" + "libindicator3-7": "12.10.2+14.04.20140402-0ubuntu1" + "libnm-util-dev": "0.9.8.8-0ubuntu7" + "libzzip-0-13": "0.13.62-2" + "live-build": "3.0~a57-1ubuntu11" + "libkpathsea-dev": "2013.20130729.30972-2build3" + "libnetaddr-ip-perl": "4.071+dfsg-1" + "nagios-plugins-basic": "1.5-3ubuntu1" + "qttools5-dev": "5.2.1-8build1" + "emacs-goodies-el": "35.8ubuntu2" + "gir1.2-farstream-0.1": "0.1.2-1ubuntu3" + "libpspell-dev": "0.60.7~20110707-1ubuntu1" + "libvisual-0.4-0": "0.4.0-5" + "language-pack-fo": "1:14.04+20140410" + "libmono-posix2.0-cil": "3.2.8+dfsg-4ubuntu1" + "dctrl-tools": "2.23ubuntu1" + "isc-dhcp-server": "4.2.4-7ubuntu12" + "libopus-dbg": "1.1-0ubuntu1" + "libqt5quicktest5": "5.2.1-3ubuntu15" + "libquorum5": "2.3.3-1ubuntu1" + "libstdc++6-powerpc-cross": "4.8.2-16ubuntu3cross0.11" + "python-defer": "1.0.6-2build1" + "sphinx-voxforge-lm-en": "0.1.1~daily20130301-0ubuntu1" + "graphviz": "2.36.0-0ubuntu3" + "libbonoboui2-dev": "2.24.5-0ubuntu3" + "libmono-windowsbase4.0-cil": "3.2.8+dfsg-4ubuntu1" + "system-config-printer-common": "1.4.3+20140219-0ubuntu2" + "libxrender1-dbg": "1:0.9.8-1" + "smartmontools": "6.2+svn3841-1.2" + "hunspell-sv-se": "1.51-1" + "ethtool": "1:3.13-1" + "libpils2-dev": "1.0.11+hg2754-1.1build1" + "libtirpc-dev": "0.2.2-5ubuntu2" + "nut-cgi": "2.7.1-1ubuntu1" + "ubuntu-release-upgrader-core": "1:0.220.2" + "libblkid1": "2.20.1-5.1ubuntu20" + "libsqlite3-0-dbg": "3.8.2-1ubuntu2" + "lzma": "9.22-2ubuntu2" + "fonts-tlwg-purisa": "1:0.5.1-3" + "libclamav6": "0.98.1+dfsg-4ubuntu1" + "libspectre-dev": "0.2.7-2ubuntu1" + "python-nose": "1.3.1-2" + "libthumbnailer0": "1.1+14.04.20140401.1-0ubuntu1" + "thunderbird-locale-lt": "1:24.4.0+build1-0ubuntu1" + "totem": "3.10.1-1ubuntu4" + "language-pack-wo-base": "1:14.04+20140410" + "libmono-system-web-http4.0-cil": "3.2.8+dfsg-4ubuntu1" + "mono-mcs": "3.2.8+dfsg-4ubuntu1" + "ruby-rgen": "0.6.6-1" + "thunderbird-locale-es": "1:24.4.0+build1-0ubuntu1" + "erlang-dev": "1:16.b.3-dfsg-1ubuntu2" + "ibus-sunpinyin": "2.0.3-5build1" + "libmpfr4-dbg": "3.1.2-1" + "libmime-charset-perl": "1.011.1-1" + "python-pyinotify": "0.9.4-1build1" + "python-tz": "2012c-1build1" + "virtuoso-opensource-6.1-common": "6.1.6+repack-0ubuntu3" + "libglapi-mesa-lts-saucy-dbg": "3:5" + "libc6-arm64-cross": "2.19-0ubuntu2cross0.10" + "nagios-images": "0.8" + "qtlocation5-doc": "5.2.1-1ubuntu2" + "ltspfsd": "1.3-1" + "wukrainian": "1.6.5-2" + "libustr-1.0-1-dbg": "1.0.4-3ubuntu2" + "sssd-ipa": "1.11.5-1ubuntu3" + "language-pack-gnome-bho-base": "1:14.04+20140410" + "myspell-sl": "1.0-5" + "libgnutls-openssl27": "2.12.23-12ubuntu2.1" + "libreoffice-avmedia-backend-gstreamer": "1:4.2.3~rc3-0ubuntu2" + "libhamcrest-java-doc": "1.3-4" + "pulseaudio-module-zeroconf-dbg": "1:4.0-0ubuntu11" + "python3-lazr.uri": "1.0.3-1build1" + "g++-multilib": "4:4.8.2-1ubuntu6" + "elks-libc": "0.16.17-3.1ubuntu3" + "logwatch": "7.4.0+svn20130529rev144-1ubuntu1" + "python-djorm-ext-pgarray": "0.8-0ubuntu2" + "gcr": "3.10.1-1" + "libumockdev-dev": "0.8.1-1" + "gstreamer1.0-pulseaudio": "1.2.3-1ubuntu2" + "gir1.2-bamf-3": "0.5.1+14.04.20140409-0ubuntu1" + "libwebkitgtk-3.0-dev": "2.4.0-1ubuntu2" + "xinit": "1.3.2-1" + "hyphen-ca": "1:4.2.1-0ubuntu1" + "libgcr-3-doc": "3.10.1-1" + "libsparsehash-dev": "1.10-1ubuntu1" + "linux-base": "3.5ubuntu4" + "python3-polib": "1.0.4-1" + "wgalician-minimos": "0.5-35" + "zsh": "5.0.2-3ubuntu6" + "xorg-docs": "1:1.7-1" + "libxrandr-dev-lts-quantal": "3:5" + "libyelp-dev": "3.10.2-0ubuntu1" + "rhythmbox-mozilla": "3.0.2-0ubuntu1" + "udisks2": "2.1.3-1" + "libmono-management2.0-cil": "3.2.8+dfsg-4ubuntu1" + "libatasmart4": "0.19-3" + "libegl1-mesa-dev-lts-saucy": "3:5" + "libgtk-3-0": "3.10.8-0ubuntu1" + "thunderbird-dbg": "1:24.4.0+build1-0ubuntu1" + "linux-lowlatency": "3.13.0.24.28" + "gtester2xunit": "0.1daily13.06.05-0ubuntu2" + "python-ply-doc": "3.4-3ubuntu2" + "colord": "1.0.6-1" + "libc6-dbg": "2.19-0ubuntu6" + "libgail-dbg": "2.24.23-0ubuntu1" + "libexif12": "0.6.21-1ubuntu1" + "libilmbase-dev": "1.0.1-6ubuntu1" + "thunderbird-locale-be": "1:24.4.0+build1-0ubuntu1" + "checkbox-ng": "0.3-2" + "dput": "0.9.6.4ubuntu1" + "language-pack-gnome-da-base": "1:14.04+20140410" + "libxml-commons-external-java": "1.4.01-2build1" + "libclass-load-xs-perl": "0.06-1build1" + "libcogl15": "1.16.2-1" + "libgfortran3": "4.8.2-19ubuntu1" + "libncursesw5-dbg": "5.9+20140118-1ubuntu1" + "ca-certificates": "20130906ubuntu2" + "python-webtest": "2.0.14-1ubuntu1" + "cryptsetup-bin": "2:1.6.1-1ubuntu1" + "gcc-4.7-base": "4.7.3-12ubuntu1" + "libaudio2": "1.9.4-1" + "libpe-status4-dev": "1.1.10+git20130802-1ubuntu2" + "libwnck22": "1:2.30.7-0ubuntu4" + "python-pil.imagetk": "2.3.0-1ubuntu3" + "umockdev": "0.8.1-1" + "gimp-help-it": "2.6.1-1" + "language-pack-gnome-ht": "1:14.04+20140410" + "gcc-arm-linux-gnueabihf": "4:4.8.2-1" + "libxrandr-dev-lts-saucy": "3:5" + "linux-image-generic-lts-raring": "3.13.0.24.28" + "libmono-custommarshalers4.0-cil": "3.2.8+dfsg-4ubuntu1" + "python-genetic": "0.1.1b-11build1" + "ltsp-client": "5.5.1-1ubuntu2" + "unity-scope-home": "6.8.2+14.04.20131029.1-0ubuntu1" + "firefox-locale-el": "28.0+build2-0ubuntu2" + "kdelibs5-dbg": "4:4.13.0-0ubuntu1" + "liburcu1": "0.7.12-0ubuntu2" + "libxres1-dbg": "2:1.0.7-1" + "linux-image-lowlatency": "3.13.0.24.28" + "libqt5multimedia5-plugins": "5.2.1-0ubuntu5" + "libsss-nss-idmap0": "1.11.5-1ubuntu3" + "libxcb-xvmc0": "1.10-2ubuntu1" + "lxc-tests": "1.0.3-0ubuntu3" + "python3-tk": "3.4.0-0ubuntu1" + "python3-werkzeug": "0.9.4+dfsg-1.1ubuntu1" + "texlive-bibtex-extra": "2013.20140215-2" + "cluster-glue-dev": "1.0.11+hg2754-1.1build1" + "libmirserver18": "0.1.8+14.04.20140411-0ubuntu1" + "policykit-1": "0.105-4ubuntu2" + "language-pack-kk-base": "1:14.04+20140410" + "firefox-locale-csb": "28.0+build2-0ubuntu2" + "libsignon-qt1": "8.56+14.04.20140307-0ubuntu2" + "unity-webapps-service": "2.5.0~+14.04.20140409-0ubuntu1" + "language-pack-gnome-hu-base": "1:14.04+20140410" + "libatk-wrapper-java": "0.30.4-4" + "libcommons-codec-java-doc": "1.9-1" + "libjunitperf-java": "1.9.1-8ubuntu1" + "distro-info": "0.12" + "isc-dhcp-relay-dbg": "4.2.4-7ubuntu12" + "libgdiplus": "2.11+git20131008.9732566-5ubuntu1" + "libunity-protocol-private0": "7.1.4+14.04.20140210-0ubuntu1" + "libc6-dev-powerpc-cross": "2.19-0ubuntu2cross1.1" + "libgcj-doc": "4.8.2-19ubuntu1" + "python3-sphinx": "1.2.2+dfsg-1ubuntu1" + "texlive-fonts-extra-doc": "2013.20140215-2" + "firefox-locale-bg": "28.0+build2-0ubuntu2" + "tmispell-voikko": "0.7.1-3" + "xserver-xorg-core": "2:1.15.1-0ubuntu2" + "software-center": "13.10-0ubuntu4" + "libmnl0": "1.0.3-3ubuntu1" + "xserver-xorg-video-radeon-lts-quantal-dbg": "3:5" + "libupstart-app-launch2": "0.3+14.04.20140411-0ubuntu1" + "itstool": "2.0.2-2" + "libgnomecanvas2-common": "2.30.3-2" + "libaccounts-qt1": "1.11+14.04.20140410.1-0ubuntu1" + "libpam-cap": "1:2.24-0ubuntu2" + "libpolkit-backend-1-dev": "0.105-4ubuntu2" + "python-pyao": "0.82-5build1" + "libx32stdc++-4.8-dev": "4.8.2-19ubuntu1" + "grub-efi-amd64": "2.02~beta2-9" + "libgdata13": "0.14.1-1" + "libgeoclue0": "0.12.99-3ubuntu1" + "libpam0g": "1.1.8-1ubuntu2" + "libplumbgpl2-dev": "1.0.11+hg2754-1.1build1" + "python-egenix-mxtools": "3.2.7-1build1" + "upstart-app-launch": "0.3+14.04.20140411-0ubuntu1" + "language-pack-fy-base": "1:14.04+20140410" + "python-jinja2": "2.7.2-2" + "xserver-common": "2:1.15.1-0ubuntu2" + "libfftw3-double3": "3.3.3-7ubuntu3" + "libfuse2": "2.9.2-4ubuntu4" + "libx32gomp1-dbg": "4.8.2-19ubuntu1" + "language-pack-gnome-pl-base": "1:14.04+20140410" + "libmono-xbuild-tasks4.0-cil": "3.2.8+dfsg-4ubuntu1" + "gedit": "3.10.4-0ubuntu4" + "libauparse-dev": "1:2.3.2-2ubuntu1" + "libburn-dev": "1.3.4-0ubuntu1" + "python3-cmd2": "0.6.7-2fakesync1build1" + "xcb-proto": "1.10-1" + "avahi-autoipd": "0.6.31-4ubuntu1" + "grub-xen-bin": "2.02~beta2-9" + "srvadmin-racsvc": "7.1.0-3" + "oneconf-common": "0.3.7" + "account-plugin-yahoo": "3.8.6-0ubuntu9" + "erlang-crypto": "1:16.b.3-dfsg-1ubuntu2" + "libgucharmap-2-90-7": "1:3.10.1-0ubuntu2" + "nvidia-settings": "331.20-0ubuntu8" + "libbrlapi-dbg": "5.0-2ubuntu2" + "python-geoip-dbg": "1.2.4-2ubuntu5" + "xserver-xorg-video-modesetting-lts-raring": "3:5" + "crossbuild-essential-powerpc": "11.6ubuntu6" + "language-pack-gu": "1:14.04+20140410" + "libt1-doc": "5.1.2-3.6ubuntu1" + "python3-requests": "2.2.1-1" + "gnome-power-manager": "3.8.2-1ubuntu2" + "xserver-xorg-video-mach64-lts-quantal": "3:5" + "libarchive-extract-perl": "0.70-1" + "lp-solve-doc": "5.5.0.13-7build1" + "unity-webapps-qml-doc": "0.1+14.04.20140408-0ubuntu1" + "libgsf-1-114-dbg": "1.14.27-2ubuntu2" + "libopenvg1-mesa-dev-lts-saucy": "3:5" + "libsfstdc++6-armhf-cross": "4.8.2-16ubuntu4cross0.11" + "libattr1": "1:2.4.47-1ubuntu1" + "libboost-iostreams1.54.0": "1.54.0-4ubuntu3" + "libwebkit2gtk-3.0-25": "2.4.0-1ubuntu2" + "linux-headers-generic-lts-raring": "3.13.0.24.28" + "language-pack-ru-base": "1:14.04+20140410" + "libaprutil1-dbg": "1.5.3-1" + "libkadm5clnt7-heimdal": "1.6~git20131207+dfsg-1ubuntu1" + "language-pack-sk-base": "1:14.04+20140410" + "python-egenix-mxtexttools-doc": "3.2.7-1build1" + "cups-server-common": "1.7.2-0ubuntu1" + "language-pack-fur-base": "1:14.04+20140410" + "linux-signed-image-generic-lts-raring": "3.13.0.24.28" + "libaccountsservice-doc": "0.6.35-0ubuntu7" + "xserver-xorg-video-neomagic-lts-raring": "3:5" + "xserver-xorg-video-sisusb-lts-raring": "3:5" + "tidy": "20091223cvs-1.2ubuntu1" + "xserver-xorg-input-vmmouse-lts-quantal": "3:5" + "language-pack-gnome-ve": "1:14.04+20140410" + "firefox-locale-kn": "28.0+build2-0ubuntu2" + "libgcc1-dbg": "1:4.9-20140406-0ubuntu1" + "liblapacke-dev": "3.5.0-2ubuntu1" + "rpcbind": "0.2.1-2ubuntu1" + "xserver-xorg-video-trident-lts-quantal": "3:5" + "dh-apparmor": "2.8.95~2430-0ubuntu5" + "libreoffice-help-pt-br": "1:4.2.3~rc3-0ubuntu1" + "dosfstools": "3.0.26-1" + "libotf0": "0.9.13-1ubuntu1" + "thunderbird-locale-gl": "1:24.4.0+build1-0ubuntu1" + "emacs24-bin-common": "24.3+1-2ubuntu1" + "libparams-validate-perl": "1.08-1" + "debiandoc-sgml": "1.2.28-1" + "python3-amqp": "1.3.3-1ubuntu1" + "unattended-upgrades": "0.82.1ubuntu2" + "libiodbc2-dev": "3.52.7-3.1" + "libpango1.0-0-dbg": "1.36.3-1ubuntu1" + "libpoppler-private-dev": "0.24.5-2ubuntu4" + "jlex": "1.2.6-7" + "language-pack-gnome-ar": "1:14.04+20140410" + "libgnomeui-common": "2.24.5-3" + "libppix-utilities-perl": "1.001000-1" + "bacula-director-mysql-dbg": "5.2.6+dfsg-9.1ubuntu3" + "libxcb-render0-dbg": "1.10-2ubuntu1" + "sssd": "1.11.5-1ubuntu3" + "libmono-system-runtime-caching4.0-cil": "3.2.8+dfsg-4ubuntu1" + "python3-pastedeploy": "1.5.2-1" + "thunderbird-locale-en-us": "1:24.4.0+build1-0ubuntu1" + "python-crochet": "1.0.0-0ubuntu2" + "python-testscenarios": "0.4-2ubuntu2" + "libaudiofile-dev": "0.3.6-2" + "libqt4-opengl": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "language-pack-gnome-tk": "1:14.04+20140410" + "libmro-compat-perl": "0.12-1" + "wakeonlan": "0.41-11" + "dovecot-imapd": "1:2.2.9-1ubuntu2" + "xserver-xorg-video-modesetting-lts-quantal-dbg": "3:5" + "cups-common": "1.7.2-0ubuntu1" + "exim4-doc-html": "4.82-2" + "libsemanage-common": "2.2-1" + "qtsensors5-dbg": "5.2.1+dfsg-2ubuntu2" + "python-jinja2-doc": "2.7.2-2" + "update-inetd": "4.43" + "libgmime-2.6-0": "2.6.20-0ubuntu1" + "libqimageblitz-dbg": "1:0.0.6-4build1" + "language-pack-gnome-zh-hant": "1:14.04+20140410" + "libtool-doc": "2.4.2-1.7ubuntu1" + "python-tablib": "0.9.11-2build1" + "cups-browsed": "1.0.52-0ubuntu1" + "gstreamer1.0-plugins-base-apps": "1.2.3-1" + "libqthelp4-perl": "4:4.13.0-0ubuntu1" + "crmsh": "1.2.5+hg1034-1ubuntu3" + "gnome-control-center-dev": "1:3.6.3-0ubuntu56" + "libc6-dev-arm64-cross": "2.19-0ubuntu2cross0.10" + "inkscape": "0.48.4-3ubuntu2" + "libboost-atomic1.54-dev": "1.54.0-4ubuntu3" + "language-pack-gnome-mr-base": "1:14.04+20140410" + "wdiff-doc": "1.2.1-2" + "libadns1": "1.4-2ubuntu1" + "libgcrypt11-dev": "1.5.3-2ubuntu4" + "liblvm2app2.2": "2.02.98-6ubuntu2" + "python3-reportlab-accel": "3.0-1build1" + "uidmap": "1:4.1.5.1-1ubuntu9" + "libvte-doc": "1:0.28.2-5ubuntu1" + "tar-doc": "1.27.1-1" + "espeak-dbg": "1.47.11-1ubuntu1" + "lib32asan0-dbg": "4.8.2-19ubuntu1" + "python-plist": "1.10-1" + "libx11-doc": "2:1.6.2-1ubuntu2" + "libcupsfilters1": "1.0.52-0ubuntu1" + "fonts-takao-gothic": "003.02.01-9ubuntu2" + "language-pack-te-base": "1:14.04+20140410" + "phonon-backend-gstreamer1.0": "4:4.7.1+git20140403-0ubuntu1" + "python-gtk2-doc": "2.24.0-3ubuntu3" + "libgupnp-igd-1.0-dev": "0.2.2-1" + "libxcb-shm0-dbg": "1.10-2ubuntu1" + "libyaml-dev": "0.1.4-3ubuntu3" + "compiz": "1:0.9.11+14.04.20140409-0ubuntu1" + "freeipmi-common": "1.1.5-3ubuntu3" + "libc6-ppc64el-cross": "2.19-0ubuntu2cross0.2" + "libgomp1-armhf-cross": "4.8.2-16ubuntu4cross0.11" + "libstdc++-4.8-dev-armhf-cross": "4.8.2-16ubuntu4cross0.11" + "nvidia-settings-319": "331.20-0ubuntu8" + "libsmbclient-dev": "2:4.1.6+dfsg-1ubuntu2" + "nux-tools": "4.0.6+14.04.20140409-0ubuntu1" + "libcogl-doc": "1.16.2-1" + "libqscintilla2-doc": "2.8.1-2" + "librhino-java-doc": "1.7R4-2" + "xfonts-scalable": "1:1.0.3-1" + "libraptor1": "1.4.21-10" + "libmono-oracle4.0-cil": "3.2.8+dfsg-4ubuntu1" + "maas-common": "1.5+bzr2252-0ubuntu1" + "pgf": "2.10-1" + "firefox-locale-sq": "28.0+build2-0ubuntu2" + "gir1.2-gucharmap-2.90": "1:3.10.1-0ubuntu2" + "python-heatclient": "0.2.8-0ubuntu1" + "python3-bs4": "4.2.1-1ubuntu2" + "sphinx-common": "1.2.2+dfsg-1ubuntu1" + "libapparmor-perl": "2.8.95~2430-0ubuntu5" + "logstash": "1.4.1-1-bd507eb" + "libcanberra-gtk3-dev": "0.30-0ubuntu3" + "glance-common": "1:2014.1-0ubuntu1" + "liblog-log4perl-perl": "1.41-1.1ubuntu1" + "python-gridfs": "2.6.3-1build1" + "liblouis2": "2.5.3-2ubuntu1" + "ubiquity-frontend-gtk": "2.18.7" + "pulseaudio-esound-compat-dbg": "1:4.0-0ubuntu11" + "libnotify-doc": "0.7.6-1ubuntu3" + "python-gtk2-dev": "2.24.0-3ubuntu3" + "python-redis": "2.7.2-1build1" + "libsignon-qt-dev": "8.56+14.04.20140307-0ubuntu2" + "libxen-ocaml": "4.4.0-0ubuntu5" + "eog-dbg": "3.10.2-0ubuntu5" + "libgtksourceview-3.0-1": "3.10.2-0ubuntu1" + "libkadm5clnt-mit9": "1.12+dfsg-2ubuntu4" + "mdbtools-dev": "0.7.1-1ubuntu1" + "unity-lens-applications": "7.1.0+13.10.20131011-0ubuntu2" + "language-pack-gnome-cs": "1:14.04+20140410" + "libgpg-error0": "1.12-0.2ubuntu1" + "libsasl2-modules-gssapi-mit": "2.1.25.dfsg1-17build1" + "libtspi-dev": "0.3.11.2-1" + "libmono-system-configuration4.0-cil": "3.2.8+dfsg-4ubuntu1" + "ghostscript-x": "9.10~dfsg-0ubuntu10" + "libreadline6": "6.3-4ubuntu2" + "texlive-fonts-recommended-doc": "2013.20140215-1" + "ttf-indic-fonts": "1:0.5.14ubuntu1" + "librabbitmq-dbg": "0.4.1-1" + "python-gi-cairo": "3.12.0-1" + "libcdio-paranoia1": "0.83-4.1ubuntu1" + "libcollection2": "0.3.0.1-4" + "libgee-0.8-2": "0.10.5-1ubuntu1" + "kdump-tools": "1.5.5-2ubuntu1" + "libcluster-glue-dev": "1.0.11+hg2754-1.1build1" + "libxml-sax-perl": "0.99+dfsg-2ubuntu1" + "libgphoto2-2-dev": "2.5.3.1-1ubuntu2" + "libxt-doc": "1:1.1.4-1" + "corosync-dbg": "2.3.3-1ubuntu1" + "libcrmcluster4-dev": "1.1.10+git20130802-1ubuntu2" + "libdiscid0": "0.6.1-2" + "libqca2": "2.0.3-5" + "libgssdp-1.0-3": "0.14.7-1ubuntu1" + "libossp-uuid16": "1.6.2-1.3ubuntu1" + "xorriso": "1.3.2-1ubuntu1" + "libgcc1-arm64-cross": "1:4.8.2-13ubuntu1cross0.11" + "libreoffice-l10n-tg": "1:4.2.3~rc3-0ubuntu1" + "bacula-console": "5.2.6+dfsg-9.1ubuntu3" + "landscape-client-ui-install": "14.01-0ubuntu3" + "soprano-daemon": "2.9.4+dfsg1-0ubuntu2" + "language-pack-gnome-ber-base": "1:14.04+20140410" + "language-pack-pa-base": "1:14.04+20140410" + "libssl-doc": "1.0.1f-1ubuntu2" + "libboost-system1.54.0": "1.54.0-4ubuntu3" + "libffado2": "2.1.0+svn2240-1ubuntu3" + "debhelper": "9.20131227ubuntu1" + "folks-common": "0.9.5-1ubuntu5" + "language-pack-gnome-ru-base": "1:14.04+20140410" + "xul-ext-websites-integration": "2.3.6+13.10.20130920.1-0ubuntu1" + "libwebpdemux1": "0.4.0-4" + "language-pack-gnome-zu-base": "1:14.04+20140410" + "libglapi-mesa-dbg": "10.1.0-4ubuntu5" + "libtidy-0.99-0": "20091223cvs-1.2ubuntu1" + "qtdeclarative5-folderlistmodel-plugin": "5.2.1-3ubuntu15" + "libgcr-3-common": "3.10.1-1" + "python-warlock": "1.1.0-0ubuntu2" + "lib32objc-4.7-dev": "4.7.3-12ubuntu1" + "libldb-dev": "1:1.1.16-1" + "libmemcached-tools": "1.0.8-1ubuntu2" + "libidl-common": "0.8.14-0.2ubuntu4" + "librest-0.7-0": "0.7.90-0ubuntu1" + "linux-tools-3.13.0-24": "3.13.0-24.46" + "tcl8.5-dev": "8.5.15-2ubuntu1" + "llvm-3.4-dev": "1:3.4-1ubuntu3" + "language-pack-gnome-wae": "1:14.04+20140410" + "python3-jsonpatch": "1.3-4" + "libcunit1-dev": "2.1-2.dfsg-1" + "libs3-2": "2.0-2" + "linux-server": "3.13.0.24.28" + "libhttp-negotiate-perl": "6.00-2" + "libreoffice-sdbc-hsqldb": "1:4.2.3~rc3-0ubuntu2" + "python3-lxml-dbg": "3.3.3-1" + "strongswan-tnc-server": "5.1.2-0ubuntu2" + "libfontconfig1": "2.11.0-0ubuntu4" + "libsepol1": "2.2-1" + "vlan": "1.9-3ubuntu10" + "libapache2-mod-perl2-doc": "2.0.8+httpd24-r1449661-6ubuntu2" + "libgtop2-common": "2.28.5-2" + "libreoffice-l10n-lt": "1:4.2.3~rc3-0ubuntu1" + "python3-testrepository": "0.0.18-1ubuntu1" + "libcompizconfig0": "1:0.9.11+14.04.20140409-0ubuntu1" + "thunderbird-locale-zh-cn": "1:24.4.0+build1-0ubuntu1" + "libsignon-qt5-dev": "8.56+14.04.20140307-0ubuntu2" + "linux-headers-generic-lts-trusty": "3.13.0.24.28" + "php5-odbc": "5.5.9+dfsg-1ubuntu4" + "python-crypto": "2.6.1-4build1" + "libmono-entityframework6.0-cil": "3.2.8+dfsg-4ubuntu1" + "manpages": "3.54-1ubuntu1" + "libburn4": "1.3.4-0ubuntu1" + "libcdio-paranoia-dev": "0.83-4.1ubuntu1" + "libcgraph6": "2.36.0-0ubuntu3" + "libbusiness-isbn-data-perl": "20120719.001-1" + "libsys-hostname-long-perl": "1.4-3" + "ubiquity-casper": "1.340" + "libqt5sensors5-dev": "5.2.1+dfsg-2ubuntu2" + "libgnomekbd-dev": "3.6.0-0ubuntu2" + "xserver-xorg-input-evdev-lts-quantal-dbg": "3:5" + "tk8.5": "8.5.15-2ubuntu3" + "libclass-singleton-perl": "1.4-1" + "qtserialport5-doc": "5.2.1-1" + "libboost-date-time1.54.0": "1.54.0-4ubuntu3" + "libcrack2-dev": "2.9.1-1build1" + "libhx509-5-heimdal": "1.6~git20131207+dfsg-1ubuntu1" + "libglewmx-dev": "1.10.0-3" + "liblzo2-2": "2.06-1.2ubuntu1" + "mdbtools-gmdb": "0.7.1-1ubuntu1" + "qtdeclarative5-ubuntu-ui-extras-browser-plugin": "0.23+14.04.20140414-0ubuntu1" + "xfslibs-dev": "3.1.9ubuntu2" + "libtsan0-dbg": "4.8.2-19ubuntu1" + "qemu-kvm": "2.0.0~rc1+dfsg-0ubuntu3" + "thunderbird-gnome-support-dbg": "1:24.4.0+build1-0ubuntu1" + "fonts-arphic-uming": "0.2.20080216.2-7ubuntu2" + "john-data": "1.8.0-1" + "libclass-c3-perl": "0.25-1" + "libreoffice-help-gl": "1:4.2.3~rc3-0ubuntu1" + "libcgmanager0": "0.24-0ubuntu7" + "libyajl2": "2.0.4-4" + "python-markupsafe": "0.18-1build2" + "python3-pyqt5.qtpositioning": "5.2.1+dfsg-1ubuntu1" + "bsh-doc": "2.0b4-15" + "language-pack-gnome-uz": "1:14.04+20140410" + "libmono-corlib2.0-cil": "3.2.8+dfsg-4ubuntu1" + "aspell": "0.60.7~20110707-1ubuntu1" + "libgcj14": "4.8.2-19ubuntu1" + "gnutls26-doc": "2.12.23-12ubuntu2" + "libthai-dev": "0.1.20-3" + "p11-kit-modules": "0.20.2-2ubuntu2" + "libcommons-httpclient-java-doc": "3.1-10.2" + "libmono-i18n-rare4.0-cil": "3.2.8+dfsg-4ubuntu1" + "gir1.2-clutter-1.0": "1.16.4-0ubuntu2" + "libgtkmm-3.0-dev": "3.10.1-0ubuntu2" + "mount": "2.20.1-5.1ubuntu20.1" + "python-oslo.rootwrap": "1.2.0-0ubuntu1" + "dnstracer": "1.9-4" + "liburl-dispatcher1-dev": "0.1+14.04.20140403-0ubuntu1" + "libxdot4": "2.36.0-0ubuntu3" + "libcunit1-doc": "2.1-2.dfsg-1" + "myspell-fa": "0.20070816-3" + "python-gobject": "3.12.0-1" + "unity-lens-photos": "1.0+14.04.20140318-0ubuntu1" + "clamav-daemon": "0.98.1+dfsg-4ubuntu1" + "gnome-sharp2-examples": "2.24.2-3" + "libfriends-gtk-dev": "0.1.2+14.04.20131108.1-0ubuntu1" + "fonts-tlwg-waree": "1:0.5.1-3" + "language-pack-hy-base": "1:14.04+20140410" + "python-cliff-doc": "1.4.5-1ubuntu2" + "python3-pyqt5": "5.2.1+dfsg-1ubuntu1" + "libpcap-dev": "1.5.3-2" + "libzeitgeist-2.0-doc": "0.9.14-0ubuntu4" + "libasan0": "4.8.2-19ubuntu1" + "mysql-client-core-5.5": "5.5.35+dfsg-1ubuntu1" + "python-sphinxbase": "0.8-0ubuntu10" + "language-pack-ta": "1:14.04+20140410" + "libgnuinet-java": "1.1.2-2build1" + "system-config-printer-gnome": "1.4.3+20140219-0ubuntu2" + "libespeak1": "1.47.11-1ubuntu1" + "initramfs-tools": "0.103ubuntu4" + "language-pack-cs": "1:14.04+20140410" + "language-pack-gnome-fy": "1:14.04+20140410" + "liblightdm-qt5-3-0": "1.10.0-0ubuntu3" + "libprotobuf-lite8": "2.5.0-9ubuntu1" + "openvswitch-pki": "2.0.1+git20140120-0ubuntu2" + "libecryptfs-dev": "104-0ubuntu1" + "wbritish-small": "7.1-1" + "firefox-locale-zh-hans": "28.0+build2-0ubuntu2" + "initramfs-tools-bin": "0.103ubuntu4" + "gettext-doc": "0.18.3.1-1ubuntu2" + "glibc-doc": "2.19-0ubuntu6" + "libmono-messaging4.0-cil": "3.2.8+dfsg-4ubuntu1" + "python-glance": "1:2014.1-0ubuntu1" + "python-pyparsing-doc": "2.0.1+dfsg1-1build1" + "python-pil": "2.3.0-1ubuntu3" + "qtdeclarative5-unity-action-plugin": "1.1.0+14.04.20140304-0ubuntu1" + "libclucene-dev": "2.3.3.4-4build1" + "libgles2-mesa-dev": "10.1.0-4ubuntu5" + "libqtwebkit4-dbg": "2.3.2-0ubuntu7" + "libuuid1": "2.20.1-5.1ubuntu20" + "open-vm-tools-dbg": "2:9.4.0-1280544-5ubuntu6" + "exim4-daemon-heavy": "4.82-3ubuntu2" + "firefox-locale-hu": "28.0+build2-0ubuntu2" + "libqimageblitz4": "1:0.0.6-4build1" + "lxc": "1.0.3-0ubuntu3" + "language-pack-uz-base": "1:14.04+20140410" + "libm17n-dev": "1.6.4-2ubuntu1" + "libsoup-gnome2.4-1": "2.44.2-1ubuntu2" + "libtxc-dxtn-s2tc-dev": "0~git20131104-1.1" + "dh-linktree": "0.4" + "keystone-doc": "1:2014.1-0ubuntu1" + "libappindicator0.1-cil": "12.10.1+13.10.20130920-0ubuntu4" + "libmono-system-enterpriseservices4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libaprutil1-dbd-sqlite3": "1.5.3-1" + "postgresql-contrib-9.3": "9.3.4-1" + "xserver-xorg-video-vesa": "1:2.3.3-1build1" + "libatk1.0-data": "2.10.0-2ubuntu2" + "dictd": "1.12.1+dfsg-2" + "libcogl-pango-dev": "1.16.2-1" + "libpython3-dbg": "3.4.0-0ubuntu2" + "mircommon-dev": "0.1.8+14.04.20140411-0ubuntu1" + "glib-networking": "2.40.0-1" + "libboost-test-dev": "1.54.0.1ubuntu1" + "liblua5.1-0-dbg": "5.1.5-5" + "libqtdeclarative4-perl": "4:4.13.0-0ubuntu1" + "libgnomecanvas2-doc": "2.30.3-2" + "oem-config-gtk": "2.18.7" + "libkmediaplayer4": "4:4.13.0-0ubuntu1" + "libyaml-0-2": "0.1.4-3ubuntu3" + "nginx-core": "1.4.6-1ubuntu3" + "simple-scan": "3.12.0-0ubuntu1" + "srvadmin-base": "7.1.0-3" + "evolution-data-server-common": "3.10.4-0ubuntu1" + "python3-magic": "1:5.14-2ubuntu3" + "cyrus-sasl2-mit-dbg": "2.1.25.dfsg1-17build1" + "e2fslibs-dbg": "1.42.9-3ubuntu1" + "network-manager-pptp": "0.9.8.2-1ubuntu2" + "cgroup-lite": "1.9" + "gsettings-desktop-schemas": "3.10.1-0ubuntu1" + "mono-runtime-boehm": "3.2.8+dfsg-4ubuntu1" + "python3-gdbm": "3.4.0-0ubuntu1" + "humanity-icon-theme": "0.6.5" + "neutron-lbaas-agent": "1:2014.1-0ubuntu1" + "ibus-doc": "1.5.5-1ubuntu3" + "libubuntu-platform-api1-dev": "0.20+14.04.20140411-0ubuntu1" + "libesmtp6": "1.0.6-1ubuntu2" + "nagios3": "3.5.1-1ubuntu1" + "lilo-doc": "1:24.0-2" + "click-apparmor": "0.2" + "liblxc1": "1.0.3-0ubuntu3" + "python-markupsafe-dbg": "0.18-1build2" + "language-pack-ky": "1:14.04+20140410" + "libxcb-xv0-dev": "1.10-2ubuntu1" + "language-pack-gnome-lv-base": "1:14.04+20140410" + "xserver-xorg-video-vmware-lts-raring": "3:5" + "gtk2.0-examples": "2.24.23-0ubuntu1" + "libframe6": "2.5.0daily13.06.05-0ubuntu1" + "libxcb-xinerama0-dev": "1.10-2ubuntu1" + "friends-facebook": "0.2.0+14.04.20140217.1-0ubuntu1" + "libgnomeui-doc": "2.24.5-3" + "libreoffice-l10n-nr": "1:4.2.3~rc3-0ubuntu1" + "tomcat7-common": "7.0.52-1" + "ant-gcj": "1.9.3-2build1" + "libmodule-build-tiny-perl": "0.034-1" + "libapache2-mod-macro": "1:2.4.7-1ubuntu4" + "libpyzy-dev": "1.0.1-4" + "modemmanager-dev": "1.0.0-2ubuntu1" + "libreoffice-l10n-ja": "1:4.2.3~rc3-0ubuntu1" + "libyaml-tiny-perl": "1.56-1" + "python-mocker": "1.0-2" + "systemtap-doc": "2.3-1ubuntu1" + "hunspell-ro": "1:4.2.1-0ubuntu1" + "libsub-install-perl": "0.927-1" + "python3-waitress": "0.8.8-1ubuntu3" + "libgtop2-dev": "2.28.5-2" + "libhybris-dev": "0.1.0+git20131207+e452e83-0ubuntu12" + "python-examples": "2.7.5-5ubuntu3" + "inputattach": "1:1.4.7-1" + "libparams-util-perl": "1.07-1build1" + "protobuf-compiler": "2.5.0-9ubuntu1" + "xserver-xorg-input-evdev-lts-saucy": "3:5" + "exim4-config": "4.82-3ubuntu2" + "libgcc-4.8-dev-ppc64el-cross": "4.8.2-16ubuntu4cross0.4" + "ruby-introspection": "0.0.2-2" + "gfxboot-theme-ubuntu": "0.16.1" + "nautilus-sendto-empathy": "3.8.6-0ubuntu9" + "language-pack-gnome-ks": "1:14.04+20140410" + "libss2-dbg": "1.42.9-3ubuntu1" + "python-newt": "0.52.15-2ubuntu5" + "libalgorithm-diff-perl": "1.19.02-3" + "libmono-cairo4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libcfg6": "2.3.3-1ubuntu1" + "libdebian-installer4": "0.88ubuntu4" + "pulseaudio-utils-dbg": "1:4.0-0ubuntu11" + "libindicator-dev": "12.10.2+14.04.20140402-0ubuntu1" + "libpengine4-dev": "1.1.10+git20130802-1ubuntu2" + "libxmu-dev": "2:1.1.1-1" + "qtx11extras5-dbg": "5.2.1-1" + "valac-0.22-vapi": "0.22.1-0ubuntu1" + "libcap-dev": "1:2.24-0ubuntu2" + "libosp5": "1.5.2-10ubuntu3" + "python3-msgpack": "0.3.0-1ubuntu3" + "libtest-subcalls-perl": "1.09-2" + "python3-json-pointer": "1.0-2build1" + "qtscript5-doc-html": "5.2.1+dfsg-1ubuntu1" + "emacs24": "24.3+1-2ubuntu1" + "python3-dbg": "3.4.0-0ubuntu2" + "libbusiness-isbn-perl": "2.07-1" + "myspell-en-gb": "1:4.2.1-0ubuntu1" + "qtsensors5-doc": "5.2.1+dfsg-2ubuntu2" + "libkrb5-dbg": "1.12+dfsg-2ubuntu4" + "liblinear-dbg": "1.8+dfsg-1ubuntu1" + "python-gnomekeyring": "2.32.0+dfsg-3" + "libjs-jquery-hotkeys": "0~20130707+git2d51e3a9+dfsg-2ubuntu1" + "libmono-system-ldap2.0-cil": "3.2.8+dfsg-4ubuntu1" + "fdupes": "1.51-1" + "gir1.2-wnck-3.0": "3.4.7-0ubuntu3" + "libplatform-hardware-api1-dev": "0.20+14.04.20140411-0ubuntu1" + "fonts-nanum": "20131007-1" + "libblas3": "1.2.20110419-7" + "libgoa-1.0-0b": "3.10.3-0ubuntu1" + "libstdc++6-4.7-doc": "4.7.3-12ubuntu1" + "bind9utils": "1:9.9.5.dfsg-3" + "libcryptsetup4": "2:1.6.1-1ubuntu1" + "libupstart-dev": "1.12.1-0ubuntu4" + "libmono-oracle2.0-cil": "3.2.8+dfsg-4ubuntu1" + "libisccfg90": "1:9.9.5.dfsg-3" + "liborcus-0.6-0": "0.5.1-7" + "libreoffice-dbg": "1:4.2.3~rc3-0ubuntu2" + "xserver-xorg-video-sis-lts-quantal": "3:5" + "language-pack-zh-hans-base": "1:14.04+20140410" + "phonon4qt5-backend-null": "4:4.7.1-0ubuntu8" + "libmono-system-servicemodel-activation4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libesmtp-dev": "1.0.6-1ubuntu2" + "libftdi-dev": "0.20-1ubuntu1" + "librbd1": "0.80.1-0ubuntu1.1" + "nasm": "2.10.09-1" + "language-pack-dv": "1:14.04+20140410" + "language-pack-it-base": "1:14.04+20140410" + "libhtml-form-perl": "6.03-1" + "libintl-perl": "1.23-1build1" + "gir1.2-lightdm-1": "1.10.0-0ubuntu3" + "libdata-section-perl": "0.200005-1" + "python3-logilab-common": "0.61.0-1" + "mount": "2.20.1-5.1ubuntu20" + "rbd-fuse-dbg": "0.79-0ubuntu1" + "libstdc++6-4.7-dbg": "4.7.3-12ubuntu1" + "xserver-xorg-video-fbdev-lts-saucy": "3:5" + "hunspell-fr-classical": "1:5.0.2-1" + "myspell-sk": "0.5.5a-2.3fakesync1" + "libgraphviz-dev": "2.36.0-0ubuntu3" + "libgssdp-1.0-dbg": "0.14.7-1ubuntu1" + "libnet1": "1.1.6+dfsg-2ubuntu1" + "libcholmod2.1.2": "1:4.2.1-3ubuntu1" + "libgupnp-igd-1.0-4": "0.2.2-1" + "voikko-fi": "1.15-1" + "libmono-corlib4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libmono-peapi2.0a-cil": "3.2.8+dfsg-4ubuntu1" + "libkprintutils4": "4:4.13.0-0ubuntu1" + "libdrm-intel1-dbg": "2.4.52-1" + "strigi-dbg": "0.7.8-1ubuntu2" + "ubuntu-minimal": "1.325" + "perl-doc": "5.18.2-2ubuntu1" + "python-babel-doc": "1.3+dfsg.1-2ubuntu1" + "libasyncns0": "0.8-4ubuntu2" + "libpoppler-qt4-4": "0.24.5-2ubuntu4" + "libslang2-dev": "2.2.4-15ubuntu1" + "language-pack-fi": "1:14.04+20140410" + "libmono-microsoft-build-engine4.0-cil": "3.2.8+dfsg-4ubuntu1" + "xchat-gnome": "1:0.30.0~git20131003.d20b8d+really20110821-0.2ubuntu12" + "language-pack-gnome-ro": "1:14.04+20140410" + "ledit": "2.03-2build1" + "python-mock-doc": "1.0.1-3" + "gstreamer0.10-plugins-good-dbg": "0.10.31-3+nmu1ubuntu5" + "libgweather-3-dev": "3.10.2-0ubuntu1" + "hyphen-ro": "1:4.2.1-0ubuntu1" + "language-pack-gnome-th": "1:14.04+20140410" + "libjs-yui3-debug": "3.5.1-1ubuntu3" + "libmono-security2.0-cil": "3.2.8+dfsg-4ubuntu1" + "firefox-locale-pl": "28.0+build2-0ubuntu2" + "libgusb2": "0.1.6-5" + "python-simplegeneric": "0.8.1-1" + "linux-signed-image-generic-lts-quantal": "3.13.0.24.28" + "xserver-xorg-video-openchrome-dbg": "1:0.3.3-1build1" + "myspell-et": "1:20030606-20" + "libharfbuzz-gobject0": "0.9.27-1" + "python-gdbm-dbg": "2.7.5-1ubuntu1" + "qemu-system-common": "2.0.0~rc1+dfsg-0ubuntu3" + "xserver-xorg-lts-quantal": "3:5" + "bzr": "2.6.0+bzr6593-1ubuntu1" + "libpaper-dev": "1.1.24+nmu2ubuntu3" + "libplist1": "1.10-1" + "libtheora0": "1.1.1+dfsg.1-3.2" + "language-pack-as": "1:14.04+20140410" + "libgoa-1.0-doc": "3.10.3-0ubuntu1" + "libxpp2-java": "2.1.10-7build1" + "libncurses5-dev": "5.9+20140118-1ubuntu1" + "libopenobex1-dev": "1.5-2.1" + "python-tickcount": "0.1-0ubuntu17" + "language-pack-ht": "1:14.04+20140410" + "ruby-setup": "3.4.1-7" + "sphinx-voxforge-hmm-en": "0.1.1~daily20130301-0ubuntu1" + "libexif-dev": "0.6.21-1ubuntu1" + "libgs-dev": "9.10~dfsg-0ubuntu10" + "libusb-1.0-0-dbg": "2:1.0.17-1ubuntu2" + "libgnomevfs2-dev": "1:2.24.4-1ubuntu6" + "libumfpack5.6.2": "1:4.2.1-3ubuntu1" + "libcommons-io-java-doc": "2.4-2" + "libmono-microsoft-build-utilities-v4.0-4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libxcb1": "1.10-2ubuntu1" + "language-pack-gnome-st": "1:14.04+20140410" + "llvm-3.4-doc": "1:3.4-1ubuntu3" + "libgail18": "2.24.23-0ubuntu1" + "symlinks": "1.4-1ubuntu1" + "logtail": "1.3.16" + "guile-2.0-dev": "2.0.9+1-1ubuntu1" + "liblzma-dev": "5.1.1alpha+20120614-2ubuntu2" + "xserver-xorg-video-nouveau-lts-quantal-dbg": "3:5" + "junit4-doc": "4.11-2" + "libpam-gnome-keyring": "3.10.1-1ubuntu4" + "libx32atomic1": "4.8.2-19ubuntu1" + "mutt-dbg": "1.5.21-6.4ubuntu2" + "vim": "2:7.4.052-1ubuntu3" + "libreoffice-l10n-eu": "1:4.2.3~rc3-0ubuntu1" + "linux-libc-dev-armhf-cross": "3.13.0-12.32cross1.104" + "x11proto-xinerama-dev": "1.2.1-2" + "libecal1.2-dev": "3.10.4-0ubuntu1" + "libkdnssd4": "4:4.13.0-0ubuntu1" + "language-pack-gnome-km": "1:14.04+20140410" + "libzip-dev": "0.10.1-1.2" + "python-coverage": "3.7.1+dfsg.1-1ubuntu2" + "libmalaga-dev": "7.12-4.1ubuntu1" + "libsystemd-daemon0": "204-5ubuntu20" + "oxideqt-codecs": "1.0.0~bzr501-0ubuntu1" + "python-oops-twisted": "0.0.6-0ubuntu4" + "gir1.2-gst-plugins-base-1.0": "1.2.3-1" + "libcmis-0.4-4": "0.4.1-3ubuntu4" + "libgomp1": "4.8.2-19ubuntu1" + "libgssglue-dev": "0.4-2ubuntu1" + "doxygen": "1.8.6-2" + "libgles1-mesa-lts-saucy-dbg": "3:5" + "ubuntu-standard": "1.325" + "myspell-th": "1:4.2.1-0ubuntu1" + "libpulse-mainloop-glib0": "1:4.0-0ubuntu11" + "libx11-6": "2:1.6.2-1ubuntu2" + "linux-image-extra-virtual": "3.13.0.24.28" + "network-manager": "0.9.8.8-0ubuntu7" + "libharfbuzz-dev": "0.9.27-1" + "libmessaging-menu-dev": "13.10.1+14.04.20140410-0ubuntu1" + "libxi6": "2:1.7.1.901-1ubuntu1" + "libapache2-mod-perl2-dev": "2.0.8+httpd24-r1449661-6ubuntu2" + "dovecot-sieve": "1:2.2.9-1ubuntu2" + "libc6-dev-x32": "2.19-0ubuntu6" + "libcdio-dev": "0.83-4.1ubuntu1" + "libgles2-mesa-dev-lts-raring": "3:5" + "qt3d5-private-dev": "5.0~git20130731-0ubuntu5" + "ibus-table-cangjie-big": "1.4.6-Source-1" + "g++-4.8-powerpc-linux-gnu": "4.8.2-16ubuntu3cross0.11" + "gir1.2-pango-1.0": "1.36.3-1ubuntu1" + "libcanberra-gtk-dev": "0.30-0ubuntu3" + "python3-netifaces-dbg": "0.8-3build1" + "cinder-volume": "1:2014.1-0ubuntu1" + "language-pack-nb": "1:14.04+20140410" + "libgtkhtml-4.0-dev": "4.6.6-2ubuntu1" + "xserver-xorg-video-ati-lts-quantal-dbg": "3:5" + "language-pack-gnome-an-base": "1:14.04+20140410" + "ruby2.0-doc": "2.0.0.484-1ubuntu2" + "wbritish-insane": "7.1-1" + "python-sss": "1.11.5-1ubuntu3" + "hunspell-kk": "1.1-2" + "ibus-table-cangjie": "1.4.6-Source-1" + "liburi-perl": "1.60-1" + "libdmraid-dev": "1.0.0.rc16-4.2ubuntu3" + "python-qt4-phonon": "4.10.4+dfsg-1ubuntu1" + "libaa1": "1.4p5-41" + "libapache2-reload-perl": "0.12-2" + "libmdds-dev": "0.10.2-1" + "python-dateutil": "1.5+dfsg-1ubuntu1" + "ceilometer-common": "2014.1-0ubuntu1" + "aptitude-dbg": "0.6.8.2-1ubuntu4" + "xserver-xorg-video-s3-lts-raring": "3:5" + "ubuntu-drivers-common": "1:0.2.91.4" + "xserver-xorg-input-all": "1:7.7+1ubuntu8" + "xserver-xorg-video-mga-lts-raring": "3:5" + "bacula-client": "5.2.6+dfsg-9.1ubuntu3" + "libreoffice-l10n-es": "1:4.2.3~rc3-0ubuntu1" + "libelfg0-dev": "0.8.13-5" + "libgbm-dev-lts-quantal": "3:5" + "libtommath0": "0.42.0-1build1" + "fonts-ubuntu-font-family-console": "0.80-0ubuntu6" + "libgimp2.0-doc": "2.8.10-0ubuntu1" + "qttools5-private-dev": "5.2.1-8build1" + "bf-utf-source": "0.07" + "xserver-xorg-input-evdev-dev": "1:2.8.2-1ubuntu2" + "telepathy-logger": "0.8.0-3" + "ubuntu-wallpapers": "14.04.0.1-0ubuntu1" + "libgnomevfs2-0-dbg": "1:2.24.4-1ubuntu6" + "libgutenprintui2-dev": "5.2.10~pre2-0ubuntu2" + "libxmltok1-dev": "1.2-3build3" + "tasksel": "2.88ubuntu15" + "appmenu-qt5": "0.3.0+14.04.20140415-0ubuntu1" + "xserver-xorg-input-all-lts-quantal": "3:5" + "libmirclientplatform-mesa": "0.1.8+14.04.20140411-0ubuntu1" + "librhino-java": "1.7R4-2" + "libxz-java-doc": "1.4-1" + "postgresql-doc": "9.3+154" + "wspanish": "1.0.26" + "libjson0": "0.11-3ubuntu1.2" + "dh-buildinfo": "0.10ubuntu1" + "ocaml": "4.01.0-3ubuntu3" + "ocaml-interp": "4.01.0-3ubuntu3" + "libxml-commons-resolver1.1-java": "1.2-7build1" + "libgmime-2.6-dev": "2.6.20-0ubuntu1" + "libnl-genl-3-200": "3.2.21-1" + "libqt4-svg": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "language-pack-gnome-km-base": "1:14.04+20140410" + "ruby-all-dev": "1:1.9.3.4" + "xkb-data-i18n": "2.10.1-1ubuntu1" + "gzip": "1.6-3ubuntu1" + "libapache2-mod-perl2": "2.0.8+httpd24-r1449661-6ubuntu2" + "libck-connector0": "0.4.5-3.1ubuntu2" + "percona-xtrabackup": "2.1.8-1" + "libdee-doc": "1.2.7+14.04.20140324-0ubuntu1" + "libice-doc": "2:1.0.8-2" + "oem-config-slideshow-ubuntu": "83" + "xdg-utils": "1.1.0~rc1-2ubuntu7" + "libc6-x32": "2.19-0ubuntu6" + "python-zope.interface": "4.0.5-1ubuntu4" + "autoconf2.64": "2.64-3" + "language-pack-st": "1:14.04+20140410" + "libhttp-daemon-perl": "6.01-1" + "libboost-thread1.54.0": "1.54.0-4ubuntu3" + "liblocale-gettext-perl": "1.05-7build3" + "hunspell-tools": "1.3.2-6ubuntu2" + "libnss3-dev": "2:3.15.4-1ubuntu7" + "installation-guide-amd64": "20100518ubuntu10" + "libx32readline6-dev": "6.3-4ubuntu2" + "libboost-date-time1.54-dev": "1.54.0-4ubuntu3" + "language-pack-eu-base": "1:14.04+20140410" + "language-pack-zh-hant": "1:14.04+20140410" + "libgeis-doc": "2.2.16+14.04.20140303-0ubuntu1" + "ecryptfs-utils": "104-0ubuntu1" + "gfortran-4.8-multilib": "4.8.2-19ubuntu1" + "python3-apparmor-click": "0.2" + "libtasn1-bin": "3.4-3" + "xserver-xorg-video-r128-lts-saucy-dbg": "3:5" + "qemu-utils": "2.0.0+dfsg-2ubuntu1.1" + "libtext-glob-perl": "0.09-1" + "libpyzy-1.0-0": "1.0.1-4" + "libxau-dev": "1:1.0.8-1" + "php5-gmp": "5.5.9+dfsg-1ubuntu4" + "postfix-ldap": "2.11.0-1" + "python-troveclient": "1:1.0.3-0ubuntu3" + "libgeoclue-dev": "0.12.99-3ubuntu1" + "libstatgrab-dev": "0.90-1.1ubuntu1" + "libtevent-dev": "0.9.19-1" + "tmux": "1.8-5" + "xserver-xorg-input-wacom": "1:0.23.0-0ubuntu2" + "libreoffice-l10n-th": "1:4.2.3~rc3-0ubuntu1" + "libgck-1-0": "3.10.1-1" + "libxkbcommon0": "0.4.1-0ubuntu1" + "phonon-backend-null": "4:4.7.1-0ubuntu8" + "qpdf": "5.1.1-1" + "libxom-java-doc": "1.2.10-1" + "librados2": "0.80.1-0ubuntu1.1" + "libyajl2-dbg": "2.0.4-4" + "libdebian-installer-extra4": "0.88ubuntu4" + "libsane-dbg": "1.0.23-3ubuntu3" + "dh-autoreconf": "9" + "grub-legacy-ec2": "0.7.5-0ubuntu1" + "language-pack-ku-base": "1:14.04+20140410" + "libreoffice-nlpsolver": "0.9~beta1-9ubuntu1" + "debianutils": "4.4" + "libqt5help5": "5.2.1-8build1" + "ssh-askpass-gnome": "1:6.6p1-2ubuntu1" + "cups-driver-gutenprint": "5.2.10~pre2-0ubuntu2" + "python-pexpect": "3.1-1" + "gcc-4.8-powerpc64le-linux-gnu": "4.8.2-16ubuntu4cross0.4" + "gir1.2-colord-1.0": "1.0.6-1" + "libbrlapi-dev": "5.0-2ubuntu2" + "libhud2-doc": "13.10.1+14.04.20140402-0ubuntu1" + "mono-dmcs": "3.2.8+dfsg-4ubuntu1" + "coreutils": "8.21-1ubuntu5" + "erlang-corba": "1:16.b.3-dfsg-1ubuntu2" + "libreadline5-dbg": "5.2+dfsg-2" + "libreoffice-help-vi": "1:4.2.3~rc3-0ubuntu1" + "python-django-piston": "0.2.3-1ubuntu5" + "ceph-dbg": "0.79-0ubuntu1" + "libgssapi-perl": "0.28-2build1" + "libqjson-dev": "0.8.1-3" + "language-pack-gnome-om": "1:14.04+20140410" + "evolution-indicator": "0.2.20-0ubuntu15" + "libxinerama-dev": "2:1.1.3-1" + "gtk-sharp2-examples": "2.12.10-5" + "libpam-radius-auth": "1.3.17-0ubuntu4" + "xserver-xorg-core-lts-quantal": "3:5" + "gnome-mime-data": "2.18.0-1" + "language-pack-sw": "1:14.04+20140410" + "firefox-locale-an": "28.0+build2-0ubuntu2" + "gutenprint-locales": "5.2.10~pre2-0ubuntu2" + "language-pack-gnome-fa": "1:14.04+20140410" + "language-pack-gnome-tg": "1:14.04+20140410" + "myspell-en-au": "2.1-5.4" + "apturl": "0.5.2ubuntu4" + "libavahi-ui-dev": "0.6.31-4ubuntu1" + "liblcms2-dev": "2.5-0ubuntu4" + "language-pack-hu-base": "1:14.04+20140410" + "libjs-yui3-doc": "3.5.1-1ubuntu3" + "rhythmbox-plugin-magnatune": "3.0.2-0ubuntu1" + "librdmacm1-dbg": "1.0.16-1" + "elasticsearch": "1.2.3" + "language-pack-nan-base": "1:14.04+20140410" + "libmono-system-web4.0-cil": "3.2.8+dfsg-4ubuntu1" + "thunderbird-locale-es-es": "1:24.4.0+build1-0ubuntu1" + "wogerman": "1:2-28" + "gimp-help-common": "2.6.1-1" + "krb5-doc": "1.12+dfsg-2ubuntu4" + "language-pack-gnome-hu": "1:14.04+20140410" + "libgexiv2-dev": "0.10.0-1ubuntu1" + "python-cddb": "1.4-5.1ubuntu2" + "libvpx-doc": "1.3.0-2" + "unity-scope-texdoc": "0.1+14.04.20140328-0ubuntu1" + "libbsd0": "0.6.0-2ubuntu1" + "qtmultimedia5-dev": "5.2.1-0ubuntu5" + "libexpat1": "2.1.0-4ubuntu1" + "libosp-dev": "1.5.2-10ubuntu3" + "netcat-openbsd": "1.105-7ubuntu1" + "libltdl-dev": "2.4.2-1.7ubuntu1" + "nih-dbus-tool": "1.0.3-4ubuntu25" + "libfile-sharedir-perl": "1.03-1" + "thunderbird-locale-ga-ie": "1:24.4.0+build1-0ubuntu1" + "wamerican": "7.1-1" + "aide": "0.16~a2.git20130520-2" + "libdb5.3++": "5.3.28-3ubuntu3" + "transfig": "1:3.2.5.e-1ubuntu1" + "fonts-takao-mincho": "003.02.01-9ubuntu2" + "language-pack-gnome-id": "1:14.04+20140410" + "gir1.2-friends-gtk-0.1": "0.1.2+14.04.20131108.1-0ubuntu1" + "multipath-tools-dbg": "0.4.9-3ubuntu7" + "printer-driver-pnm2ppa": "1.13+nondbs-0ubuntu4" + "junit": "3.8.2-8build1" + "python-sqlalchemy-doc": "0.8.4-1build1" + "gir1.2-dee-1.0": "1.2.7+14.04.20140324-0ubuntu1" + "xserver-xorg-dev-lts-raring": "3:5" + "libcorosync-common4": "2.3.3-1ubuntu1" + "hicolor-icon-theme": "0.13-1" + "language-pack-az": "1:14.04+20140410" + "language-pack-gnome-as-base": "1:14.04+20140410" + "python-babel": "1.3+dfsg.1-2ubuntu1" + "firefox-locale-zu": "28.0+build2-0ubuntu2" + "bash-doc": "4.3-6ubuntu1" + "language-pack-gnome-ga-base": "1:14.04+20140410" + "libibus-1.0-5": "1.5.5-1ubuntu3" + "libsmbsharemodes0": "2:4.1.6+dfsg-1ubuntu2" + "python3-icu-dbg": "1.5-2ubuntu4" + "augeas-lenses": "1.2.0-0ubuntu1" + "libgtksourceview-3.0-doc": "3.10.2-0ubuntu1" + "libdconf-dbus-1-0": "0.20.0-1" + "librrds-perl": "1.4.7-2ubuntu5" + "libwebkitgtk-common-dev": "2.4.0-1ubuntu2" + "shared-desktop-ontologies": "0.11.0-1" + "librest-0.7-0-dbg": "0.7.90-0ubuntu1" + "shotwell": "0.18.0-0ubuntu4" + "libmono-system-web-extensions-design4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libsignon-plugins-doc": "8.56+14.04.20140307-0ubuntu2" + "libtext-diff-perl": "1.41-1" + "gcc-4.8-aarch64-linux-gnu": "4.8.2-13ubuntu1cross0.11" + "python3-pyxattr": "0.5.1-1.1build4" + "libmail-sendmail-perl": "0.79.16-1" + "pulseaudio-utils": "1:4.0-0ubuntu11" + "mono-xbuild": "3.2.8+dfsg-4ubuntu1" + "keyutils": "1.5.6-1" + "libspqr1.3.1": "1:4.2.1-3ubuntu1" + "libxmu6": "2:1.1.1-1" + "signon-plugin-oauth2": "0.19+14.04.20140305-0ubuntu2" + "oxideqt-codecs-extra-dbg": "1.0.0~bzr501-0ubuntu1" + "libmx-doc": "1.4.7-0ubuntu3" + "nut": "2.7.1-1ubuntu1" + "python3-pyudev": "0.16.1-2build1" + "wnorwegian": "2.0.10-5.1" + "linux-signed-generic-lts-quantal-eol-upgrade": "3.13.0.24.28" + "libdevel-partialdump-perl": "0.17-1" + "libdrm-intel1": "2.4.52-1" + "language-pack-gnome-en-base": "1:14.04+20140707" + "libvorbisfile3": "1.3.2-1.3ubuntu1" + "language-pack-fi-base": "1:14.04+20140410" + "language-pack-gnome-xh": "1:14.04+20140410" + "libglm-doc": "0.9.5.1-1" + "archdetect-deb": "1.95ubuntu2" + "dpkg-repack": "1.37" + "texlive-publishers-doc": "2013.20140215-2" + "libpython-stdlib": "2.7.5-5ubuntu3" + "esound-common": "0.2.41-11" + "munin-node": "2.0.19-3" + "libcroco3": "0.6.8-2ubuntu1" + "open-vm-tools-dev": "2:9.4.0-1280544-5ubuntu6" + "libnotify4": "0.7.6-1ubuntu3" + "libvirt0-dbg": "1.2.2-0ubuntu13" + "libx32quadmath0-dbg": "4.8.2-19ubuntu1" + "gir1.2-gtk-2.0": "2.24.23-0ubuntu1" + "libsmokeqtgui4-3": "4:4.13.0-0ubuntu1" + "linux-generic-lts-quantal-eol-upgrade": "3.13.0.24.28" + "python-egenix-mxproxy": "3.2.7-1build1" + "gimp-help-de": "2.6.1-1" + "bc": "1.06.95-8ubuntu1" + "pptp-linux": "1.7.2-7" + "python-svn-dbg": "1.7.8-0.2" + "systemd-services": "204-5ubuntu20.3" + "friends-dispatcher": "0.2.0+14.04.20140217.1-0ubuntu1" + "libdevel-cover-perl": "1.08-1ubuntu2" + "libnice-dbg": "0.1.4-1" + "language-pack-gnome-sq": "1:14.04+20140410" + "ruby-minitest": "5.2.1-1" + "libmysqlclient18": "5.5.38+maria-1~trusty" + "language-pack-gv": "1:14.04+20140410" + "libmono-messaging2.0-cil": "3.2.8+dfsg-4ubuntu1" + "ntp-doc": "1:4.2.6.p5+dfsg-3ubuntu2" + "python3-junitxml": "0.6-1.1build1" + "rhythmbox": "3.0.2-0ubuntu1" + "zsh-dbg": "5.0.2-3ubuntu6" + "python-genshi-doc": "0.7-3" + "python-nine": "0.3.3-2" + "qtdeclarative5-doc": "5.2.1-8build1" + "libjpeg62-dbg": "6b1-4ubuntu1" + "libstonith1": "1.0.11+hg2754-1.1build1" + "libpe-rules2-dev": "1.1.10+git20130802-1ubuntu2" + "libwebp-dev": "0.4.0-4" + "libmono-system-data-services4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libsecret-common": "0.16-0ubuntu1" + "ghostscript": "9.10~dfsg-0ubuntu10" + "libecpg6": "9.3.4-1" + "libipmidetect-dev": "1.1.5-3ubuntu3" + "language-pack-gnome-bho": "1:14.04+20140410" + "language-pack-th": "1:14.04+20140410" + "libqmi-glib-dev": "1.4.0-1" + "psutils": "1.17.dfsg-1" + "libxkbfile-dev": "1:1.0.8-1" + "language-pack-my": "1:14.04+20140410" + "libtest-cpan-meta-perl": "0.23-1" + "gfortran": "4:4.8.2-1ubuntu6" + "libgtk-vnc-1.0-0": "0.5.3-0ubuntu2" + "libmx-bin": "1.4.7-0ubuntu3" + "gcj-4.8-jre-lib": "4.8.2-19ubuntu1" + "mythes-cs": "1:4.2.1-0ubuntu1" + "libnss3-1d": "2:3.15.4-1ubuntu7" + "libqt5xmlpatterns5-dev": "5.2.1-3" + "language-pack-st-base": "1:14.04+20140410" + "python-json-pointer": "1.0-2build1" + "ttf-oriya-fonts": "1:0.5.14ubuntu1" + "libaccounts-glib-dev": "1.15+14.04.20131126.2-0ubuntu3" + "libevent-dbg": "2.0.21-stable-1ubuntu1" + "icc-profiles-free": "2.0.1+dfsg-1" + "gir1.2-rb-3.0": "3.0.2-0ubuntu1" + "libtest-taint-perl": "1.06-1" + "libyelp0": "3.10.2-0ubuntu1" + "python-zope.interface-dbg": "4.0.5-1ubuntu4" + "libtheora-dev": "1.1.1+dfsg.1-3.2" + "xserver-xorg-video-ati": "1:7.3.0-1ubuntu3" + "libstdc++-4.8-dev-ppc64el-cross": "4.8.2-16ubuntu4cross0.4" + "gstreamer0.10-nice": "0.1.4-1" + "libboost-iostreams-dev": "1.54.0.1ubuntu1" + "libcurl3": "7.35.0-1ubuntu2" + "libpam-systemd": "204-5ubuntu20.3" + "libcdr-0.0-0": "0.0.15-1ubuntu1" + "libconfig8-dev": "1.4.9-2" + "libisccc90": "1:9.9.5.dfsg-3" + "linux-headers-generic-lts-quantal": "3.13.0.24.28" + "python-talloc-dev": "2.1.0-1" + "python-django-nose": "1.2-1" + "libasyncns-dev": "0.8-4ubuntu2" + "libxcb-composite0-dbg": "1.10-2ubuntu1" + "xserver-xorg-video-neomagic": "1:1.2.8-1build1" + "language-pack-gnome-ku-base": "1:14.04+20140410" + "libmono-system-web-http-selfhost4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libwayland-server0-dbg": "1.4.0-1ubuntu1" + "syslinux-themes-ubuntu-saucy": "8" + "eog-dev": "3.10.2-0ubuntu5" + "libgweather-common": "3.10.2-0ubuntu1" + "libpam-runtime": "1.1.8-1ubuntu2" + "lupin-casper": "0.55" + "python3-debian": "0.1.21+nmu2ubuntu2" + "libspeex-dbg": "1.2~rc1.1-1ubuntu1" + "ipxe-qemu": "1.0.0+git-20131111.c3d1e78-2ubuntu1" + "myspell-zu": "20070207-5ubuntu1" + "python3.4-doc": "3.4.0-2ubuntu1" + "libfaketime": "0.9.5-2" + "librsvg2-common": "2.40.2-1" + "language-pack-nn-base": "1:14.04+20140410" + "bacula-console-qt-dbg": "5.2.6+dfsg-9.1ubuntu3" + "hplip": "3.14.3-0ubuntu3" + "libjaxp1.3-java-gcj": "1.3.05-2ubuntu3" + "fop-doc": "1:1.1.dfsg-2ubuntu1" + "libreoffice-help-km": "1:4.2.3~rc3-0ubuntu1" + "liblrm2-dev": "1.0.11+hg2754-1.1build1" + "python3-bson": "2.6.3-1build1" + "android-headers": "4.2.2-2-0ubuntu1" + "sysv-rc": "2.88dsf-41ubuntu6" + "libgl1-mesa-glx": "10.1.0-4ubuntu5" + "libkdecore5": "4:4.13.0-0ubuntu1" + "xserver-xorg-video-r128": "6.9.2-1build1" + "language-pack-gnome-it-base": "1:14.04+20140410" + "libjaxen-java": "1.1.6-1ubuntu1" + "libopenvg1-mesa-lts-saucy": "3:5" + "python-cheetah": "2.4.4-3.fakesyncbuild1" + "xserver-xorg-video-r128-lts-quantal": "3:5" + "language-pack-gnome-ru": "1:14.04+20140410" + "john": "1.8.0-1" + "lib32go4": "4.8.2-19ubuntu1" + "libcmap4": "2.3.3-1ubuntu1" + "libstonithd2-dev": "1.1.10+git20130802-1ubuntu2" + "hwdata": "0.249-1" + "language-pack-ur": "1:14.04+20140410" + "gnome-keyring": "3.10.1-1ubuntu4" + "libcommon-sense-perl": "3.72-2build1" + "libtag1c2a": "1.9.1-2" + "mklibs": "0.1.39" + "libraw1394-dev": "2.1.0-1ubuntu1" + "libreadline-dev": "6.3-4ubuntu2" + "python-ogg-dbg": "1.3+repack-5ubuntu2" + "language-pack-gnome-nan": "1:14.04+20140410" + "libmx-1.0-2-dbg": "1.4.7-0ubuntu3" + "pacemaker-dbg": "1.1.10+git20130802-1ubuntu2" + "ncurses-examples": "5.9+20140118-1ubuntu1" + "automake1.11": "1:1.11.6-2" + "language-pack-gnome-sl": "1:14.04+20140410" + "grub-efi-amd64-bin": "2.02~beta2-9" + "libsombok-dev": "2.3.1-2" + "linux-generic-lts-saucy-eol-upgrade": "3.13.0.24.28" + "cmake-doc": "2.8.12.2-0ubuntu3" + "language-pack-gnome-am-base": "1:14.04+20140410" + "gir1.2-webkit-1.0": "2.4.0-1ubuntu2" + "liblockfile1": "1.09-6ubuntu1" + "libxcb1-dbg": "1.10-2ubuntu1" + "emacs": "45.0ubuntu1" + "libreoffice-help-en-us": "1:4.2.3~rc3-0ubuntu1" + "policykit-desktop-privileges": "0.17" + "libhud2": "13.10.1+14.04.20140402-0ubuntu1" + "librasqal3-dbg": "0.9.32-1" + "transmission-daemon": "2.82-1.1ubuntu3" + "libblas-dev": "1.2.20110419-7" + "python-subversion": "1.8.8-1ubuntu3" + "python-pexpect-doc": "3.1-1" + "unity-scope-audacious": "0.1+13.10.20130927.1-0ubuntu1" + "zsh-beta-doc": "5.0.2-3ubuntu6" + "evolution-data-server-dbg": "3.10.4-0ubuntu1" + "isc-dhcp-server-dbg": "4.2.4-7ubuntu12" + "librecode0": "3.6-21" + "linux-signed-image-generic": "3.13.0.24.28" + "app-install-data": "14.04.0" + "language-pack-gnome-hy-base": "1:14.04+20140410" + "virtinst": "0.600.4-3ubuntu2" + "libdbus-c++-dev": "0.9.0-6ubuntu1" + "libkmod-dev": "15-0ubuntu6" + "librtmp-dev": "2.4+20121230.gitdf6c518-1" + "python-pygresql-dbg": "1:4.0-3build3" + "libgcj-common": "1:4.8.2-1ubuntu6" + "python-mock": "1.0.1-3" + "tasksel-data": "2.88ubuntu15" + "lib32stdc++6-4.7-dbg": "4.7.3-12ubuntu1" + "libqt4-test": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "human-theme": "0.39.2" + "language-pack-hsb": "1:12.04+20120417" + "fakeroot": "1.20-3ubuntu2" + "libcanberra0": "0.30-0ubuntu3" + "libgdk-pixbuf2.0-0": "2.30.7-0ubuntu1" + "libmono-npgsql2.0-cil": "3.2.8+dfsg-4ubuntu1" + "myspell-it": "1:4.2.1-0ubuntu1" + "ubuntuone-dev-tools": "13.10-0ubuntu2" + "bluez-dbg": "4.101-0ubuntu13" + "gir1.2-upowerglib-1.0": "0.9.23-2ubuntu1" + "unity-gtk3-module": "0.0.0+14.04.20140403-0ubuntu1" + "apport": "2.14.1-0ubuntu3" + "hyphen-sr": "1:4.2.1-0ubuntu1" + "ldap-auth-client": "0.5.3" + "libhttp-cookies-perl": "6.00-2" + "linux-tools-lts-saucy": "3.13.0.24.28" + "libcheese-doc": "3.10.2-0ubuntu2" + "srvadmin-racadm5": "7.1.0-2" + "language-pack-gnome-nso-base": "1:14.04+20140410" + "libmono-parallel4.0-cil": "3.2.8+dfsg-4ubuntu1" + "neutron-plugin-nicira": "1:2014.1-0ubuntu1" + "libdumbnet-dev": "1.12-4build1" + "libusb-dev": "2:0.1.12-23.3ubuntu1" + "qtdeclarative5-ubuntu-ui-toolkit-plugin": "0.1.46+14.04.20140408.1-0ubuntu1" + "dict-moby-thesaurus": "1.0-6.2" + "language-pack-om-base": "1:14.04+20140410" + "libcogl-common": "1.16.2-1" + "wbritish-huge": "7.1-1" + "libboost-atomic1.54.0": "1.54.0-4ubuntu3" + "libtotem-plparser-dbg": "3.10.2-0ubuntu1" + "mono-runtime-dbg": "3.2.8+dfsg-4ubuntu1" + "mutt": "1.5.21-6.4ubuntu2" + "srvadmin-rac4": "7.1.0-3" + "libtelepathy-logger-doc": "0.8.0-3" + "overlay-scrollbar": "0.2.16+r359+14.04.20131129-0ubuntu1" + "unity-scope-devhelp": "0.1+14.04.20140328-0ubuntu1" + "gstreamer0.10-plugins-base": "0.10.36-1.1ubuntu2" + "libicu52-dbg": "52.1-3" + "bluez-alsa": "4.101-0ubuntu13" + "libpgtypes3": "9.3.4-1" + "libselinux1": "2.2.2-1ubuntu0.1" + "gir1.2-nautilus-3.0": "1:3.10.1-0ubuntu8" + "x11-xfs-utils": "7.7+1" + "libreadonly-perl": "1.04-1" + "linux-libc-dev-ppc64el-cross": "3.13.0-13.33cross0.2" + "logstash-contrib": "1.4.0-1-b37bbca" + "libaa1-dev": "1.4p5-41" + "libmhash-dev": "0.9.9.9-4" + "python-webob": "1.3.1-1" + "accounts-qml-module-doc": "0.4+14.04.20140317-0ubuntu1" + "at": "3.1.14-1ubuntu1" + "heat-engine": "2014.1-0ubuntu1" + "libasound2-data": "1.0.27.2-3ubuntu7" + "libxaw7-dbg": "2:1.0.12-1" + "printer-driver-c2esp": "27~rc1-1" + "re2c": "0.13.5-1build2" + "xserver-xorg-lts-raring": "3:5" + "rdfind": "1.3.4-1ubuntu1" + "libmono-system-web-webpages2.0-cil": "3.2.8+dfsg-4ubuntu1" + "libreoffice-help-ko": "1:4.2.3~rc3-0ubuntu1" + "firefox-locale-ast": "28.0+build2-0ubuntu2" + "libknotifyconfig4": "4:4.13.0-0ubuntu1" + "libpangomm-1.4-1": "2.34.0-1ubuntu1" + "libesd0-dev": "0.2.41-11" + "libgcj14-dev": "4.8.2-19ubuntu1" + "libmonosgen-2.0-dev": "3.2.8+dfsg-4ubuntu1" + "language-pack-gnome-bn": "1:14.04+20140410" + "libgflags-doc": "2.0-1.1ubuntu1" + "libhttp-date-perl": "6.02-1" + "libnet-dns-resolver-programmable-perl": "0.003-2" + "python3-astroid": "1.0.1-1" + "linux-image-generic-lts-trusty": "3.13.0.24.28" + "language-pack-vi-base": "1:14.04+20140410" + "liburl-dispatcher1": "0.1+14.04.20140403-0ubuntu1" + "libvisio-0.0-0": "0.0.31-1ubuntu2" + "xserver-xorg-video-intel-dbg": "2:2.99.910-0ubuntu1" + "libmono-sharpzip2.6-cil": "3.2.8+dfsg-4ubuntu1" + "bacula-sd": "5.2.6+dfsg-9.1ubuntu3" + "linux-tools-lowlatency": "3.13.0.24.28" + "python3-checkbox-support": "0.2-1" + "libglapi-mesa": "10.1.0-4ubuntu5" + "libsystemd-id128-dev": "204-5ubuntu20" + "python3-pyqt5.qtwebkit-dbg": "5.2.1+dfsg-1ubuntu1" + "docbook2x": "0.8.8-9" + "libxext-dev": "2:1.3.2-1" + "mlocate": "0.26-1ubuntu1" + "language-pack-gnome-is": "1:14.04+20140410" + "libbind-dev": "1:9.9.5.dfsg-3" + "libdv4": "1.0.0-6" + "xaw3dg-dev": "1.5+E-18.2" + "libpurple0": "1:2.10.9-0ubuntu3" + "srvadmin-storelib": "7.1.0-2" + "zeitgeist-core": "0.9.14-0ubuntu4" + "installation-guide-powerpc": "20100518ubuntu10" + "language-pack-hr": "1:14.04+20140410" + "language-pack-nl": "1:14.04+20140410" + "python-testtools": "0.9.35-0ubuntu1" + "xul-ext-unity": "3.0.0+14.04.20140416-0ubuntu1" + "libpam-doc": "1.1.8-1ubuntu2" + "libfolks-eds-dev": "0.9.5-1ubuntu5" + "libmariadbclient18": "5.5.38+maria-1~trusty" + "mythes-en-au": "2.1-5.4" + "gdb-doc": "7.6.2-1ubuntu1" + "libgsl0ldbl": "1.16+dfsg-1ubuntu1" + "libtagc0-dev": "1.9.1-2" + "srvadmin-isvc": "7.1.0-2" + "libboost-regex1.54.0": "1.54.0-4ubuntu3" + "libdbus-c++-bin": "0.9.0-6ubuntu1" + "libgudev-1.0-0": "1:204-5ubuntu20" + "libkdb5-7": "1.12+dfsg-2ubuntu4" + "libxfont1": "1:1.4.7-1" + "librole-tiny-perl": "1.003002-1" + "libfltk1.1-dev": "1.1.10-17" + "libpam-ldap": "184-8.5ubuntu3" + "libpcap0.8": "1.5.3-2" + "libpolkit-gobject-1-dev": "0.105-4ubuntu2" + "libunique-1.0-0": "1.1.6-4ubuntu2" + "libxfont-dev": "1:1.4.7-1" + "strongswan-plugin-eap-peap": "5.1.2-0ubuntu2" + "libtheora-doc": "1.1.1+dfsg.1-3.2" + "python-oops-datedir-repo": "0.0.17-0ubuntu2" + "sgmltools-lite": "3.0.3.0.cvs.20010909-17" + "libboost-filesystem1.54-dev": "1.54.0-4ubuntu3" + "libtotem-plparser18": "3.10.2-0ubuntu1" + "libnet-ldap-perl": "1:0.5800-1" + "ssl-cert": "1.0.33" + "libpolkit-gobject-1-0": "0.105-4ubuntu2" + "unity-greeter": "14.04.9-0ubuntu1" + "libx32stdc++6-4.8-dbg": "4.8.2-19ubuntu1" + "libxcb-composite0": "1.10-2ubuntu1" + "dkms": "2.2.0.3-1.1ubuntu5" + "libgomp1-powerpc-cross": "4.8.2-16ubuntu3cross0.11" + "libgtop2-doc": "2.28.5-2" + "perltidy": "20120701-1" + "wbrazilian": "3.0~beta4-15" + "libnamespace-autoclean-perl": "0.15-1" + "nant": "0.92~rc1+dfsg-3" + "bogl-bterm": "0.1.18-9ubuntu1" + "python3-defer": "1.0.6-2build1" + "geoip-dbg": "1.6.0-1" + "libgtkspell3-3-0": "3.0.4-1" + "python3-pyqt4.qtsql-dbg": "4.10.4+dfsg-1ubuntu1" + "python-pylibacl": "0.5.1-1.1build4" + "python3-sane": "2.3.0-1ubuntu3" + "libbtf1.2.0": "1:4.2.1-3ubuntu1" + "libcurl3-gnutls": "7.35.0-1ubuntu2" + "libgdraw4": "20120731.b-5" + "libglade2.0-cil": "2.12.10-5" + "liblightdm-qt-dev": "1.10.0-0ubuntu3" + "account-plugin-salut": "3.8.6-0ubuntu9" + "gir1.2-hud-client-2": "13.10.1+14.04.20140402-0ubuntu1" + "libxml++2.6-dbg": "2.36.0-2ubuntu1" + "raptor-utils": "1.4.21-10" + "srvadmin-rac5": "7.1.0-2" + "python-kajiki": "0.4.4-1ubuntu1" + "gedit-dev": "3.10.4-0ubuntu4" + "libglade2-dev": "1:2.6.4-2" + "libipmiconsole2": "1.1.5-3ubuntu3" + "ure": "4.2.3~rc3-0ubuntu2" + "heat-api-cfn": "2014.1-0ubuntu1" + "libssh-doc": "0.6.1-0ubuntu3" + "kpartx": "0.4.9-3ubuntu7" + "libcryptsetup-dev": "2:1.6.1-1ubuntu1" + "libgettextpo-dev": "0.18.3.1-1ubuntu2" + "libobjc-4.8-dev": "4.8.2-19ubuntu1" + "libsub-name-perl": "0.05-1build4" + "xserver-xorg-video-sis-lts-saucy": "3:5" + "language-pack-gnome-dz-base": "1:14.04+20140410" + "libparse-debcontrol-perl": "2.005-4" + "oneconf": "0.3.7" + "libattica-dbg": "0.4.2-1" + "liblqr-1-0-dev": "0.4.1-2ubuntu1" + "libmono-system-identitymodel4.0-cil": "3.2.8+dfsg-4ubuntu1" + "lua5.1-doc": "5.1.5-5" + "libbasicobjects0": "0.3.0.1-4" + "strongswan-plugin-sql": "5.1.2-0ubuntu2" + "libmono-system-xml4.0-cil": "3.2.8+dfsg-4ubuntu1" + "nova-common": "1:2014.1-0ubuntu1" + "pinentry-doc": "0.8.3-1ubuntu1" + "tomcat7-examples": "7.0.52-1" + "libpst4-dbg": "0.6.59-1build1" + "xserver-xorg-video-intel": "2:2.99.910-0ubuntu1" + "python-pyasn1": "0.1.7-1ubuntu2" + "rhythmbox-data": "3.0.2-0ubuntu1" + "libgl1-mesa-glx-lts-raring": "3:5" + "libmemcachedprotocol0": "1.0.8-1ubuntu2" + "libxcb-xinerama0": "1.10-2ubuntu1" + "apg": "2.2.3.dfsg.1-2ubuntu1" + "libiberty-dev": "20131116-1" + "libunity-misc4": "4.0.5+14.04.20140115-0ubuntu1" + "libwpg-0.2-2": "0.2.2-1ubuntu1" + "phonon-backend-gstreamer-common": "4:4.7.1+git20140403-0ubuntu1" + "python-bson": "2.6.3-1build1" + "qemu-system-arm": "2.0.0~rc1+dfsg-0ubuntu3" + "gir1.2-networkmanager-1.0": "0.9.8.8-0ubuntu7" + "libexiv2-dev": "0.23-1ubuntu2" + "libodbc1": "2.2.14p2-5ubuntu5" + "libutempter0": "1.1.5-4build1" + "mdadm": "3.2.5-5ubuntu4" + "language-pack-sr-base": "1:14.04+20140410" + "rabbitmq-server": "3.2.4-1" + "libpipeline-dev": "1.3.0-1" + "packagekit": "0.8.12-1ubuntu5" + "language-selector-gnome": "0.129" + "libreoffice-l10n-fr": "1:4.2.3~rc3-0ubuntu1" + "bacula-common-pgsql": "5.2.6+dfsg-9.1ubuntu3" + "smoke-dev-tools": "4:4.13.0-0ubuntu1" + "xserver-xorg-input-void-lts-saucy": "3:5" + "libao-dbg": "1.1.0-2ubuntu2" + "libpython2.7": "2.7.6-8" + "python3-apt-dbg": "0.9.3.5" + "libnss3-nssdb": "2:3.15.4-1ubuntu7" + "libunity-core-6.0-9": "7.2.0+14.04.20140416-0ubuntu1" + "ca-certificates-java": "20130815ubuntu1" + "python-qt4-doc": "4.10.4+dfsg-1ubuntu1" + "libcephfs-jni": "0.79-0ubuntu1" + "python-appindicator": "12.10.1+13.10.20130920-0ubuntu4" + "libedataserver-1.2-18": "3.10.4-0ubuntu1" + "thunderbird-locale-zh-hant": "1:24.4.0+build1-0ubuntu1" + "xserver-xorg-video-sis-lts-raring": "3:5" + "pacemaker-dev": "1.1.10+git20130802-1ubuntu2" + "pulseaudio-module-x11-dbg": "1:4.0-0ubuntu11" + "usb-creator-common": "0.2.56" + "libvisio-doc": "0.0.31-1ubuntu2" + "python-cinder": "1:2014.1-0ubuntu1" + "qtscript5-doc": "5.2.1+dfsg-1ubuntu1" + "libgettextpo0": "0.18.3.1-1ubuntu2" + "libwacom2-dbg": "0.8-1" + "language-pack-wa": "1:14.04+20140410" + "libreoffice-l10n-zh-cn": "1:4.2.3~rc3-0ubuntu1" + "apache2-dbg": "2.4.7-1ubuntu4" + "libgtk-vnc-2.0-dev": "0.5.3-0ubuntu2" + "python-dirspec": "13.10-0ubuntu2" + "python-wadllib": "1.3.2-2build1" + "gnome-mahjongg": "1:3.10.2-0ubuntu1" + "libnewt-dev": "0.52.15-2ubuntu5" + "libxv-dev": "2:1.0.10-1" + "libdjvulibre-text": "3.5.25.4-3" + "libsndfile1-dev": "1.0.25-7ubuntu2" + "libxerces2-java-gcj": "2.11.0-7" + "libaio-dev": "0.3.109-4" + "cli-common-dev": "0.9" + "libwebkit-cil-dev": "0.3-6" + "firefox-locale-ja": "28.0+build2-0ubuntu2" + "lp-solve": "5.5.0.13-7build1" + "lsscsi": "0.27-2" + "xserver-xorg-video-cirrus-lts-saucy": "3:5" + "gstreamer1.0-doc": "1.2.3-1" + "totem-common": "3.10.1-1ubuntu4" + "gir1.2-appindicator-0.1": "12.10.1+13.10.20130920-0ubuntu4" + "libapparmor1": "2.8.95~2430-0ubuntu5" + "libelfg0": "0.8.13-5" + "libmono-system-net2.0-cil": "3.2.8+dfsg-4ubuntu1" + "python-sure": "1.2.2-2build1" + "x11-common": "1:7.7+1ubuntu8" + "gnome-terminal": "3.6.2-0ubuntu1" + "libfreeipmi12": "1.1.5-3ubuntu3" + "kernel-wedge": "2.87ubuntu1" + "language-pack-ast-base": "1:14.04+20140410" + "libwhoopsie-dev": "0.2.24.5" + "libgnome-keyring-common": "3.8.0-2" + "libreoffice-l10n-sv": "1:4.2.3~rc3-0ubuntu1" + "pm-utils": "1.4.1-13" + "gir1.2-dbusmenu-gtk-0.4": "12.10.3+14.04.20140319-0ubuntu1" + "libio-dirent-perl": "0.05-1build1" + "postgresql-contrib": "9.3+154" + "libxcomposite1-dbg": "1:0.4.4-1" + "libbit-vector-perl": "7.3-1build1" + "libktexteditor4": "4:4.13.0-0ubuntu1" + "linux-cloud-tools-lowlatency": "3.13.0.24.28" + "xserver-xorg-video-radeon-lts-raring-dbg": "3:5" + "libmail-spf-perl": "2.9.0-2" + "maas": "1.5+bzr2252-0ubuntu1" + "update-manager-core": "1:0.196.11" + "hardening-wrapper": "2.5ubuntu2" + "libisc95": "1:9.9.5.dfsg-3" + "python3-pyqt5.qtquick-dbg": "5.2.1+dfsg-1ubuntu1" + "libxmlbeans-java": "2.5.0-4build1" + "python-webtest-doc": "2.0.14-1ubuntu1" + "schroot-common": "1.6.8-1ubuntu1" + "squid-deb-proxy": "0.8.6" + "linux-generic-lts-raring-eol-upgrade": "3.13.0.24.28" + "python-egenix-mxproxy-doc": "3.2.7-1build1" + "libperl-dev": "5.18.2-2ubuntu1" + "xserver-xorg-video-sisusb-lts-saucy": "3:5" + "cups-ppdc": "1.7.2-0ubuntu1" + "psmisc": "22.20-1ubuntu2" + "python-pycurl-dbg": "7.19.3-0ubuntu3" + "dict-foldoc": "20120518-1" + "liblog4net-cil-dev": "1.2.10+dfsg-6" + "libmono-system-drawing-design4.0-cil": "3.2.8+dfsg-4ubuntu1" + "python-kombu-doc": "3.0.7-1ubuntu1" + "python-py": "1.4.20-1" + "iproute-doc": "1:3.12.0-2" + "libxerces2-java-doc": "2.11.0-7" + "grub-xen-dbg": "2.02~beta2-9" + "libhashkit2": "1.0.8-1ubuntu2" + "zlib1g-dbg": "1:1.2.8.dfsg-1ubuntu1" + "libstatgrab9": "0.90-1.1ubuntu1" + "libfontembed1": "1.0.52-0ubuntu1" + "libgnome-control-center1": "1:3.6.3-0ubuntu56" + "libx32z1": "1:1.2.8.dfsg-1ubuntu1" + "libmbim-glib-dev": "1.6.0-2" + "nagios3-dbg": "3.5.1-1ubuntu1" + "python3-pil.imagetk": "2.3.0-1ubuntu3" + "libio-multiplex-perl": "1.13-1" + "python-pyorbit-dev": "2.24.0-6ubuntu4" + "firefox-locale-lg": "28.0+build2-0ubuntu2" + "libgoogle-perftools4": "2.1-2ubuntu1" + "libusb-1.0-0-dev": "2:1.0.17-1ubuntu2" + "python3-uno": "1:4.2.3~rc3-0ubuntu2" + "hunspell-se": "1.0~beta6.20081222-1.2" + "libperl-critic-perl": "1.121-1" + "gcc-4.9-base": "4.9-20140406-0ubuntu1" + "gvfs-libs": "1.20.1-1ubuntu1" + "libldap-2.4-2": "2.4.31-1+nmu2ubuntu8" + "language-pack-or": "1:14.04+20140410" + "pyflakes": "0.8.1-1" + "unity-scopes-master-default": "6.8.2+14.04.20131029.1-0ubuntu1" + "libevdocument3-4": "3.10.3-0ubuntu10" + "xserver-xorg-input-synaptics-lts-saucy-dbg": "3:5" + "libclutter-1.0-0": "1.16.4-0ubuntu2" + "xserver-xorg-video-dummy-lts-quantal": "3:5" + "libisoburn-dbg": "1.3.2-1ubuntu1" + "cyrus-sasl2-doc": "2.1.25.dfsg1-17build1" + "language-pack-gnome-eu-base": "1:14.04+20140410" + "language-pack-gnome-kk-base": "1:14.04+20140410" + "libdaemon0": "0.14-2ubuntu1" + "libxatracker1-lts-saucy": "3:5" + "maas-region-controller-min": "1.5+bzr2252-0ubuntu1" + "libsbc-dev": "1.1-2ubuntu2" + "libxcb-shape0-dev": "1.10-2ubuntu1" + "telnet": "0.17-36build2" + "python3-fixtures": "0.3.14-1ubuntu2" + "python3-webtest": "2.0.14-1ubuntu1" + "libmission-control-plugins0": "1:5.16.1-1ubuntu3" + "syslinux-themes-ubuntu-trusty": "8" + "libcolumbus1": "1.1.0+14.04.20140325.3-0ubuntu1" + "libcolumbus1-common": "1.1.0+14.04.20140325.3-0ubuntu1" + "libhybris-common1": "0.1.0+git20131207+e452e83-0ubuntu12" + "docbook5-xml": "5.0-2" + "libmono-data-tds4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libbamf3-2": "0.5.1+14.04.20140409-0ubuntu1" + "libubuntu-platform-hardware-api1": "0.20+14.04.20140411-0ubuntu1" + "libclutter-1.0-dev": "1.16.4-0ubuntu2" + "libxcb-xevie0": "1.10-2ubuntu1" + "winbind": "2:4.1.6+dfsg-1ubuntu2" + "rhythmbox-dbg": "3.0.2-0ubuntu1" + "xserver-xorg-dev-lts-quantal": "3:5" + "libdconf-doc": "0.20.0-1" + "libhtml-template-perl": "2.95-1" + "libpeas-common": "1.8.1-2ubuntu2" + "libsaxon-java-doc": "1:6.5.5-10" + "libopts25-dev": "1:5.18-2ubuntu2" + "pinentry-gtk2": "0.8.3-1ubuntu1" + "wpasupplicant": "2.1-0ubuntu1" + "dbus": "1.6.18-0ubuntu4" + "firefox-locale-nso": "28.0+build2-0ubuntu2" + "libcppunit-dev": "1.13.1-2ubuntu1" + "libdv4-dev": "1.0.0-6" + "libreoffice-base": "1:4.2.3~rc3-0ubuntu2" + "python-newt-dbg": "0.52.15-2ubuntu5" + "fonts-lmodern": "2.004.4-3" + "language-pack-kl": "1:14.04+20140410" + "libclutter-gst-2.0-dbg": "2.0.8-1build1" + "libmemcached10": "1.0.8-1ubuntu2" + "libtelepathy-farstream3": "0.6.1-0ubuntu1" + "hyphen-ta": "0.7.0-1" + "libhashkit-dev": "1.0.8-1ubuntu2" + "libqt5sql5": "5.2.1+dfsg-1ubuntu14" + "libwnck-dev": "1:2.30.7-0ubuntu4" + "python-mox3": "0.7.0-1build1" + "help2man": "1.44.1" + "libdlrestrictions1": "0.15.12ubuntu1" + "debconf-i18n": "1.5.51ubuntu2" + "language-pack-gnome-lt-base": "1:14.04+20140410" + "libpath-tiny-perl": "0.052-1" + "python-compressor": "1.3-1ubuntu3" + "python-markdown-doc": "2.4-1" + "python3-psycopg2": "2.4.5-1build5" + "qt3d5-dev": "5.0~git20130731-0ubuntu5" + "unity-settings-daemon-dev": "14.04.0+14.04.20140414-0ubuntu1" + "wamerican-small": "7.1-1" + "liblzo2-dev": "2.06-1.2ubuntu1" + "libnepomukquery4a": "4:4.13.0-0ubuntu1" + "libxcb-res0-dbg": "1.10-2ubuntu1" + "python-geoip": "1.2.4-2ubuntu5" + "python-numpy-dbg": "1:1.8.1-1ubuntu1" + "language-pack-dz-base": "1:14.04+20140410" + "python-simplejson-doc": "3.3.1-1ubuntu6" + "libglibmm-2.4-dbg": "2.39.93-0ubuntu1" + "liboxideqtcore0": "1.0.0~bzr501-0ubuntu1" + "libsm6": "2:1.2.1-2" + "libtotem-pg5": "2.3.3-1ubuntu1" + "liblog-message-simple-perl": "0.10-1" + "ttf-malayalam-fonts": "1:0.5.14ubuntu1" + "libgles2-mesa-lts-raring-dbg": "3:5" + "libgnomeui-0": "2.24.5-3" + "libsnappy1": "1.1.0-1ubuntu1" + "qtbase5-private-dev": "5.2.1+dfsg-1ubuntu14" + "foomatic-db-engine": "4.0.11-0ubuntu1" + "postgresql-plpython-9.3": "9.3.4-1" + "python3-pil-dbg": "2.3.0-1ubuntu3" + "xserver-xorg-video-trident-lts-raring": "3:5" + "xserver-xorg-input-evdev-lts-raring": "3:5" + "language-pack-gnome-tl": "1:14.04+20140410" + "language-pack-gnome-wae-base": "1:14.04+20140410" + "libpackage-stash-perl": "0.36-1" + "wswedish": "1.4.5-2.1" + "libtool": "2.4.2-1.7ubuntu1" + "maven-ant-helper": "7.10" + "postgresql-client-9.3": "9.3.4-1" + "libmirplatform": "0.1.8+14.04.20140411-0ubuntu1" + "libx32gfortran3-dbg": "4.8.2-19ubuntu1" + "iamerican": "3.3.02-6" + "language-pack-hne-base": "1:12.04+20120417" + "bacula-sd-mysql": "5.2.6+dfsg-9.1ubuntu3" + "firefox-locale-te": "28.0+build2-0ubuntu2" + "libavahi-gobject-dev": "0.6.31-4ubuntu1" + "libmm-glib-doc": "1.0.0-2ubuntu1" + "python-distlib": "0.1.8-1" + "tcl-dev": "8.6.0+6ubuntu3" + "libdata-optlist-perl": "0.109-1" + "python-oslo.messaging": "1.3.0-0ubuntu1" + "libatkmm-1.6-dev": "2.22.7-2ubuntu1" + "libjavascriptcoregtk-3.0-dev": "2.4.0-1ubuntu2" + "liborbit2-dev": "1:2.14.19-0.3" + "session-migration": "0.2.1" + "gsettings-ubuntu-schemas": "0.0.1+14.04.20140401-0ubuntu1" + "pyqt5-dev": "5.2.1+dfsg-1ubuntu1" + "wpolish": "20130519-1" + "firefox-locale-et": "28.0+build2-0ubuntu2" + "libvncserver0": "0.9.9+dfsg-1ubuntu1" + "python3-tempita": "0.5.2-1build1" + "gir1.2-gnomekeyring-1.0": "3.8.0-2" + "libqt5x11extras5": "5.2.1-1" + "phonon-backend-gstreamer": "4:4.7.1+git20140403-0ubuntu1" + "augeas-doc": "1.2.0-0ubuntu1" + "libdb5.3++-dev": "5.3.28-3ubuntu3" + "liblua5.1-0": "5.1.5-5" + "libpoppler44": "0.24.5-2ubuntu4" + "libqtcore4-perl": "4:4.13.0-0ubuntu1" + "python-bsddb3-dbg": "6.0.1-1build1" + "python3-crypto": "2.6.1-4build1" + "unzip": "6.0-9ubuntu1" + "libmono-debugger-soft4.0a-cil": "3.2.8+dfsg-4ubuntu1" + "ruby-blankslate": "2.1.2.4-4" + "firefox-locale-sk": "28.0+build2-0ubuntu2" + "libmirclient7": "0.1.8+14.04.20140411-0ubuntu1" + "libsdl1.2-dbg": "1.2.15-8ubuntu1" + "libwacom-common": "0.8-1" + "e2fslibs": "1.42.9-3ubuntu1" + "libvorbisenc2": "1.3.2-1.3ubuntu1" + "telepathy-salut": "0.8.1-1ubuntu3" + "xserver-xorg-video-radeon": "1:7.3.0-1ubuntu3" + "libppi-perl": "1.215-1" + "libproxy-cil-dev": "0.4.11-0ubuntu4" + "python": "2.7.5-5ubuntu3" + "liblapack-doc": "3.5.0-2ubuntu1" + "grub-pc": "2.02~beta2-9" + "language-pack-gnome-ro-base": "1:14.04+20140410" + "libmtp-doc": "1.1.6-20-g1b9f164-1ubuntu2" + "libaspell-dev": "0.60.7~20110707-1ubuntu1" + "libvala-0.22-dev": "0.22.1-0ubuntu1" + "libxen-ocaml-dev": "4.4.0-0ubuntu5" + "click-doc": "0.4.21.1" + "nova-compute-libvirt": "1:2014.1-0ubuntu1" + "neutron-plugin-vmware": "1:2014.1-0ubuntu1" + "firefox-locale-sr": "28.0+build2-0ubuntu2" + "hello": "2.8-4" + "libxcb-xfixes0-dbg": "1.10-2ubuntu1" + "libx32stdc++6-4.7-dbg": "4.7.3-12ubuntu1" + "libxt6": "1:1.1.4-1" + "python-twisted-bin-dbg": "13.2.0-1ubuntu1" + "libboost1.54-doc": "1.54.0-4ubuntu3" + "libtest-minimumversion-perl": "0.101081-1" + "python3-pytest": "2.5.1-1" + "libcairomm-1.0-1": "1.10.0-1ubuntu3" + "libieee1284-3-dev": "0.2.11-12" + "alsa-base": "1.0.25+dfsg-0ubuntu4" + "gettext-el": "0.18.3.1-1ubuntu2" + "freetds-dev": "0.91-5" + "hplip-dbg": "3.14.3-0ubuntu3" + "libkjsapi4": "4:4.13.0-0ubuntu1" + "onboard": "1.0.0-0ubuntu4" + "openssl": "1.0.1f-1ubuntu2" + "xserver-xorg-input-all-lts-saucy": "3:5" + "oem-config-debconf": "2.18.7" + "evolution": "3.10.4-0ubuntu1" + "gir1.2-unity-5.0": "7.1.4+14.04.20140210-0ubuntu1" + "libjavascriptcoregtk-1.0-0": "2.4.0-1ubuntu2" + "linux-headers-server": "3.13.0.24.28" + "hunspell-sr": "1:4.2.1-0ubuntu1" + "libdbus-c++-dbg": "0.9.0-6ubuntu1" + "libgnutls26": "2.12.23-12ubuntu2.1" + "thunderbird-locale-id": "1:24.4.0+build1-0ubuntu1" + "python-apt-common": "0.9.3.5" + "gcj-4.8-jdk": "4.8.2-19ubuntu1" + "liblapack3": "3.5.0-2ubuntu1" + "python3-pyqt5.qtsensors-dbg": "5.2.1+dfsg-1ubuntu1" + "language-pack-gnome-gd": "1:14.04+20140410" + "neutron-plugin-openvswitch-agent": "1:2014.1-0ubuntu1" + "gir1.2-gmenu-3.0": "3.10.1-0ubuntu2" + "gir1.2-nmgtk-1.0": "0.9.8.8-0ubuntu4" + "dh-xsp": "3.0.11-1" + "compiz-gnome": "1:0.9.11+14.04.20140409-0ubuntu1" + "gcc-4.8-multilib-powerpc-linux-gnu": "4.8.2-16ubuntu3cross0.11" + "hunspell-da": "1:4.2.1-0ubuntu1" + "samba-doc": "2:4.1.6+dfsg-1ubuntu2" + "xserver-common-lts-raring": "3:5" + "libaprutil1": "1.5.3-1" + "libavahi-common-data": "0.6.31-4ubuntu1" + "libqt5qml5": "5.2.1-3ubuntu15" + "libv4l2rds0": "1.0.1-1" + "gobject-introspection": "1.40.0-1" + "libct4": "0.91-5" + "libfarstream-0.2-dbg": "0.2.3-1ubuntu2" + "libgoogle-glog0": "0.3.3-1" + "libgtk-vnc-1.0-0-dbg": "0.5.3-0ubuntu2" + "remmina-plugin-rdp": "1.0.0-4ubuntu3" + "gimp-help-nn": "2.6.1-1" + "libasound2-doc": "1.0.27.2-3ubuntu7" + "powerwake": "2.18-0ubuntu2" + "libkntlm4": "4:4.13.0-0ubuntu1" + "libxcb-icccm4": "0.4.1-1ubuntu1" + "libmono-sqlite2.0-cil": "3.2.8+dfsg-4ubuntu1" + "python-openid-doc": "2.2.5-3ubuntu1" + "libunix-syslog-perl": "1.1-2build5" + "libxz-java": "1.4-1" + "libaudit-dev": "1:2.3.2-2ubuntu1" + "libqt3support4-perl": "4:4.13.0-0ubuntu1" + "zlib1g-dev": "1:1.2.8.dfsg-1ubuntu1" + "libedit2-dbg": "3.1-20130712-2" + "account-plugin-facebook": "0.11+14.04.20140409.1-0ubuntu1" + "libmime-tools-perl": "5.505-1" + "python-parsedatetime": "1.1.2-0ubuntu1" + "texlive-base": "2013.20140215-1" + "firefox-locale-pa": "28.0+build2-0ubuntu2" + "texinfo-doc-nonfree": "5.2.0-1" + "vala-0.18-doc": "0.18.1-0ubuntu11" + "yui-compressor": "2.4.7-1" + "libsane-hpaio": "3.14.3-0ubuntu3" + "libwacom2": "0.8-1" + "libroman-perl": "1.23-1" + "python-oslotest-doc": "0.1-1ubuntu3" + "python3-d2to1": "0.2.11-1build1" + "binutils-aarch64-linux-gnu": "2.24-1ubuntu1cross0.11" + "firefox-locale-ml": "28.0+build2-0ubuntu2" + "lsb-desktop": "4.1+Debian11ubuntu6" + "libytnef0-dev": "1.5-6" + "gnome-accessibility-themes": "3.10.0-1ubuntu2" + "libcommons-net1-java": "1.4.1-5build1" + "libmailtools-perl": "2.12-1" + "grantlee-dbg": "0.4.0-0ubuntu1" + "libmagick++5": "8:6.7.7.10-6ubuntu3" + "toshset": "1.76-4" + "python3-oauthlib": "0.6.1-1" + "avahi-utils": "0.6.31-4ubuntu1" + "libaspell15": "0.60.7~20110707-1ubuntu1" + "libnih-dbus1": "1.0.3-4ubuntu25" + "libsl0-heimdal": "1.6~git20131207+dfsg-1ubuntu1" + "language-pack-gnome-gv-base": "1:14.04+20140410" + "language-pack-kn-base": "1:14.04+20140410" + "python3.4-examples": "3.4.0-2ubuntu1" + "sssd-proxy": "1.11.5-1ubuntu3" + "language-pack-ug": "1:14.04+20140410" + "libgtk2.0-doc": "2.24.23-0ubuntu1" + "python3-imaging": "2.3.0-1ubuntu3" + "libxxf86vm1-dbg": "1:1.1.3-1" + "language-pack-et": "1:14.04+20140410" + "libtest-object-perl": "0.07-2" + "libhangul1": "0.1.0-3" + "python3-yaml-dbg": "3.10-4build4" + "xserver-xorg-video-tdfx-lts-quantal": "3:5" + "libatk1.0-0": "2.10.0-2ubuntu2" + "libsmokeqt3support4-3": "4:4.13.0-0ubuntu1" + "libwpd-dev": "0.9.9-1" + "libxdamage1-dbg": "1:1.1.4-1ubuntu1" + "xserver-xorg-video-all": "1:7.7+1ubuntu8" + "libmono-microsoft-csharp4.0-cil": "3.2.8+dfsg-4ubuntu1" + "exim4-daemon-heavy-dbg": "4.82-3ubuntu2" + "libprocps3": "1:3.3.9-1ubuntu2" + "gir1.2-gstreamer-1.0": "1.2.3-1" + "libpangoft2-1.0-0": "1.36.3-1ubuntu1" + "plymouth-label": "0.8.8-0ubuntu17" + "hunspell-gl-es": "2.2a-10" + "libreoffice-l10n-zu": "1:4.2.3~rc3-0ubuntu1" + "manpages-dev": "3.54-1ubuntu1" + "ceph-fuse": "0.79-0ubuntu1" + "cpp-aarch64-linux-gnu": "4:4.8.2-1" + "libtie-ixhash-perl": "1.23-1" + "libcomerr2": "1.42.9-3ubuntu1" + "libgtkmm-2.4-dbg": "1:2.24.4-1ubuntu1" + "libgles1-mesa-lts-quantal-dbg": "3:5" + "fonts-unfonts-core": "1.0.3.is.1.0.2-080608-10ubuntu1" + "language-pack-gnome-ta": "1:14.04+20140410" + "python-configobj": "4.7.2+ds-5build1" + "python-sphinx": "1.2.2+dfsg-1ubuntu1" + "wfrench": "1.2.3-10" + "libthai-data": "0.1.20-3" + "python3-pycurl-dbg": "7.19.3-0ubuntu3" + "libavalon-framework-java-doc": "4.2.0-9" + "libegl1-mesa-drivers-lts-quantal": "3:5" + "libboost-serialization-dev": "1.54.0.1ubuntu1" + "libipmidetect0": "1.1.5-3ubuntu3" + "libmpdec2": "2.4.0-6" + "libp11-kit-gnome-keyring": "3.10.1-1ubuntu4" + "rhythmbox-plugin-cdrecorder": "3.0.2-0ubuntu1" + "xserver-xorg-video-r128-dbg": "6.9.2-1build1" + "libnunit2.6-cil": "2.6.0.12051+dfsg-2" + "libecj-java-gcj": "3.9.0-1" + "libmessaging-menu0": "13.10.1+14.04.20140410-0ubuntu1" + "libgles2-mesa-lts-quantal": "3:5" + "librsvg2-dev": "2.40.2-1" + "libslp1": "1.2.1-9" + "libproxy0.4-cil": "0.4.11-0ubuntu4" + "x11proto-input-dev": "2.3-1" + "libunity-gtk3-parser0": "0.0.0+14.04.20140403-0ubuntu1" + "xserver-xorg-video-mach64-lts-saucy": "3:5" + "librelp0": "1.2.2-2ubuntu1" + "libstrongswan": "5.1.2-0ubuntu2" + "libtest-perl-critic-perl": "1.02-1" + "exuberant-ctags": "1:5.9~svn20110310-7" + "libcamel-1.2-45": "3.10.4-0ubuntu1" + "libcolorhug-dev": "1.0.6-1" + "libcppunit-subunit-dev": "0.0.18-0ubuntu7" + "printer-driver-ptouch": "1.3-8" + "qtdeclarative5-dev": "5.2.1-3ubuntu15" + "language-pack-gnome-fr": "1:14.04+20140410" + "libgxps-doc": "0.2.2-2ubuntu2" + "groff": "1.22.2-5" + "libappindicator1": "12.10.1+13.10.20130920-0ubuntu4" + "libdevel-caller-perl": "2.06-1build1" + "rpm2cpio": "4.11.1-3" + "language-pack-kk": "1:14.04+20140410" + "unity-scope-gmusicbrowser": "0.1+13.10.20130723-0ubuntu1" + "libjson-c2": "0.11-3ubuntu1.2" + "libmono-2.0-1": "3.2.8+dfsg-4ubuntu1" + "libtk8.5-dbg": "8.5.15-2ubuntu3" + "libvigraimpex5": "1.10.0+dfsg-3ubuntu2" + "grub-doc": "0.97-29ubuntu66" + "perl-modules": "5.18.2-2ubuntu1" + "cpp-4.8-powerpc64le-linux-gnu": "4.8.2-16ubuntu4cross0.4" + "flite1-dev": "1.4-release-8" + "libtsan0": "4.8.2-19ubuntu1" + "libusb++-dev": "2:0.1.12-23.3ubuntu1" + "language-pack-gnome-kl-base": "1:14.04+20140410" + "libwayland0": "1.4.0-1ubuntu1" + "firefox-locale-mai": "28.0+build2-0ubuntu2" + "liblua5.2-0-dbg": "5.2.3-1" + "libsasl2-2": "2.1.25.dfsg1-17build1" + "liblocale-us-perl": "2.112150-1" + "python3-newt-dbg": "0.52.15-2ubuntu5" + "language-pack-gu-base": "1:14.04+20140410" + "system-config-kickstart": "2.5.20-0ubuntu23" + "ispell": "3.3.02-6" + "libboost-chrono1.54-dev": "1.54.0-4ubuntu3" + "libxvmc1": "2:1.0.8-1ubuntu1" + "cryptsetup": "2:1.6.1-1ubuntu1" + "dbus-test-runner": "14.04.1+14.04.20140320-0ubuntu1" + "libdbusmenu-gtk3-4": "12.10.3+14.04.20140319-0ubuntu1" + "libxtables10": "1.4.21-1ubuntu1" + "ceph-fuse-dbg": "0.79-0ubuntu1" + "libgpg-error-dev": "1.12-0.2ubuntu1" + "ceilometer-agent-central": "2014.1-0ubuntu1" + "libtest-use-ok-perl": "0.11-1" + "pylint": "1.1.0-1" + "python-d2to1": "0.2.11-1build1" + "ubuntu-virt-server": "1.4" + "libreoffice-l10n-gd": "1:4.2.3~rc3-0ubuntu1" + "samba-common": "2:4.1.6+dfsg-1ubuntu2" + "libsmbclient": "2:4.1.6+dfsg-1ubuntu2" + "libqscintilla2-dev": "2.8.1-2" + "librpm3": "4.11.1-3" + "language-pack-se-base": "1:14.04+20140410" + "libdbm-deep-perl": "2.0011-1" + "python-sip-doc": "4.15.5-1build1" + "cliff-tablib": "1.1-1" + "gir1.2-click-0.4": "0.4.21.1" + "iputils-ping": "3:20121221-4ubuntu1.1" + "webbrowser-app": "0.23+14.04.20140414-0ubuntu1" + "libcairomm-1.0-doc": "1.10.0-1ubuntu3" + "libhangul-data": "0.1.0-3" + "libmono-peapi4.0a-cil": "3.2.8+dfsg-4ubuntu1" + "firefox-dbg": "28.0+build2-0ubuntu2" + "powertop-dbg": "2.5-1ubuntu1" + "python3-all-dev": "3.4.0-0ubuntu2" + "language-pack-gnome-ia": "1:14.04+20140410" + "mobile-broadband-provider-info": "20140317-1" + "libatomic-ops-dev": "7.4-0ubuntu3" + "libpeas-dev": "1.8.1-2ubuntu2" + "libsmokeqt4-dbg": "4:4.13.0-0ubuntu1" + "libxml-namespacesupport-perl": "1.11-1" + "bash": "4.3-7ubuntu1" + "cpp-4.8-powerpc-linux-gnu": "4.8.2-16ubuntu3cross0.11" + "librdf0-dev": "1.0.17-1" + "xserver-xorg-input-evdev-dev-lts-quantal": "3:5" + "libxalan2-java": "2.7.1-9" + "swift-doc": "1.13.1-0ubuntu1" + "libjpeg-dev": "8c-2ubuntu8" + "nvidia-settings-experimental-304": "331.20-0ubuntu8" + "python-all-dbg": "2.7.5-5ubuntu3" + "libatk1.0-dbg": "2.10.0-2ubuntu2" + "libsepol1-dev": "2.2-1" + "libsoprano4": "2.9.4+dfsg1-0ubuntu2" + "autoconf2.13": "2.13-62" + "libmono-system-servicemodel-discovery4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libreoffice-l10n-mk": "1:4.2.3~rc3-0ubuntu1" + "libtext-levenshtein-perl": "0.06~01-2" + "mythes-sv": "1.3.1-2" + "libwvstreams4.6-base": "4.6.1-7" + "language-pack-gnome-nb": "1:14.04+20140410" + "libmono-system-net-http-formatting4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libdmx1-dbg": "1:1.1.3-1" + "libgbm1-dbg": "10.1.0-4ubuntu5" + "libgssglue1": "0.4-2ubuntu1" + "wswiss": "20120607-1" + "libsystemd-journal0": "204-5ubuntu20" + "python3-software-properties": "0.92.37.1" + "libgles2-mesa-lts-saucy": "3:5" + "language-pack-aa": "1:14.04+20140410" + "language-pack-gnome-ha-base": "1:14.04+20140410" + "libboost-python1.54-dev": "1.54.0-4ubuntu3" + "libpam-sss": "1.11.5-1ubuntu3" + "srvadmin-racdrsc": "7.1.0-2" + "libmono-system-io-compression4.0-cil": "3.2.8+dfsg-4ubuntu1" + "swig-doc": "2.0.11-1ubuntu2" + "gir1.2-folks-0.6": "0.9.5-1ubuntu5" + "libspiro0-dbg": "20071029-8ubuntu1" + "libnet-libidn-perl": "0.12.ds-1build4" + "friends-twitter": "0.2.0+14.04.20140217.1-0ubuntu1" + "language-pack-bn-base": "1:14.04+20140410" + "libjs-yui3-min": "3.5.1-1ubuntu3" + "python-imaging": "2.3.0-1ubuntu3" + "unity-webapps-common": "2.4.17+14.04.20140416-0ubuntu1" + "x11-utils": "7.7+1" + "fonts-kacst": "2.01+mry-10" + "language-pack-gnome-my-base": "1:14.04+20140410" + "python3-xkit": "0.5.0ubuntu2" + "liblinear-tools": "1.8+dfsg-1ubuntu1" + "libs3-dev": "2.0-2" + "libvpx-dev": "1.3.0-2" + "logstash": "1.4.0-1-c82dc09" + "python3-feedparser": "5.1.3-2" + "python3-stevedore": "0.14.1-1" + "libboost-thread-dev": "1.54.0.1ubuntu1" + "libgbm-dev-lts-saucy": "3:5" + "linux-libc-dev": "3.13.0-32.57" + "libxml-dom-perl": "1.44-1" + "libgee-0.8-2-dbg": "0.10.5-1ubuntu1" + "libxkbcommon-x11-0": "0.4.1-0ubuntu1" + "python-qt4-sql-dbg": "4.10.4+dfsg-1ubuntu1" + "language-pack-gnome-shs": "1:14.04+20140410" + "neutron-plugin-nec": "1:2014.1-0ubuntu1" + "tzdata-java": "2014b-1" + "dbus-cpp-dev-examples": "2.0.0+14.04.20140326-0ubuntu1" + "squashfs-tools": "1:4.2+20130409-2" + "gimp-dbg": "2.8.10-0ubuntu1" + "bacula-server": "5.2.6+dfsg-9.1ubuntu3" + "libqt5scintilla2-dev": "2.8.1-2" + "mysql-common": "5.5.38+maria-1~trusty" + "neutron-plugin-cisco": "1:2014.1-0ubuntu1" + "zsh-common": "5.0.2-3ubuntu6" + "x11proto-scrnsaver-dev": "1.2.2-1" + "db5.3-util": "5.3.28-3ubuntu3" + "libavc1394-0": "0.5.4-2" + "libnetfilter-conntrack-dev": "1.0.4-1" + "libatkmm-1.6-doc": "2.22.7-2ubuntu1" + "python-flask": "0.10.1-2build1" + "python2.7-minimal": "2.7.6-8" + "xserver-xorg-video-mach64-dbg": "6.9.4-1build1" + "xserver-xorg-video-radeon-lts-saucy": "3:5" + "python-reportlab-doc": "3.0-1build1" + "bacula-common-sqlite3-dbg": "5.2.6+dfsg-9.1ubuntu3" + "libpoppler-dev": "0.24.5-2ubuntu4" + "mysql-server-5.5": "5.5.35+dfsg-1ubuntu1" + "indicator-printers": "0.1.7+14.04.20140313-0ubuntu1" + "cpp-4.7-doc": "4.7.3-12ubuntu1" + "libmono-system-numerics4.0-cil": "3.2.8+dfsg-4ubuntu1" + "linux-image-3.13.0-30-generic": "3.13.0-30.55" + "syslinux-themes-ubuntu-precise": "8" + "libhx-doc": "3.15-2ubuntu1" + "module-init-tools": "15-0ubuntu6" + "pbuilder": "0.215ubuntu7" + "libxpm-dev": "1:3.5.10-1" + "shared-mime-info": "1.2-0ubuntu3" + "language-pack-gnome-sa-base": "1:14.04+20140410" + "gir1.2-javascriptcoregtk-1.0": "2.4.0-1ubuntu2" + "libcsparse3.1.2": "1:4.2.1-3ubuntu1" + "libtotem-pg-dev": "2.3.3-1ubuntu1" + "php5-pgsql": "5.5.9+dfsg-1ubuntu4" + "openslp-doc": "1.2.1-9" + "libfftw3-dbg": "3.3.3-7ubuntu3" + "libpth20": "2.0.7-19ubuntu1" + "libxcb-dri2-0-dev": "1.10-2ubuntu1" + "fonts-tibetan-machine": "1.901b-5" + "language-pack-hsb-base": "1:12.04+20120417" + "language-pack-pt": "1:14.04+20140410" + "libmono-system-web-services4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libxen-dev": "4.4.0-0ubuntu5" + "libxml2-utils": "2.9.1+dfsg1-3ubuntu4" + "language-pack-uk": "1:14.04+20140410" + "laptop-detect": "0.13.7ubuntu2" + "libgtk-3-dev": "3.10.8-0ubuntu1" + "libnss-db": "2.2.3pre1-5build3" + "libvte-2.90-dev": "1:0.34.9-1ubuntu1" + "libdbi-doc": "0.9.0-1" + "libreoffice-l10n-bs": "1:4.2.3~rc3-0ubuntu1" + "gobjc": "4:4.8.2-1ubuntu6" + "libxkbfile1": "1:1.0.8-1" + "python3-pyqt5.qtsvg-dbg": "5.2.1+dfsg-1ubuntu1" + "firefox-locale-sw": "28.0+build2-0ubuntu2" + "uno-libs3": "4.2.3~rc3-0ubuntu2" + "hunspell-eu-es": "0.4.20081029-6" + "language-pack-gnome-ml": "1:14.04+20140410" + "libhardware-dev": "0.1.0+git20131207+e452e83-0ubuntu12" + "libmariadbclient-dev": "5.5.38+maria-1~trusty" + "lsof": "4.86+dfsg-1ubuntu2" + "libgegl-0.2-0": "0.2.0-4ubuntu1" + "libzip2": "0.10.1-1.2" + "language-pack-cs-base": "1:14.04+20140410" + "x11proto-resource-dev": "1.2.0-3" + "iw": "3.4-1" + "libxslt1.1": "1.1.28-2build1" + "python2.7-dev": "2.7.6-8" + "language-pack-gnome-nds-base": "1:14.04+20140410" + "advancecomp": "1.18-1" + "libgdbm3": "1.8.3-12build1" + "linux-tools-virtual": "3.13.0.24.28" + "python-libvirt": "1.2.2-0ubuntu1" + "libzeitgeist-doc": "0.3.18-1ubuntu2" + "libboost-thread1.54-dev": "1.54.0-4ubuntu3" + "language-pack-gnome-bo-base": "1:14.04+20140410" + "lksctp-tools": "1.0.15+dfsg-1" + "subversion": "1.8.8-1ubuntu3" + "language-pack-lt-base": "1:14.04+20140410" + "libxml-sax-expat-perl": "0.40-2" + "pyqt5-examples": "5.2.1+dfsg-1ubuntu1" + "python-beanstalkc": "0.3.0-2build1" + "libanthy-dev": "9100h-23ubuntu2" + "python-webob-doc": "1.3.1-1" + "libdb-dev": "1:5.3.21~exp1ubuntu1" + "libtest-failwarnings-perl": "0.7-1" + "libdee-qt5-dev": "3.3+14.04.20140317-0ubuntu1" + "libexpat1-dev": "2.1.0-4ubuntu1" + "libpath-utils-dev": "0.3.0.1-4" + "libtcl8.6": "8.6.1-4ubuntu1" + "language-pack-gnome-yi-base": "1:14.04+20140410" + "lib64gcc1-powerpc-cross": "1:4.8.2-16ubuntu3cross0.11" + "hunspell": "1.3.2-6ubuntu2" + "libcheese-gtk23": "3.10.2-0ubuntu2" + "libkdewebkit5": "4:4.13.0-0ubuntu1" + "libqca2-dev": "2.0.3-5" + "backuppc": "3.3.0-1ubuntu1" + "libnatpmp-dev": "20110808-3ubuntu2" + "nautilus-sendto": "3.6.1-2ubuntu1" + "language-pack-es": "1:14.04+20140410" + "python-ipaddr": "2.1.10-1" + "odbc-mdbtools": "0.7.1-1ubuntu1" + "thunderbird-locale-pa": "1:24.4.0+build1-0ubuntu1" + "apt-listchanges": "2.85.13ubuntu2" + "libmono-system-xaml4.0-cil": "3.2.8+dfsg-4ubuntu1" + "mtx": "1.3.12-8" + "python-ldb-dev": "1:1.1.16-1" + "tdsodbc": "0.91-5" + "dh-di": "6" + "gsfonts": "1:8.11+urwcyr1.0.7~pre44-4.2ubuntu1" + "libbluetooth3-dbg": "4.101-0ubuntu13" + "libwps-dev": "0.2.9-2ubuntu1" + "libxcb-xfixes0": "1.10-2ubuntu1" + "libc6-armhf-cross": "2.19-0ubuntu2cross1.104" + "libbamf3-dev": "0.5.1+14.04.20140409-0ubuntu1" + "pkg-config-aarch64-linux-gnu": "4:4.8.2-1" + "orbit2": "1:2.14.19-0.3" + "libfftw3-doc": "3.3.3-7ubuntu3" + "libxalan2-java-doc": "2.7.1-9" + "ncurses-base": "5.9+20140118-1ubuntu1" + "libcanberra-gstreamer": "0.30-0ubuntu3" + "libcupsfilters-dev": "1.0.52-0ubuntu1" + "python3-openssl-dbg": "0.13-2ubuntu6" + "language-pack-gnome-cs-base": "1:14.04+20140410" + "python3-setuptools": "3.3-1ubuntu1" + "docbook-to-man": "1:2.0.0-31" + "libmonosgen-2.0-1-dbg": "3.2.8+dfsg-4ubuntu1" + "mesa-common-dev-lts-raring": "3:5" + "firefox-locale-be": "28.0+build2-0ubuntu2" + "libical1": "1.0-0ubuntu1" + "libjpeg-turbo8-dbg": "1.3.0-0ubuntu2" + "language-pack-th-base": "1:14.04+20140410" + "libreoffice-l10n-ss": "1:4.2.3~rc3-0ubuntu1" + "run-one": "1.17-0ubuntu1" + "slice": "1.3.8-12" + "bacula-common-sqlite3": "5.2.6+dfsg-9.1ubuntu3" + "postfix": "2.11.0-1" + "ubuntu-location-service-examples": "0.0.2+14.04.20140307-0ubuntu1" + "xserver-xorg-video-intel-lts-saucy": "3:5" + "libpython2.7-testsuite": "2.7.6-8" + "libtest-inter-perl": "1.05-1" + "binutils-powerpc-linux-gnu": "2.24-2ubuntu1cross0.10" + "libaccount-plugin-generic-oauth": "0.11+14.04.20140409.1-0ubuntu1" + "libatasmart-dev": "0.19-3" + "libmono-system-runtime2.0-cil": "3.2.8+dfsg-4ubuntu1" + "libcap-ng0": "0.7.3-1ubuntu2" + "libgcc1-armhf-cross": "1:4.8.2-16ubuntu4cross0.11" + "python-pymongo-doc": "2.6.3-1build1" + "libclamav-dev": "0.98.1+dfsg-4ubuntu1" + "libsm6-dbg": "2:1.2.1-2" + "packagekit-tools": "0.8.12-1ubuntu5" + "libatk-bridge2.0-dev": "2.10.2-2ubuntu1" + "libtelepathy-glib-dev": "0.22.1-1ubuntu2" + "libtiff4-dev": "4.0.3-7" + "pulseaudio-module-x11": "1:4.0-0ubuntu11" + "autopoint": "0.18.3.1-1ubuntu2" + "libglamor0": "0.6.0-0ubuntu4" + "gvfs-common": "1.20.1-1ubuntu1" + "language-pack-lo-base": "1:14.04+20140410" + "libmono-cairo2.0-cil": "3.2.8+dfsg-4ubuntu1" + "python-ubuntuone-devtools": "13.10-0ubuntu2" + "python3-packagekit": "0.8.12-1ubuntu5" + "libnss3": "2:3.15.4-1ubuntu7" + "python3-pam": "0.4.2-13.1ubuntu3" + "language-pack-gnome-as": "1:14.04+20140410" + "language-pack-gnome-hr": "1:14.04+20140410" + "bacula-sd-pgsql-dbg": "5.2.6+dfsg-9.1ubuntu3" + "dict": "1.12.1+dfsg-2" + "less": "458-2" + "libleveldb-dev": "1.15.0-2" + "language-pack-ca": "1:14.04+20140410" + "language-pack-gnome-mn": "1:14.04+20140410" + "latex2html": "2008-debian1-10" + "libreoffice-l10n-mr": "1:4.2.3~rc3-0ubuntu1" + "libglibmm-2.4-dev": "2.39.93-0ubuntu1" + "perlqt-dbg": "4:4.13.0-0ubuntu1" + "usb-creator-gtk": "0.2.56" + "language-pack-gnome-br": "1:14.04+20140410" + "libasm3-java-doc": "3.3.2-2" + "iputils-ping": "3:20121221-4ubuntu1" + "libsctp1": "1.0.15+dfsg-1" + "xserver-xorg-video-qxl": "0.1.1-0ubuntu3" + "libuuid-perl": "0.05-1" + "python-lxml": "3.3.3-1" + "libdata-section-simple-perl": "0.05-1" + "icedtea-7-plugin": "1.5-1ubuntu1" + "libavahi-glib-dev": "0.6.31-4ubuntu1" + "libconvert-uulib-perl": "1:1.4~dfsg-1build3" + "libestr-dev": "0.1.9-0ubuntu2" + "language-pack-gnome-mhr": "1:14.04+20140410" + "qt4-qmake": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "wirish": "2.0-22" + "libgee2": "0.6.8-1ubuntu1" + "librabbitmq-dev": "0.4.1-1" + "libx32gfortran-4.7-dev": "4.7.3-12ubuntu1" + "libreoffice-help-ru": "1:4.2.3~rc3-0ubuntu1" + "libstrigiqtdbusclient0": "0.7.8-1ubuntu2" + "libjdom1-java": "1.1.3-1" + "ltsp-server": "5.5.1-1ubuntu2" + "cpu-checker": "0.7-0ubuntu4" + "freeradius": "2.1.12+dfsg-1.2ubuntu8" + "lib32stdc++6": "4.8.2-19ubuntu1" + "libunwind8-dev": "1.1-2.2ubuntu3" + "libxcb-dri3-0": "1.10-2ubuntu1" + "language-pack-yo": "1:14.04+20140410" + "augeas-dbg": "1.2.0-0ubuntu1" + "cvsps": "2.1-6build1" + "libmaa-dev": "1.3.2-2" + "libqtwebkit-dev": "2.3.2-0ubuntu7" + "kpartx-boot": "0.4.9-3ubuntu7" + "libsexy-doc": "0.1.11-2ubuntu1" + "python-notify": "0.1.1-3ubuntu2" + "language-pack-sq-base": "1:14.04+20140410" + "python3-json-patch": "1.3-4" + "byacc-j": "1.15-1build2" + "clamav-freshclam": "0.98.1+dfsg-4ubuntu1" + "language-pack-si-base": "1:14.04+20140410" + "libcommons-pool-java-doc": "1.6-2" + "libcolord1": "1.0.6-1" + "python-mailer": "0.7-1ubuntu2" + "libgnutls26-dbg": "2.12.23-12ubuntu2" + "python3-pylibacl-dbg": "0.5.1-1.1build4" + "gconf2-common": "3.2.6-0ubuntu2" + "libmono-system-reactive-windows-forms2.2-cil": "3.2.8+dfsg-4ubuntu1" + "python-oauthlib": "0.6.1-1" + "libdbusmenu-qt-dev": "0.9.3+14.04.20140314-0ubuntu1" + "libphononexperimental4": "4:4.7.1-0ubuntu8" + "myspell-tn": "20070206-4ubuntu1" + "libgssdp-1.0-dev": "0.14.7-1ubuntu1" + "xserver-xorg-video-openchrome-lts-saucy": "3:5" + "debconf-doc": "1.5.51ubuntu2" + "libemail-address-perl": "1.900-1" + "libmono-system-web-webpages-razor2.0-cil": "3.2.8+dfsg-4ubuntu1" + "python3-nine": "0.3.3-2" + "libcdio-cdda1": "0.83-4.1ubuntu1" + "pcmciautils": "018-8" + "xserver-xorg-video-r128-lts-quantal-dbg": "3:5" + "libexporter-lite-perl": "0.02-2" + "libjack-jackd2-0": "1.9.9.5+20130622git7de15e7a-1ubuntu1" + "libjson-c2": "0.11-3ubuntu1" + "libqt5core5a": "5.2.1+dfsg-1ubuntu14" + "libwayland-client0": "1.4.0-1ubuntu1" + "libegl1-mesa-dev-lts-raring": "3:5" + "libprotobuf8": "2.5.0-9ubuntu1" + "libvformat-dev": "1.13-10" + "python-pocketsphinx": "0.8.0+real-0ubuntu6" + "python3-numpy": "1:1.8.1-1ubuntu1" + "libmspub-doc": "0.0.6-1ubuntu2" + "libtest-memory-cycle-perl": "1.04-1" + "postgresql-doc-9.3": "9.3.4-1" + "libraptor2-0": "2.0.13-1" + "librsync1": "0.9.7-10" + "gnome-settings-daemon-schemas": "3.8.6.1-0ubuntu11" + "jflex": "1.4.3-3" + "upstart-monitor": "1.12.1-0ubuntu4" + "lib32readline6-dev": "6.3-4ubuntu2" + "strongswan-dbg": "5.1.2-0ubuntu2" + "fonts-gubbi": "1.3-3" + "fonts-lao": "0.0.20060226-9" + "libkparts4": "4:4.13.0-0ubuntu1" + "libqt5svg5": "5.2.1-1" + "libxatracker-dev": "10.1.0-4ubuntu5" + "sgmls-doc": "1.03ii-32" + "cups": "1.7.2-0ubuntu1" + "exim4-base": "4.82-3ubuntu2" + "hyphen-it": "1:4.2.1-0ubuntu1" + "libreoffice-core": "1:4.2.3~rc3-0ubuntu2" + "command-not-found": "0.3ubuntu12" + "libreoffice-l10n-pt-br": "1:4.2.3~rc3-0ubuntu1" + "python-egenix-mxstack-doc": "3.2.7-1build1" + "libxmuu1": "2:1.1.1-1" + "libasm4-java-doc": "4.1-3" + "mythes-hu": "1:4.2.1-0ubuntu1" + "flex": "2.5.35-10.1ubuntu2" + "libqt5designercomponents5": "5.2.1-8build1" + "libxcb-dpms0": "1.10-2ubuntu1" + "rarian-compat": "0.8.1-5ubuntu1" + "javacc": "5.0-5" + "libhttp-message-perl": "6.06-1" + "gcc-aarch64-linux-gnu": "4:4.8.2-1" + "jfsutils": "1.1.15-2.1" + "librados2": "0.79-0ubuntu1" + "libbcprov-java-doc": "1.49+dfsg-2" + "libgd-barcode-perl": "1.15-5ubuntu1" + "ocaml-nox": "4.01.0-3ubuntu3" + "libxv1-dbg": "2:1.0.10-1" + "amavisd-new": "1:2.7.1-2ubuntu3" + "gcc": "4:4.8.2-1ubuntu6" + "libcppunit-1.13-0": "1.13.1-2ubuntu1" + "libcunit1-ncurses-dev": "2.1-2.dfsg-1" + "libkafs0-heimdal": "1.6~git20131207+dfsg-1ubuntu1" + "x11proto-damage-dev": "1:1.2.1-2" + "iputils-tracepath": "3:20121221-4ubuntu1" + "libboost-serialization1.54.0": "1.54.0-4ubuntu3" + "debugedit": "4.11.1-3" + "libdrm-nouveau2-dbg": "2.4.52-1" + "libxcb-xevie0-dev": "1.10-2ubuntu1" + "xorg": "1:7.7+1ubuntu8" + "libvoikko1": "3.7-2ubuntu2" + "language-pack-gnome-tg-base": "1:14.04+20140410" + "gconf-service": "3.2.6-0ubuntu2" + "gir1.2-rest-0.7": "0.7.90-0ubuntu1" + "gnome-system-monitor": "3.8.2.1-2ubuntu1" + "libqt4-help": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "libreoffice-l10n-ca": "1:4.2.3~rc3-0ubuntu1" + "firefox-locale-or": "28.0+build2-0ubuntu2" + "python-glade2": "2.24.0-3ubuntu3" + "srvadmin-idrac-vmcli": "7.1.0-2" + "xserver-xorg-input-mouse": "1:1.9.0-1build1" + "mythes-sk": "1:4.2.1-0ubuntu1" + "tomcat7-admin": "7.0.52-1" + "libdigest-hmac-perl": "1.03+dfsg-1" + "libeasymock-java-doc": "2.5.2+ds-1" + "libhpmud0": "3.14.3-0ubuntu3" + "libportaudio2": "19+svn20140130-1" + "srvadmin-storageservices": "7.1.0-3" + "xserver-xorg-video-neomagic-lts-quantal": "3:5" + "aptdaemon-data": "1.1.1-1ubuntu5" + "python3-subunit": "0.0.18-0ubuntu7" + "hud": "13.10.1+14.04.20140402-0ubuntu1" + "libfolks-telepathy-dbg": "0.9.5-1ubuntu5" + "libvpx1": "1.3.0-2" + "subunit": "0.0.18-0ubuntu7" + "libnettle4": "2.7.1-1" + "bittornado": "0.3.18-10ubuntu4" + "xserver-xorg-video-modesetting-lts-saucy": "3:5" + "wbritish-large": "7.1-1" + "libldns1-dbg": "1.6.17-1" + "libplasma3": "4:4.13.0-0ubuntu1" + "libufe-xidgetter0": "3.0.0+14.04.20140416-0ubuntu1" + "transmission-qt": "2.82-1.1ubuntu3" + "apache2-doc": "2.4.7-1ubuntu4" + "python-recaptcha": "1.0.6-1build1" + "python-zeitgeist": "0.9.14-0ubuntu4" + "eximon4": "4.82-3ubuntu2" + "language-pack-cv-base": "1:14.04+20140410" + "language-pack-ml": "1:14.04+20140410" + "python-bzrlib.tests": "2.6.0+bzr6593-1ubuntu1" + "xserver-xorg-video-radeon-dbg": "1:7.3.0-1ubuntu3" + "gnome-icon-theme-symbolic": "3.10.1-1ubuntu1" + "libmono-accessibility4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libpst-dev": "0.6.59-1build1" + "libwww-robotrules-perl": "6.01-1" + "logstash": "1.4.2-1-2c0f5a1" + "eperl": "2.2.14-20build1" + "libboost-program-options1.54-dev": "1.54.0-4ubuntu3" + "libklibc-dev": "2.0.3-0ubuntu1" + "libstrictures-perl": "1.005002-1" + "python-cmd2": "0.6.7-2fakesync1build1" + "util-linux-locales": "2.20.1-5.1ubuntu20" + "libgtk-vnc-1.0-dev": "0.5.3-0ubuntu2" + "python-txtftp": "0.1~bzr38-0ubuntu2" + "libebackend-1.2-7": "3.10.4-0ubuntu1" + "libseccomp2": "2.1.0+dfsg-1" + "qtchooser": "39-g4717841-3" + "xserver-xorg-video-sisusb-lts-quantal": "3:5" + "debconf-utils": "1.5.51ubuntu2" + "grub-ipxe": "1.0.0+git-20131111.c3d1e78-2ubuntu1" + "libatomic1-arm64-cross": "4.8.2-13ubuntu1cross0.11" + "libcairo2-doc": "1.13.0~20140204-0ubuntu1" + "libreoffice-officebean": "1:4.2.3~rc3-0ubuntu2" + "libc6-dev-i386": "2.19-0ubuntu6" + "libnl-nf-3-dev": "3.2.21-1" + "python3-pyqt4.qtsql": "4.10.4+dfsg-1ubuntu1" + "openvpn": "2.3.2-7ubuntu3" + "pth-dbg": "2.0.7-19ubuntu1" + "fonts-vlgothic": "20130607-1ubuntu1" + "libchart-perl": "2.4.6-1" + "maven-repo-helper": "1.8.5" + "qtsvg5-doc": "5.2.1-1" + "unity-scope-openclipart": "0.1+13.10.20130723-0ubuntu1" + "python-txlongpoll": "0.3.1+bzr86-0ubuntu3" + "ubuntu-sso-client-qt": "13.10-0ubuntu6" + "gtk-sharp2-gapi": "2.12.10-5" + "culmus": "0.130-1" + "libnautilus-extension-dev": "1:3.10.1-0ubuntu8" + "libpkcs11-helper1-dev": "1.11-1" + "language-pack-nso": "1:14.04+20140410" + "libpod-coverage-perl": "0.23-1" + "unity-voice-service": "0.1+14.04.20140304-0ubuntu1" + "language-pack-gnome-gu-base": "1:14.04+20140410" + "libmbim-glib0": "1.6.0-2" + "libtiff5": "4.0.3-7" + "qtlocation5-dbg": "5.2.1-1ubuntu2" + "libmodule-pluggable-perl": "5.1-1" + "libmono-relaxng2.0-cil": "3.2.8+dfsg-4ubuntu1" + "clvm": "2.02.98-6ubuntu2" + "libdmapsharing-3.0-dev": "2.9.24-0ubuntu1" + "libunityvoice1": "0.1+14.04.20140304-0ubuntu1" + "adduser": "3.113+nmu3ubuntu3" + "language-pack-gnome-zu": "1:14.04+20140410" + "xfonts-utils": "1:7.7+1" + "libqt5serialport5-dev": "5.2.1-1" + "openssh-sftp-server": "1:6.6p1-2ubuntu1" + "php5-tidy": "5.5.9+dfsg-1ubuntu4" + "modemmanager-doc": "1.0.0-2ubuntu1" + "default-jdk": "2:1.7-51" + "devhelp": "3.8.2-2ubuntu1" + "libcupsppdc1-dev": "1.7.2-0ubuntu1" + "libjavascriptcoregtk-1.0-0-dbg": "2.4.0-1ubuntu2" + "qtbase5-dev-tools": "5.2.1+dfsg-1ubuntu14" + "libbcpg-java-doc": "1.49+dfsg-2" + "libcglib-java": "2.2.2+dfsg-5" + "libtask-weaken-perl": "1.04-1" + "libkcmutils4": "4:4.13.0-0ubuntu1" + "srvadmin-realssd": "7.1.0-2" + "libexcalibur-logkit-java": "2.0-10" + "python-imaging-doc": "2.3.0-1ubuntu3" + "firefox-locale-mk": "28.0+build2-0ubuntu2" + "gstreamer1.0-clutter": "2.0.8-1build1" + "python3-plainbox-doc": "0.5.3-2" + "libubuntu-application-api1": "0.20+14.04.20140411-0ubuntu1" + "javahelper": "0.45ubuntu1" + "libjaxen-java-doc": "1.1.6-1ubuntu1" + "python-dbus-doc": "1.2.0-2build2" + "python-ibus": "1.5.5-1ubuntu3" + "python-mox": "0.5.3-3build1" + "heat-api-cloudwatch": "2014.1-0ubuntu1" + "iproute2": "3.12.0-2" + "libnetcf1-dbg": "1:0.2.3-4ubuntu1" + "libpolkit-qt-1-1": "0.103.0-1ubuntu1" + "hyphen-hi": "0.7.0-3" + "libsss-sudo": "1.11.5-1ubuntu3" + "xserver-xorg-video-all-lts-quantal": "3:5" + "libatkmm-1.6-dbg": "2.22.7-2ubuntu1" + "linuxdoc-tools": "0.9.69-2" + "witalian": "1.7.5ubuntu1" + "libegl1-mesa-drivers-lts-raring-dbg": "3:5" + "libknewstuff2-4": "4:4.13.0-0ubuntu1" + "libnux-4.0-common": "4.0.6+14.04.20140409-0ubuntu1" + "libqt5webkit5-dbg": "5.1.1-1ubuntu8" + "bash": "4.3-6ubuntu1" + "libnm-gtk-dev": "0.9.8.8-0ubuntu4" + "signon-keyring-extension": "0.6+14.04.20140307-0ubuntu1" + "texlive-extra-utils": "2013.20140215-2" + "cpp-arm-linux-gnueabihf": "4:4.8.2-1" + "pax": "1:20120606-2+deb7u1" + "python-twisted": "13.2.0-1ubuntu1" + "libjpeg62": "6b1-4ubuntu1" + "libqjson-dbg": "0.8.1-3" + "vorbis-tools": "1.4.0-1ubuntu3" + "libmbim-glib-doc": "1.6.0-2" + "python-pip": "1.5.4-1" + "gcc-powerpc64le-linux-gnu": "4:4.8.2-1" + "libxss1": "1:1.2.2-1" + "lua5.2": "5.2.3-1" + "language-pack-gnome-kk": "1:14.04+20140410" + "language-pack-id": "1:14.04+20140410" + "python-itsdangerous": "0.22+dfsg1-1build1" + "libsensors4": "1:3.3.4-2ubuntu1" + "language-pack-gnome-mt": "1:14.04+20140410" + "python-colorama": "0.2.5-0.1ubuntu1" + "libpcsclite1-dbg": "1.8.10-1ubuntu1" + "libsecret-1-0": "0.16-0ubuntu1" + "libserf-1-1": "1.3.3-1" + "freeradius-utils": "2.1.12+dfsg-1.2ubuntu8" + "x11-xserver-utils-lts-quantal": "3:5" + "libavalon-framework-java": "4.2.0-9" + "libraptor1-doc": "1.4.21-10" + "libreoffice-l10n-pl": "1:4.2.3~rc3-0ubuntu1" + "mythes-de": "20120516-2" + "python-setuptools-git": "1.0b1-0ubuntu3" + "language-pack-my-base": "1:14.04+20140410" + "libmono-i18n-cjk4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libwebkit1.1-cil": "0.3-6" + "gnome-user-share": "3.0.4-0ubuntu1" + "libtcl8.6-dbg": "8.6.1-4ubuntu1" + "language-pack-gnome-mi": "1:14.04+20140410" + "neutron-plugin-ml2": "1:2014.1-0ubuntu1" + "cups-dbg": "1.7.2-0ubuntu1" + "libqt5location5": "5.2.1-1ubuntu2" + "libserf1-dbg": "1.3.3-1" + "libgles1-mesa-dbg": "10.1.0-4ubuntu5" + "xserver-xorg-input-synaptics-dev-lts-saucy": "3:5" + "dblatex": "0.3.4-3build1" + "language-pack-gnome-ca": "1:14.04+20140410" + "libboost-doc": "1.54.0.1ubuntu1" + "dconf-cli": "0.20.0-1" + "ghostscript-dbg": "9.10~dfsg-0ubuntu10" + "evolution-dev": "3.10.4-0ubuntu1" + "libxcb-xv0-dbg": "1.10-2ubuntu1" + "cinder-scheduler": "1:2014.1-0ubuntu1" + "libdbusmenu-gtk-doc": "12.10.3+14.04.20140319-0ubuntu1" + "python-doc": "2.7.5-5ubuntu3" + "ubuntu-ui-toolkit-doc": "0.1.46+14.04.20140408.1-0ubuntu1" + "libmodule-signature-perl": "0.73-1" + "libmono-system-reactive-windows-threading2.2-cil": "3.2.8+dfsg-4ubuntu1" + "anthy": "9100h-23ubuntu2" + "lib32tinfo5": "5.9+20140118-1ubuntu1" + "libsmokeqtdeclarative4-3": "4:4.13.0-0ubuntu1" + "debian-goodies": "0.63" + "language-pack-mai": "1:14.04+20140410" + "libcrypt-openssl-rsa-perl": "0.28-1build1" + "libssl1.0.0": "1.0.1f-1ubuntu2.4" + "libstrigihtmlgui-dev": "0.7.8-1ubuntu2" + "ruby-flexmock": "0.9.0-1" + "ant-optional-gcj": "1.9.3-2build1" + "hfsplus": "1.0.4-12.1" + "libck-connector-dev": "0.4.5-3.1ubuntu2" + "libecpg-compat3": "9.3.4-1" + "language-pack-gnome-ia-base": "1:14.04+20140410" + "ruby-hiera": "1.3.0-1" + "libcairo-gobject2": "1.13.0~20140204-0ubuntu1" + "libseccomp-dev": "2.1.0+dfsg-1" + "libxcb-keysyms1-dev": "0.3.9-1ubuntu1" + "python3-coverage": "3.7.1+dfsg.1-1ubuntu2" + "language-pack-gnome-sc-base": "1:14.04+20140410" + "myspell-lv": "0.9.6-1" + "neutron-plugin-midonet": "1:2014.1-0ubuntu1" + "libgrantlee-dev": "0.4.0-0ubuntu1" + "libhdate-dev": "1.6-2ubuntu3" + "qtscript5-private-dev": "5.2.1+dfsg-1ubuntu1" + "cloud-utils": "0.27-0ubuntu9" + "language-pack-da": "1:14.04+20140410" + "libreoffice-l10n-za": "1:4.2.3~rc3-0ubuntu2" + "libqtgui4": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "libglew-dbg": "1.10.0-3" + "nettle-dev": "2.7.1-1" + "libantlr-dev": "2.7.7+dfsg-5" + "libcheese7": "3.10.2-0ubuntu2" + "libunity-gtk2-parser0": "0.0.0+14.04.20140403-0ubuntu1" + "qtsvg5-examples": "5.2.1-1" + "rrdtool": "1.4.7-2ubuntu5" + "cgmanager": "0.24-0ubuntu7" + "libamd2.3.1": "1:4.2.1-3ubuntu1" + "libcdr-dev": "0.0.15-1ubuntu1" + "libgxps-dev": "0.2.2-2ubuntu2" + "notify-osd": "0.9.35+14.04.20140213-0ubuntu1" + "language-pack-gnome-ber": "1:14.04+20140410" + "glib-networking-services": "2.40.0-1" + "python3-pyqt5-dbg": "5.2.1+dfsg-1ubuntu1" + "libsfstdc++-4.8-dev-armhf-cross": "4.8.2-16ubuntu4cross0.11" + "emacs24-nox": "24.3+1-2ubuntu1" + "myspell-ca": "0.20111230b-4" + "lib32readline6": "6.3-4ubuntu2" + "ruby-augeas": "0.5.0-2" + "shim": "0.4-0ubuntu4" + "ltsp-docs": "1.1-1" + "myspell-ts": "20070207-4ubuntu1" + "libwebkitgtk-1.0-0-dbg": "2.4.0-1ubuntu2" + "network-manager-gnome": "0.9.8.8-0ubuntu4" + "python-gpgme": "0.3-0ubuntu3" + "language-pack-hi": "1:14.04+20140410" + "libserf-dev": "1.3.3-1" + "thunderbird-locale-nn": "1:24.4.0+build1-0ubuntu1" + "tcl8.5": "8.5.15-2ubuntu1" + "xserver-xorg-input-synaptics-dev-lts-raring": "3:5" + "firefox-locale-pt": "28.0+build2-0ubuntu2" + "libaccounts-qt5-dev": "1.11+14.04.20140410.1-0ubuntu1" + "libgnome2-dev": "2.32.1-4ubuntu1" + "libgpod-common": "0.8.3-4ubuntu3" + "linux-generic-lts-quantal": "3.13.0.24.28" + "libusbmuxd-dev": "1.0.8-2ubuntu1" + "rubygems-integration": "1.5" + "gstreamer1.0-alsa": "1.2.3-1" + "librecode-dev": "3.6-21" + "ant-contrib": "1.0~b3+svn177-6" + "cinder-common": "1:2014.1-0ubuntu1" + "fonts-sil-padauk": "2.80-2" + "hyphen-af": "1:4.2.1-0ubuntu1" + "language-pack-be-base": "1:14.04+20140410" + "python3-zope.interface": "4.0.5-1ubuntu4" + "signon-plugin-oauth2-dev": "0.19+14.04.20140305-0ubuntu2" + "xserver-xorg-video-radeon-lts-saucy-dbg": "3:5" + "language-pack-eo": "1:14.04+20140410" + "language-pack-gnome-ky": "1:14.04+20140410" + "libpoppler-qt4-dev": "0.24.5-2ubuntu4" + "libprelude2": "1.0.0-11ubuntu4" + "mozilla-devscripts": "0.36" + "libgnomevfs2-extra": "1:2.24.4-1ubuntu6" + "liblinear1": "1.8+dfsg-1ubuntu1" + "language-pack-gnome-fur": "1:14.04+20140410" + "libqdox-java-doc": "1.12-1build1" + "libgegl-dev": "0.2.0-4ubuntu1" + "pwgen": "2.06-1ubuntu4" + "libjs-jquery-tablesorter": "8-2" + "python-anyjson": "0.3.3-1build1" + "python-dnspython": "1.11.1-1build1" + "libevent-extra-2.0-5": "2.0.21-stable-1ubuntu1" + "libfcgi0ldbl": "2.4.0-8.1ubuntu5" + "libx32tinfo5": "5.9+20140118-1ubuntu1" + "ocfs2-tools-dev": "1.6.4-3ubuntu1" + "language-pack-gnome-ta-base": "1:14.04+20140410" + "libmono-microsoft-web-infrastructure1.0-cil": "3.2.8+dfsg-4ubuntu1" + "espeak": "1.47.11-1ubuntu1" + "libevent-2.0-5": "2.0.21-stable-1ubuntu1" + "libgpm2": "1.20.4-6.1" + "python3-piston-mini-client": "0.7.5-0ubuntu2" + "libcloog-isl4": "0.18.2-1" + "libminiupnpc-dev": "1.6-3ubuntu2" + "lsb-printing": "4.1+Debian11ubuntu6" + "libjs-jquery-isonscreen": "1.2.0-1" + "python3-mako": "0.9.1-1" + "libipmiconsole-dev": "1.1.5-3ubuntu3" + "python3-pyqt5.qtsql-dbg": "5.2.1+dfsg-1ubuntu1" + "rdate": "1:1.2-5" + "language-pack-gnome-ur": "1:14.04+20140410" + "mono-4.0-gac": "3.2.8+dfsg-4ubuntu1" + "ubuntu-wallpapers-trusty": "14.04.0.1-0ubuntu1" + "libprocps3-dev": "1:3.3.9-1ubuntu2" + "libvorbis0a": "1.3.2-1.3ubuntu1" + "python-requestbuilder": "0.1.0~beta2-1build1" + "zenity-common": "3.8.0-1ubuntu1" + "libproxy1-plugin-networkmanager": "0.4.11-0ubuntu4" + "libtinfo5-dbg": "5.9+20140118-1ubuntu1" + "trousers-dbg": "0.3.11.2-1" + "python-pika": "0.9.13-1build1" + "language-pack-kl-base": "1:14.04+20140410" + "cython": "0.20.1+git90-g0e6e38e-1ubuntu2" + "libpulsedsp-dbg": "1:4.0-0ubuntu11" + "libclutter-1.0-common": "1.16.4-0ubuntu2" + "erlang-asn1": "1:16.b.3-dfsg-1ubuntu2" + "file": "1:5.14-2ubuntu3" + "libaio1-dbg": "0.3.109-4" + "libtirpc1": "0.2.2-5ubuntu2" + "libx32go4": "4.8.2-19ubuntu1" + "telepathy-haze": "0.8.0-1" + "libstdc++-4.8-dev": "4.8.2-19ubuntu1" + "parted": "2.3-19ubuntu1" + "libtasn1-3-dev": "3.4-3" + "libtime-modules-perl": "2011.0517-1" + "libxpp3-java": "1.1.4c-2build1" + "libjack0": "1:0.121.3+20120418git75e3e20b-2.1ubuntu1" + "libpisock9": "0.12.5-6ubuntu2" + "openjdk-7-source": "7u51-2.4.6-1ubuntu4" + "wamerican-huge": "7.1-1" + "apache2-utils": "2.4.7-1ubuntu4" + "pulseaudio-esound-compat": "1:4.0-0ubuntu11" + "libpython3-stdlib": "3.4.0-0ubuntu2" + "libreoffice-base-core": "1:4.2.3~rc3-0ubuntu2" + "libunwind-setjmp0-dbg": "1.1-2.2ubuntu3" + "mono-runtime": "3.2.8+dfsg-4ubuntu1" + "sssd-krb5": "1.11.5-1ubuntu3" + "ttf-alee": "13" + "libid3tag0": "0.15.1b-10ubuntu1" + "libqt5serialport5": "5.2.1-1" + "libwacom-dev": "0.8-1" + "smbios-utils": "2.2.13-0ubuntu4" + "libsmokeqtwebkit4-3": "4:4.13.0-0ubuntu1" + "strongswan-plugin-sqlite": "5.1.2-0ubuntu2" + "language-pack-li-base": "1:14.04+20140410" + "python-ply": "3.4-3ubuntu2" + "gstreamer0.10-alsa": "0.10.36-1.1ubuntu2" + "liblua5.1-0-dev": "5.1.5-5" + "libselinux1": "2.2.2-1" + "libgtkhtml-4.0-common": "4.6.6-2ubuntu1" + "libdns100": "1:9.9.5.dfsg-3" + "libplumb2": "1.0.11+hg2754-1.1build1" + "python-gevent-dbg": "1.0-1ubuntu1" + "libqt5positioning5": "5.2.1-1ubuntu2" + "libxss-dev": "1:1.2.2-1" + "pulseaudio": "1:4.0-0ubuntu11" + "gstreamer0.10-doc": "0.10.36-1.2ubuntu3" + "python-twisted-conch": "1:13.2.0-1ubuntu1" + "gir1.2-atspi-2.0": "2.10.2.is.2.10.1-0ubuntu1" + "gir1.2-cheese-3.0": "3.10.2-0ubuntu2" + "libcogl-pango15": "1.16.2-1" + "uuid-runtime": "2.20.1-5.1ubuntu20" + "python3-mock": "1.0.1-3" + "apache2-dev": "2.4.7-1ubuntu4" + "brasero": "3.10.0-0ubuntu1" + "lsb-graphics": "4.1+Debian11ubuntu6" + "xserver-xorg-video-nouveau-lts-quantal": "3:5" + "heimdal-docs": "1.6~git20131207+dfsg-1ubuntu1" + "libapache2-mod-php5": "5.5.9+dfsg-1ubuntu4" + "language-pack-gnome-bg": "1:14.04+20140410" + "language-pack-tt-base": "1:14.04+20140410" + "libmono-system-runtime-serialization-formatters-soap4.0-cil": "3.2.8+dfsg-4ubuntu1" + "linux-sound-base": "1.0.25+dfsg-0ubuntu4" + "nautilus-share": "0.7.3-1ubuntu5" + "malaga-doc": "7.12-4.1ubuntu1" + "libboost-python1.54.0": "1.54.0-4ubuntu3" + "language-pack-gnome-mk-base": "1:14.04+20140410" + "x11proto-record-dev": "1.14.2-1" + "libgoa-backend-1.0-dev": "3.10.3-0ubuntu1" + "gstreamer1.0-plugins-good-doc": "1.2.3-1ubuntu2" + "libsgmls-perl": "1.03ii-32" + "procps": "1:3.3.9-1ubuntu2" + "syslinux-legacy": "2:3.63+dfsg-2ubuntu5" + "python-twisted-runner-dbg": "13.2.0-1ubuntu1" + "libgl1-mesa-dri-lts-raring": "3:5" + "fonts-arphic-bkai00mp": "2.10-12" + "libreoffice-l10n-et": "1:4.2.3~rc3-0ubuntu1" + "myspell-gv": "0.50-11" + "unity-scope-musique": "0.1+13.10.20130723-0ubuntu1" + "libdlm3": "4.0.1-0ubuntu1" + "thunderbird-locale-fy-nl": "1:24.4.0+build1-0ubuntu1" + "dvipng": "1.14-2" + "firefox-locale-nn": "28.0+build2-0ubuntu2" + "hud-doc": "13.10.1+14.04.20140402-0ubuntu1" + "language-pack-gnome-mn-base": "1:14.04+20140410" + "libdom4j-java-doc": "1.6.1+dfsg.3-2ubuntu1" + "libtest-synopsis-perl": "0.06+ds-1" + "libwvstreams4.6-doc": "4.6.1-7" + "libfribidi-bin": "0.19.6-1" + "libgnomeui-dev": "2.24.5-3" + "libqscintilla2-11": "2.8.1-2" + "libxcb-xf86dri0-dev": "1.10-2ubuntu1" + "erlang-syntax-tools": "1:16.b.3-dfsg-1ubuntu2" + "libapparmor-dev": "2.8.95~2430-0ubuntu5" + "libdbd-pgsql": "0.9.0-2ubuntu2" + "libsystemd-id128-0": "204-5ubuntu20" + "libgmime2.6-cil": "2.6.20-0ubuntu1" + "libreoffice-l10n-de": "1:4.2.3~rc3-0ubuntu1" + "python3-configglue": "1.1.2-0ubuntu2" + "libqtassistantclient-dev": "4.6.3-6" + "language-pack-fil": "1:14.04+20140410" + "autopkgtest": "2.14.1" + "libcupscgi1-dev": "1.7.2-0ubuntu1" + "python-vte": "1:0.28.2-5ubuntu1" + "libqt4-dbg": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "thunderbird-locale-hr": "1:24.4.0+build1-0ubuntu1" + "libmono-system-threading-tasks-dataflow4.0-cil": "3.2.8+dfsg-4ubuntu1" + "accountsservice": "0.6.35-0ubuntu7" + "binutils": "2.24-5ubuntu3" + "libindirect-perl": "0.31-1" + "libkfile4": "4:4.13.0-0ubuntu1" + "mono-csharp-shell": "3.2.8+dfsg-4ubuntu1" + "python-cairo-dev": "1.8.8-1ubuntu5" + "libsuitesparse-dbg": "1:4.2.1-3ubuntu1" + "qtdeclarative5-test-plugin": "5.2.1-3ubuntu15" + "thunderbird-locale-bg": "1:24.4.0+build1-0ubuntu1" + "hplip-doc": "3.14.3-0ubuntu3" + "zeitgeist": "0.9.14-0ubuntu4" + "cmake-dbg": "2.8.12.2-0ubuntu3" + "libvisio-dev": "0.0.31-1ubuntu2" + "myspell-nr": "20070206-4ubuntu1" + "srvadmin-standardagent": "7.1.0-3" + "distro-info-data": "0.18ubuntu0.1" + "bacula-director-pgsql": "5.2.6+dfsg-9.1ubuntu3" + "bacula-sd-pgsql": "5.2.6+dfsg-9.1ubuntu3" + "libx32objc4": "4.8.2-19ubuntu1" + "printer-driver-hpijs": "3.14.3-0ubuntu3" + "python-pil.imagetk-dbg": "2.3.0-1ubuntu3" + "iso-codes": "3.52-1" + "language-pack-gnome-lb": "1:14.04+20140410" + "libparse-recdescent-perl": "1.967009+dfsg-1" + "liblua5.2-rrd0": "1.4.7-2ubuntu5" + "libunwind-setjmp0": "1.1-2.2ubuntu3" + "scdaemon": "2.0.22-3ubuntu1" + "xserver-xorg-input-void": "1:1.4.0-1build3" + "libmono-compilerservices-symbolwriter4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libreoffice-help-pt": "1:4.2.3~rc3-0ubuntu1" + "libxmlgraphics-commons-java-doc": "1.5-4ubuntu1" + "libcamel1.2-dev": "3.10.4-0ubuntu1" + "pciutils": "1:3.2.1-1ubuntu5" + "user-setup": "1.48ubuntu2" + "libmtp-dbg": "1.1.6-20-g1b9f164-1ubuntu2" + "libxcb-xtest0-dev": "1.10-2ubuntu1" + "sssd-krb5-common": "1.11.5-1ubuntu3" + "language-pack-gnome-si": "1:14.04+20140410" + "xserver-xorg-input-synaptics-dev": "1.7.4-0ubuntu1" + "libpython3-dev": "3.4.0-0ubuntu2" + "libsmbios2": "2.2.13-0ubuntu4" + "nautilus": "1:3.10.1-0ubuntu8" + "libxcb-xinerama0-dbg": "1.10-2ubuntu1" + "qemu-system-misc": "2.0.0~rc1+dfsg-0ubuntu3" + "qttools5-dev-tools": "5.2.1-8build1" + "seahorse": "3.10.2-0ubuntu1" + "speech-dispatcher": "0.8-5ubuntu1" + "language-pack-gnome-sq-base": "1:14.04+20140410" + "libc6-armel-armhf-cross": "2.19-0ubuntu2cross1.104" + "libjs-yui3-full": "3.5.1-1ubuntu3" + "texi2html": "1.82+dfsg1-3" + "libgupnp-igd-1.0-dbg": "0.2.2-1" + "language-pack-is-base": "1:14.04+20140410" + "libjpeg-turbo8": "1.3.0-0ubuntu2" + "libnl-route-3-200": "3.2.21-1" + "libspiro-dev": "20071029-8ubuntu1" + "metacity": "1:2.34.13-0ubuntu4" + "fonts-ipafont-gothic": "00303-12ubuntu1" + "po-debconf": "1.0.16+nmu2ubuntu1" + "iptables-dev": "1.4.21-1ubuntu1" + "libplumb2-dev": "1.0.11+hg2754-1.1build1" + "libxcb-screensaver0": "1.10-2ubuntu1" + "libapp-fatpacker-perl": "0.010000-1" + "libclutter-gst-2.0-doc": "2.0.8-1build1" + "x11proto-dri3-dev": "1.0-1" + "libini-config-dev": "0.3.0.1-4" + "python3-lxc": "1.0.3-0ubuntu3" + "language-pack-gnome-fy-base": "1:14.04+20140410" + "libreoffice-l10n-nb": "1:4.2.3~rc3-0ubuntu1" + "irssi": "0.8.15-5ubuntu3" + "libxcb-dri3-0-dbg": "1.10-2ubuntu1" + "libreoffice-help-cs": "1:4.2.3~rc3-0ubuntu1" + "libusb-1.0-doc": "2:1.0.17-1ubuntu2" + "libx32go5": "4.9-20140406-0ubuntu1" + "python3-openssl": "0.13-2ubuntu6" + "ureadahead": "0.100.0-16" + "qtsensors5-dev": "5.2.1+dfsg-2ubuntu2" + "libmono-system-net4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libtree-dagnode-perl": "1.17-1" + "python-json-patch": "1.3-4" + "software-properties-gtk": "0.92.36" + "gtk2-engines": "1:2.20.2-3ubuntu1" + "libpwquality1": "1.2.3-1ubuntu1" + "snmpd": "5.7.2~dfsg-8.1ubuntu3" + "libpisync1": "0.12.5-6ubuntu2" + "libc6-pic": "2.19-0ubuntu6" + "libgd3": "2.1.0-3" + "libverto-glib1": "0.2.4-1ubuntu2" + "language-pack-ber-base": "1:14.04+20140410" + "language-pack-fr": "1:14.04+20140410" + "language-pack-gnome-dv-base": "1:14.04+20140410" + "language-pack-gnome-yi": "1:14.04+20140410" + "language-pack-tr": "1:14.04+20140410" + "printer-driver-m2300w": "0.51-11" + "language-pack-gnome-ms": "1:14.04+20140410" + "libtest-requires-perl": "0.07-1" + "libegl1-mesa-drivers-lts-saucy": "3:5" + "libfftw3-bin": "3.3.3-7ubuntu3" + "libxrandr2-dbg": "2:1.4.2-1" + "language-pack-gnome-fur-base": "1:14.04+20140410" + "language-pack-mr": "1:14.04+20140410" + "ldm-server": "2:2.2.13-1" + "gir1.2-ebookcontacts-1.2": "3.10.4-0ubuntu1" + "gir1.2-gkbd-3.0": "3.6.0-0ubuntu2" + "gnome-screenshot": "3.10.1-0ubuntu1" + "libqt4-opengl-dev": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "libvisual-0.4-dev": "0.4.0-5" + "apparmor-easyprof-ubuntu": "1.1.16" + "epydoc-doc": "3.0.1+dfsg-4" + "gnome-common": "3.10.0-1" + "libmono-i18n4.0-all": "3.2.8+dfsg-4ubuntu1" + "libsfgcc-4.8-dev-armhf-cross": "4.8.2-16ubuntu4cross0.11" + "linux-headers-generic": "3.13.0.24.28" + "qemu-system-x86": "2.0.0~rc1+dfsg-0ubuntu3" + "ibus-m17n": "1.3.4-3ubuntu1" + "liblinear-dev": "1.8+dfsg-1ubuntu1" + "libpython3.4-dev": "3.4.0-2ubuntu1" + "libtalloc2-dbg": "2.1.0-1" + "unity-lens-files": "7.1.0+13.10.20130920-0ubuntu1" + "install-info": "5.2.0.dfsg.1-2" + "libmono-system-runtime-serialization4.0-cil": "3.2.8+dfsg-4ubuntu1" + "systemtap-sdt-dev": "2.3-1ubuntu1" + "libc6-ppc64-powerpc-cross": "2.19-0ubuntu2cross1.1" + "openssh-blacklist-extra": "0.4.1+nmu1" + "libkeyutils1": "1.5.6-1" + "libpth-dev": "2.0.7-19ubuntu1" + "libxcb-xkb1": "1.10-2ubuntu1" + "erlang-src": "1:16.b.3-dfsg-1ubuntu2" + "language-pack-gnome-mg": "1:14.04+20140410" + "libgles2-mesa": "10.1.0-4ubuntu5" + "libwvstreams4.6-extras": "4.6.1-7" + "bzip2-doc": "1.0.6-5" + "libapache2-mod-python": "3.3.1-11ubuntu2" + "pkg-config-powerpc-linux-gnu": "4:4.8.2-1" + "libsexy-dev": "0.1.11-2ubuntu1" + "upstart": "1.12.1-0ubuntu4.2" + "apparmor-docs": "2.8.95~2430-0ubuntu5" + "language-pack-oc": "1:14.04+20140410" + "libmtp-common": "1.1.6-20-g1b9f164-1ubuntu2" + "texlive-pictures-doc": "2013.20140215-1" + "libaugeas-dev": "1.2.0-0ubuntu1" + "mesa-common-dev": "10.1.0-4ubuntu5" + "thunderbird-locale-hu": "1:24.4.0+build1-0ubuntu1" + "language-pack-gnome-bo": "1:14.04+20140410" + "language-pack-gnome-en-base": "1:14.04+20140410" + "unity-scope-firefoxbookmarks": "0.1+13.10.20130809.1-0ubuntu1" + "libcap2-bin": "1:2.24-0ubuntu2" + "linux-tools-lts-quantal": "3.13.0.24.28" + "language-pack-gnome-pa": "1:14.04+20140410" + "nova-compute-lxc": "1:2014.1-0ubuntu1" + "python-pymongo-ext": "2.6.3-1build1" + "qtdeclarative5-localstorage-plugin": "5.2.1-3ubuntu15" + "libmono-system-io-compression-filesystem4.0-cil": "3.2.8+dfsg-4ubuntu1" + "qtbase5-doc": "5.2.1-8build1" + "bacula-sd-dbg": "5.2.6+dfsg-9.1ubuntu3" + "ifupdown": "0.7.47.2ubuntu4" + "libgnutls26": "2.12.23-12ubuntu2" + "libsigsegv-dev": "2.10-2" + "libreoffice-l10n-tn": "1:4.2.3~rc3-0ubuntu1" + "libgdbm-dev": "1.8.3-12build1" + "libqtxmlpatterns4-perl": "4:4.13.0-0ubuntu1" + "libcanberra-gtk3-module-dbg": "0.30-0ubuntu3" + "libjasper1": "1.900.1-14ubuntu3" + "lib32go5": "4.9-20140406-0ubuntu1" + "python-subversion-dbg": "1.8.8-1ubuntu3" + "python3-dbus.mainloop.pyqt5": "5.2.1+dfsg-1ubuntu1" + "language-pack-gnome-ja-base": "1:14.04+20140410" + "mythes-pl": "1.5-4ubuntu1" + "python3-aptdaemon.test": "1.1.1-1ubuntu5" + "libxcb-record0": "1.10-2ubuntu1" + "libxinerama1": "2:1.1.3-1" + "icedtea-netx-common": "1.5-1ubuntu1" + "libdbus-c++-doc": "0.9.0-6ubuntu1" + "libmono-system-data-services2.0-cil": "3.2.8+dfsg-4ubuntu1" + "language-pack-ja": "1:14.04+20140410" + "liblcms2-2": "2.5-0ubuntu4" + "samba-libs": "2:4.1.6+dfsg-1ubuntu2" + "whoopsie-preferences": "0.12" + "libgnomecanvas2-0": "2.30.3-2" + "mtr-tiny": "0.85-2" + "strongswan-plugin-eap-tnc": "5.1.2-0ubuntu2" + "libtest-output-perl": "1.02-1" + "attr": "1:2.4.47-1ubuntu1" + "libreoffice-sdbc-firebird": "1:4.2.3~rc3-0ubuntu2" + "xserver-xorg-input-evdev-dev-lts-raring": "3:5" + "python3-pyicu-dbg": "1.5-2ubuntu4" + "crossbuild-essential-armhf": "11.6ubuntu6" + "language-pack-af": "1:14.04+20140410" + "language-pack-ff-base": "1:14.04+20140410" + "libgtkhtml-4.0-0": "4.6.6-2ubuntu1" + "libstdc++-4.8-pic": "4.8.2-19ubuntu1" + "language-pack-gnome-hi-base": "1:14.04+20140410" + "libnss3-tools": "2:3.15.4-1ubuntu7" + "libqt4-declarative-gestures": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "strongswan-plugin-dhcp": "5.1.2-0ubuntu2" + "libunityvoice1-dev": "0.1+14.04.20140304-0ubuntu1" + "python-egenix-mxtexttools": "3.2.7-1build1" + "gstreamer1.0-plugins-good": "1.2.3-1ubuntu2" + "libwayland-client0-dbg": "1.4.0-1ubuntu1" + "libreoffice-l10n-in": "1:4.2.3~rc3-0ubuntu2" + "python-greenlet-doc": "0.4.2-1build1" + "fontconfig": "2.11.0-0ubuntu4" + "g++-4.8": "4.8.2-19ubuntu1" + "gnome-session-bin": "3.9.90-0ubuntu12" + "language-pack-gnome-vi-base": "1:14.04+20140410" + "libboost-system1.54.0": "1.54.0-4ubuntu3.1" + "librasqal3": "0.9.32-1" + "libgnome-vfs2.0-cil-dev": "2.24.2-3" + "nagios3-common": "3.5.1-1ubuntu1" + "libqt4-dev": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "libtextwrap1": "0.1-14" + "gcc-4.8-doc": "4.8.2-19ubuntu1" + "python-dictclient": "1.0.3.1+nmu1build1" + "libusbmuxd2-dbg": "1.0.8-2ubuntu1" + "python-pyicu": "1.5-2ubuntu4" + "xserver-xorg-video-vmware-lts-quantal": "3:5" + "libjline-java-doc": "1.0-2" + "python-bsddb3-doc": "6.0.1-1build1" + "libplymouth2": "0.8.8-0ubuntu17" + "python-tk-dbg": "2.7.5-1ubuntu1" + "firefox-locale-cy": "28.0+build2-0ubuntu2" + "libpython-all-dbg": "2.7.5-5ubuntu3" + "libqt5dbus5": "5.2.1+dfsg-1ubuntu14" + "libsignon-qt-doc": "8.56+14.04.20140307-0ubuntu2" + "upower-doc": "0.9.23-2ubuntu1" + "postgresql-plpython3-9.3": "9.3.4-1" + "python-launchpadlib": "1.10.2+ds-2" + "python3-nose": "1.3.1-2" + "apt-utils": "1.0.1ubuntu2" + "python-psycopg2": "2.4.5-1build5" + "gir1.2-gee-0.8": "0.10.5-1ubuntu1" + "libdpkg-dev": "1.17.5ubuntu5" + "python-librdf": "1.0.16.1-1.1ubuntu1" + "thunderbird-locale-is": "1:24.4.0+build1-0ubuntu1" + "language-pack-en": "1:14.04+20140410" + "apache2-mpm-event": "2.4.7-1ubuntu4" + "cluster-glue": "1.0.11+hg2754-1.1build1" + "libgtkhtml-editor-4.0-dev": "4.6.6-2ubuntu1" + "libkjsembed4": "4:4.13.0-0ubuntu1" + "heimdal-dbg": "1.6~git20131207+dfsg-1ubuntu1" + "libffi6": "3.1~rc1+r3.0.13-12" + "libgl1-mesa-dri-lts-quantal": "3:5" + "nagios-plugins-common": "1.5-3ubuntu1" + "libtest-fatal-perl": "0.012-1" + "qtxmlpatterns5-doc-html": "5.2.1-3" + "ruby-session": "3.1.0-1" + "firefox-locale-zh-hant": "28.0+build2-0ubuntu2" + "siege": "3.0.5-1" + "gnome-calculator": "1:3.10.2-0ubuntu1" + "libgnome-bluetooth-dev": "3.8.2.1-0ubuntu4" + "libx32ncursesw5": "5.9+20140118-1ubuntu1" + "libcommons-collections3-java-doc": "3.2.1-6" + "libio-socket-ssl-perl": "1.965-1ubuntu1" + "ruby-test-unit": "2.5.5-1" + "xmltoman": "0.4-3" + "gir1.2-goa-1.0": "3.10.3-0ubuntu1" + "libmono-system-web-razor2.0-cil": "3.2.8+dfsg-4ubuntu1" + "cups-core-drivers": "1.7.2-0ubuntu1" + "erlang-ic": "1:16.b.3-dfsg-1ubuntu2" + "gir1.2-gdkpixbuf-2.0": "2.30.7-0ubuntu1" + "libmagick++-dev": "8:6.7.7.10-6ubuntu3" + "libtokyocabinet-dbg": "1.4.48-2" + "libverto-dev": "0.2.4-1ubuntu2" + "ruby2.0-dev": "2.0.0.484-1ubuntu2" + "language-pack-gnome-es": "1:14.04+20140410" + "libkutils4": "4:4.13.0-0ubuntu1" + "python-gnome2": "2.28.1+dfsg-1ubuntu2" + "libxcb-composite0-dev": "1.10-2ubuntu1" + "libjs-raphael": "2.1.0-1ubuntu1" + "libnet-domain-tld-perl": "1.70-1" + "libsub-exporter-progressive-perl": "0.001011-1" + "libgles1-mesa-dev-lts-quantal": "3:5" + "libsigsegv2": "2.10-2" + "language-pack-gnome-mk": "1:14.04+20140410" + "libchewing3-data": "0.3.5-4build1" + "mouseemu": "0.16-0ubuntu9" + "python-pyicu-dbg": "1.5-2ubuntu4" + "libmime-types-perl": "2.04-1" + "ruby-metaclass": "0.0.1-2" + "libqgsttools-p1": "5.2.1-0ubuntu5" + "libtk8.5": "8.5.15-2ubuntu3" + "srvadmin-webserver": "7.1.0-3" + "keymapper": "0.5.3-10.1build2" + "libhyphen0": "2.8.6-3ubuntu2" + "libreoffice-math": "1:4.2.3~rc3-0ubuntu2" + "libreoffice-l10n-af": "1:4.2.3~rc3-0ubuntu1" + "python-twisted-news": "13.2.0-1ubuntu1" + "libappindicator-dev": "12.10.1+13.10.20130920-0ubuntu4" + "libxpathselect-dev": "1.4+14.04.20140303-0ubuntu1" + "dpkg-cross": "2.6.11ubuntu1" + "libxfont1-dbg": "1:1.4.7-1" + "python3-simplegeneric": "0.8.1-1" + "gir1.2-clutter-gst-2.0": "2.0.8-1build1" + "gpgsm": "2.0.22-3ubuntu1" + "libkrad0": "1.12+dfsg-2ubuntu4" + "libpulse-mainloop-glib0-dbg": "1:4.0-0ubuntu11" + "libmono-system-json4.0-cil": "3.2.8+dfsg-4ubuntu1" + "libatkmm-1.6-1": "2.22.7-2ubuntu1" + "libkio5": "4:4.13.0-0ubuntu1" + "python-scour": "0.26-3build1" + "libegl1-mesa-lts-saucy-dbg": "3:5" + "python3-brlapi": "5.0-2ubuntu2" + "language-pack-gnome-an": "1:14.04+20140410" + "language-pack-mai-base": "1:14.04+20140410" + "postfix-doc": "2.11.0-1" + "libmng-dev": "2.0.2-0ubuntu3" + "libsexy2": "0.1.11-2ubuntu1" + "gitk": "1:1.9.1-1" + "pollinate": "4.7-0ubuntu1" + "python-unittest2": "0.5.1-1ubuntu1" + "libmpfr-dev": "3.1.2-1" + "libtasn1-6": "3.4-3ubuntu0.1" + "language-pack-gnome-ha": "1:14.04+20140410" + "baobab": "3.8.2-1ubuntu1" + "pkg-config": "0.26-1ubuntu4" + "libapache2-mod-auth-mysql": "4.3.9-13.1ubuntu3" + "libthai0": "0.1.20-3" + "ocaml-base-nox": "4.01.0-3ubuntu3" + "libopenvg1-mesa-lts-raring": "3:5" + "thunderbird-locale-pl": "1:24.4.0+build1-0ubuntu1" + "dosfstools-dbg": "3.0.26-1" + "libident-dev": "0.22-3build4" + "libsane": "1.0.23-3ubuntu3" + "libxcb-xv0": "1.10-2ubuntu1" + "language-pack-tg": "1:14.04+20140410" + "libkadm5srv-mit8": "1.12+dfsg-2ubuntu4" + "acpi-support": "0.142" + "python-crypto-dbg": "2.6.1-4build1" + "ghostscript-doc": "9.10~dfsg-0ubuntu10" + "libxcb-dri3-dev": "1.10-2ubuntu1" + "linux-headers-lowlatency": "3.13.0.24.28" + "thunderbird-locale-sr": "1:24.4.0+build1-0ubuntu1" + "language-pack-gnome-fa-base": "1:14.04+20140410" + "libextutils-helpers-perl": "0.021-1" + "libgd2-noxpm-dev": "2.1.0-3" + "libtest-most-perl": "0.33-1" + "gtk-doc-tools": "1.20-1ubuntu1" + "language-pack-ti-base": "1:14.04+20140410" + "gdb": "7.7-0ubuntu3" + "libsndfile1-dbg": "1.0.25-7ubuntu2" + "libfile-find-rule-perl-perl": "1.13-1" + "python-jsonpath-rw": "1.2.0-1build1" + "python3-all-dbg": "3.4.0-0ubuntu2" + "language-pack-mk-base": "1:14.04+20140410" + "hello-debhelper": "2.8-1" + "libcephfs-dev": "0.79-0ubuntu1" + "libxi-dev": "2:1.7.1.901-1ubuntu1" + "python-nose-doc": "1.3.1-2" + "libgnome-keyring0": "3.8.0-2" + "libjson-glib-1.0-0-dbg": "0.16.2-1ubuntu1" + "python-oops": "0.0.10-0ubuntu2" + "shotwell-common": "0.18.0-0ubuntu4" + "libmirprotobuf-dev": "0.1.8+14.04.20140411-0ubuntu1" + "xserver-xorg-input-wacom-lts-quantal": "3:5" + "python3-renderpm-dbg": "3.0-1build1" + "gir1.2-gudev-1.0": "1:204-5ubuntu20" + "lib32tinfo-dev": "5.9+20140118-1ubuntu1" + "libdb5.3-stl": "5.3.28-3ubuntu3" + "libnetpbm10-dev": "2:10.0-15ubuntu2" + "php5-cgi": "5.5.9+dfsg-1ubuntu4" + "neutron-plugin-openvswitch": "1:2014.1-0ubuntu1" + "texlive-latex-base-doc": "2013.20140215-1" + "libreoffice-ogltrans": "1:4.2.3~rc3-0ubuntu2" + "python3-gpgme": "0.3-0ubuntu3" + "language-pack-gnome-crh-base": "1:14.04+20140410" + "libgrail-dev": "3.1.0daily13.06.05-0ubuntu1" + "srvadmin-racadm4": "7.1.0-3" + "zeitgeist-datahub": "0.9.14-0ubuntu4" + "libclass-inspector-perl": "1.28-1" + "dh-exec": "0.12" + "libcupsimage2-dev": "1.7.2-0ubuntu1" + "libdmx1": "1:1.1.3-1" + "mcp-account-manager-uoa": "3.8.6-0ubuntu9" + "language-pack-gnome-id-base": "1:14.04+20140410" + "python-gi": "3.12.0-1" + "libxxf86dga-dev": "2:1.1.4-1" + "python-pyvorbis": "1.5-2ubuntu2" + "language-pack-gnome-fi-base": "1:14.04+20140410" + "libmono-webbrowser4.0-cil": "3.2.8+dfsg-4ubuntu1" + "unity-scope-manpages": "3.0+14.04.20140324-0ubuntu1" + "device-tree-compiler": "1.4.0+dfsg-1" + "libftdipp1": "0.20-1ubuntu1" + "language-pack-af-base": "1:14.04+20140410" + "language-pack-bho": "1:14.04+20140410" + "unity-control-center-dev": "14.04.3+14.04.20140410-0ubuntu1" + "libgnome2-dbg": "2.32.1-4ubuntu1" + "fonts-tlwg-typist": "1:0.5.1-3" + "icu-doc": "52.1-3" + "ivy": "2.3.0-3" + "language-pack-yi-base": "1:14.04+20140410" + "python-mutagen": "1.22-1ubuntu2" + "mono-utils": "3.2.8+dfsg-4ubuntu1" + "thunderbird-locale-fi": "1:24.4.0+build1-0ubuntu1" + "mysql-common": "5.5.35+dfsg-1ubuntu1" + "ibus-gtk": "1.5.5-1ubuntu3" + "libebook1.2-dev": "3.10.4-0ubuntu1" + "libreoffice-writer": "1:4.2.3~rc3-0ubuntu2" + "libwrap0-dev": "7.6.q-25" + "python-pkg-resources": "3.3-1ubuntu1" + "libcap2": "1:2.24-0ubuntu2" + "libfile-fcntllock-perl": "0.14-2build1" + "git-core": "1:1.9.1-1" + "gnome-session": "3.9.90-0ubuntu12" + "language-pack-gnome-csb": "1:14.04+20140410" + "pkg-php-tools": "1.11" + "python-openssl-doc": "0.13-2ubuntu6" + "xserver-xorg-video-trident-lts-saucy": "3:5" + "libreoffice-l10n-br": "1:4.2.3~rc3-0ubuntu1" + "libpst4": "0.6.59-1build1" + "libqt5xml5": "5.2.1+dfsg-1ubuntu14" + "php5-common": "5.5.9+dfsg-1ubuntu4" + "resource-agents-dev": "1:3.9.3+git20121009-3ubuntu2" + "libcommons-vfs-java-doc": "2.0-3ubuntu1" + "nginx-common": "1.4.6-1ubuntu3" + "libgles2-mesa-dbg": "10.1.0-4ubuntu5" + "libxcb-xvmc0-dbg": "1.10-2ubuntu1" + "libxpathselect1.4": "1.4+14.04.20140303-0ubuntu1" + "mksh": "46-2ubuntu3" + "nvidia-settings-updates": "331.20-0ubuntu8" + "language-pack-csb": "1:14.04+20140410" + "language-pack-gnome-ka": "1:14.04+20140410" + "libpangomm-1.4-dev": "2.34.0-1ubuntu1" + "libpcsclite1": "1.8.10-1ubuntu1" + "libudev-dev": "204-5ubuntu20" + "language-pack-gnome-gv": "1:14.04+20140410" + "ldm-ubuntu-theme": "2:2.0.47" + "libwebkitgtk-dev": "2.4.0-1ubuntu2" + "python-psutil": "1.2.1-1ubuntu2" + "libunique-dev": "1.1.6-4ubuntu2" + "libxaw7-dev": "2:1.0.12-1" + "mariadb-client-core-5.5": "5.5.38+maria-1~trusty" + "language-pack-gnome-et": "1:14.04+20140410" + "libgupnp-igd-1.0-doc": "0.2.2-1" + "gir1.2-unity-webapps-0.2": "2.5.0~+14.04.20140409-0ubuntu1" + "libbz2-1.0": "1.0.6-5" + "libmaa3": "1.3.2-2" + "network-manager-pptp-gnome": "0.9.8.2-1ubuntu2" + "libconfig++8-dev": "1.4.9-2" + "libpci-dev": "1:3.2.1-1ubuntu5" + "libxi6-dbg": "2:1.7.1.901-1ubuntu1" + "language-pack-as-base": "1:14.04+20140410" + "libao-common": "1.1.0-2ubuntu2" + "libsigc++-2.0-doc": "2.2.10-0.2ubuntu2" + "lib32objc-4.8-dev": "4.8.2-19ubuntu1" + "libencode-hanextra-perl": "0.23-2build3" + "hunspell-hu": "1:4.2.1-0ubuntu1" + "apparmor": "2.8.95~2430-0ubuntu5" + "g++-4.8-aarch64-linux-gnu": "4.8.2-13ubuntu1cross0.11" + "libclass-c3-xs-perl": "0.13-1build4" + "openssh-client": "1:6.6p1-2ubuntu1" + "isoquery": "1.7-1build1" + "ttf-tamil-fonts": "1:0.5.14ubuntu1" + "speex-doc": "1.2~rc1.1-1ubuntu1" + "nmap": "6.40-0.2ubuntu1" + "qtlocation5-dev": "5.2.1-1ubuntu2" + "whiptail": "0.52.15-2ubuntu5" + "erlang-base": "1:16.b.3-dfsg-1ubuntu2" + "libgphoto2-port10": "2.5.3.1-1ubuntu2" + "libsasl2-modules-gssapi-heimdal": "2.1.25.dfsg1-17build1" + "python3-pyqt4": "4.10.4+dfsg-1ubuntu1" + "x11-xserver-utils-lts-raring": "3:5" + "libservlet3.0-java": "7.0.52-1" + "monodoc-base": "3.2.8+dfsg-4ubuntu1" + "libfftw3-long3": "3.3.3-7ubuntu3" + "sip-dbg": "4.15.5-1build1" + "gir1.2-farstream-0.2": "0.2.3-1ubuntu2" + "libgcc-4.8-dev": "4.8.2-19ubuntu1" + "libhud-gtk1": "13.10.1+14.04.20140402-0ubuntu1" + "installation-guide-armhf": "20100518ubuntu10" + "python-pygments": "1.6+dfsg-1ubuntu1" + "ruby-fakefs": "0.4.2-2" + "libcrypt-openssl-random-perl": "0.04-1build6" + "python3-bsddb3": "6.0.1-1build1" + "brasero-common": "3.10.0-0ubuntu1" + "isc-dhcp-client-dbg": "4.2.4-7ubuntu12" + "libkeyutils-dev": "1.5.6-1" + "libsignon-glib1": "1.10daily13.06.25-0ubuntu2" + "libtotem-dev": "3.10.1-1ubuntu4" + "libtemplate-perl": "2.24-1.1" + "language-pack-sd": "1:14.04+20140410" + "libmono2.0-cil": "3.2.8+dfsg-4ubuntu1" + "policykit-1-doc": "0.105-4ubuntu2" + "python-openid": "2.2.5-3ubuntu1" + "libqt4-qt3support": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "libmono-db2-1.0-cil": "3.2.8+dfsg-4ubuntu1" + "pulseaudio-module-raop-dbg": "1:4.0-0ubuntu11" + "tk8.5-dev": "8.5.15-2ubuntu3" + "libavahi-client3": "0.6.31-4ubuntu1" + "libegl1-mesa-drivers-dbg": "10.1.0-4ubuntu5" + "libqt4-script-dbg": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "libsearchclient-dev": "0.7.8-1ubuntu2" + "htmldoc-common": "1.8.27-8ubuntu1" + "openprinting-ppds": "20140410-0ubuntu1" + "libpkcs11-helper1": "1.11-1" + "libtagcoll2-dev": "2.0.14-1" + "language-pack-gnome-os": "1:14.04+20140410" + "gir1.2-edataserver-1.2": "3.10.4-0ubuntu1" + "liboauth-dev": "1.0.1-1" + "libzeitgeist-1.0-1": "0.3.18-1ubuntu2" + "mdbtools-dbg": "0.7.1-1ubuntu1" + "language-pack-gnome-hi": "1:14.04+20140410" + "lib64atomic1-powerpc-cross": "4.8.2-16ubuntu3cross0.11" + "libmission-control-plugins-doc": "1:5.16.1-1ubuntu3" + "libgphoto2-6": "2.5.3.1-1ubuntu2" + "libksba-dev": "1.3.0-3" + "gstreamer0.10-plugins-good": "0.10.31-3+nmu1ubuntu5" + "libgee-0.8-dev": "0.10.5-1ubuntu1" + "libqt4-sql-mysql": "4:4.8.5+git192-g085f851+dfsg-2ubuntu4" + "libhunspell-dev": "1.3.2-6ubuntu2" + "libzeitgeist-2.0-dev": "0.9.14-0ubuntu4" + "python-xappy": "0.5-5" + "git": "1:1.9.1-1" + "libdbusmenu-gtk4": "12.10.3+14.04.20140319-0ubuntu1" + "libfdt-dev": "1.4.0+dfsg-1" + "libffi-dev": "3.1~rc1+r3.0.13-12" + "libsgutils2-2": "1.36-1ubuntu1" + "libbamf-doc": "0.5.1+14.04.20140409-0ubuntu1" + "libcpan-meta-perl": "2.133380-2" + "libjargs-java": "1.0.0-4" + "gfortran-doc": "4:4.8.2-1ubuntu6" + "libgnomeui-0-dbg": "2.24.5-3" + "language-pack-gnome-ug": "1:14.04+20140410" + "libgeronimo-jta-1.1-spec-java-doc": "1.1.1-3ubuntu1" + "python-chardet": "2.0.1-2build2" + "libcurl4-openssl-dev": "7.35.0-1ubuntu2" + "pulseaudio-module-lirc-dbg": "1:4.0-0ubuntu11" + "cdrkit-doc": "9:1.1.11-2ubuntu3" + "germinate": "2.16" + "firefox-locale-as": "28.0+build2-0ubuntu2" + "libreoffice-l10n-hu": "1:4.2.3~rc3-0ubuntu1" + "ubuntu-cloudimage-keyring": "2013.11.11" + "libapt-inst1.5": "1.0.1ubuntu2" + "libipa-hbac0": "1.11.5-1ubuntu3" + "libmirprotobuf0": "0.1.8+14.04.20140411-0ubuntu1" + "xserver-xorg-video-modesetting-lts-raring-dbg": "3:5" + "language-pack-en-base": "1:14.04+20140707" + "libaudit-common": "1:2.3.2-2ubuntu1" + "libgeronimo-jta-1.1-spec-java": "1.1.1-3ubuntu1" + "libkrosscore4": "4:4.13.0-0ubuntu1" + "libqt5sensors5": "5.2.1+dfsg-2ubuntu2" + "php5-xsl": "5.5.9+dfsg-1ubuntu4" + "dh-systemd": "1.14" + "bind9": "1:9.9.5.dfsg-3" + "libavahi-glib1": "0.6.31-4ubuntu1" + "libqmi-glib0": "1.4.0-1" + "libtimezonemap1-dev": "0.4.1" + "language-pack-gnome-mi-base": "1:14.04+20140410" + "libcairo2-dbg": "1.13.0~20140204-0ubuntu1" + "libxcb-sync-dev": "1.10-2ubuntu1" + "xserver-xorg-video-mga-lts-saucy": "3:5" + "bison-doc": "1:3.0.2-1" + "freeglut3": "2.8.1-1" + "libxcb-screensaver0-dev": "1.10-2ubuntu1" + "udhcpc": "1:1.21.0-1ubuntu1" + "unity": "7.2.0+14.04.20140416-0ubuntu1" + "gimp-help-en": "2.6.1-1" + "idle-python2.7": "2.7.6-8" + "python3-iso8601": "0.1.10-0ubuntu1" + "libm17n-0-dbg": "1.6.4-2ubuntu1" + "libpam-cracklib": "1.1.8-1ubuntu2" + "python-neutron": "1:2014.1-0ubuntu1" + "python-pil-doc": "2.3.0-1ubuntu3" + "libnl-cli-3-dev": "3.2.21-1" + "libpython3.4-dbg": "3.4.0-2ubuntu1" + "libleveldb-dbg": "1.15.0-2" + "qtdeclarative5-qtquick2-plugin": "5.2.1-3ubuntu15" + "signon-plugin-password": "8.56+14.04.20140307-0ubuntu2" + "cdbs": "0.4.122ubuntu2" + "pyppd": "1.0.2-1" + "libksba8": "1.3.0-3" + "transmission-dbg": "2.82-1.1ubuntu3" + "language-pack-gnome-st-base": "1:14.04+20140410" + "language-pack-ne-base": "1:14.04+20140410" + "poppler-data": "0.4.6-4" + "libasm-dev": "0.158-0ubuntu5" + "python-qt4-sql": "4.10.4+dfsg-1ubuntu1" + "libaprutil1-ldap": "1.5.3-1" + "libldns-dev": "1.6.17-1" + "libmythes-1.2-0": "2:1.2.2-1ubuntu2" + "unity-scopes-runner": "7.1.4+14.04.20140210-0ubuntu1" + "libgles1-mesa-dev-lts-saucy": "3:5" + "libqjson0-dbg": "0.8.1-3" + "pppconfig": "2.3.19ubuntu1" + "python-swift": "1.13.1-0ubuntu1" + "ruby-rspec-expectations": "2.14.2-1" + "ssh-import-id": "3.21-0ubuntu1" + "sharutils": "1:4.14-1ubuntu1" + "language-pack-gnome-ku": "1:14.04+20140410" + "language-pack-gnome-xh-base": "1:14.04+20140410" + "gettext": "0.18.3.1-1ubuntu2" + "libglewmx1.10": "1.10.0-3" + "libtdb-dev": "1.2.12-1" diff --git a/scripts/general_labsetup.sh b/scripts/general_labsetup.sh new file mode 100755 index 0000000000..73f0f273d9 --- /dev/null +++ b/scripts/general_labsetup.sh @@ -0,0 +1,89 @@ +#!/usr/bin/env bash +# Copyright 2014, Rackspace US, Inc. +# +# 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. +# +# (c) 2014, Kevin Carter + +set -e -u -v -x +LAB=${1} +# Go to rpc_deployment directory +pushd ../rpc_deployment + +# Build all of the containers +ansible-playbook -i inventory/${LAB}.yml \ + -e dinv=inventory/host_vars/${LAB}.yml \ + -e @inventory/overrides/${LAB}.yml \ + setup/build-containers.yml + +# Install Lab bits +ansible-playbook -i inventory/${LAB}.yml \ + -e dinv=inventory/host_vars/${LAB}.yml \ + -e @inventory/overrides/${LAB}.yml \ + setup/general_labsetup.yml + +# Build out HAProxy +ansible-playbook -i inventory/${LAB}.yml \ + -e dinv=inventory/host_vars/${LAB}.yml \ + -e @inventory/overrides/${LAB}.yml \ + setup/haproxy.yml + +# install all of Keystone +ansible-playbook -i inventory/${LAB}.yml \ + -e dinv=inventory/host_vars/${LAB}.yml \ + -e @inventory/overrides/${LAB}.yml \ + openstack/keystone.yml + +# install all of Glance +ansible-playbook -i inventory/${LAB}.yml \ + -e dinv=inventory/host_vars/${LAB}.yml \ + -e @inventory/overrides/${LAB}.yml \ + openstack/glance-all.yml + +# install all of Cinder +ansible-playbook -i inventory/${LAB}.yml \ + -e dinv=inventory/host_vars/${LAB}.yml \ + -e @inventory/overrides/${LAB}.yml \ + openstack/cinder-all.yml + +# install all of Heat +ansible-playbook -i inventory/${LAB}.yml \ + -e dinv=inventory/host_vars/${LAB}.yml \ + -e @inventory/overrides/${LAB}.yml \ + openstack/heat-all.yml + +# install all of Neutron +ansible-playbook -i inventory/${LAB}.yml \ + -e dinv=inventory/host_vars/${LAB}.yml \ + -e @inventory/overrides/${LAB}.yml \ + openstack/neutron-all.yml + +# Install All of Nova +ansible-playbook -i inventory/${LAB}.yml \ + -e dinv=inventory/host_vars/${LAB}.yml \ + -e @inventory/overrides/${LAB}.yml \ + openstack/nova-all.yml + +# Install All of Horizon +ansible-playbook -i inventory/${LAB}.yml \ + -e dinv=inventory/host_vars/${LAB}.yml \ + -e @inventory/overrides/${LAB}.yml \ + openstack/horizon.yml + +# Restart Everything +ansible-playbook -i inventory/${LAB}.yml \ + -e dinv=inventory/host_vars/${LAB}.yml \ + -e @inventory/overrides/${LAB}.yml \ + setup/restart-containers.yml + +popd diff --git a/scripts/inventory-manage.py b/scripts/inventory-manage.py new file mode 100755 index 0000000000..9036762694 --- /dev/null +++ b/scripts/inventory-manage.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python +# Copyright 2014, Rackspace US, Inc. +# +# 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. +# +# (c) 2014, Kevin Carter +import argparse +import os +import json + +import prettytable + + +def file_find(filename, user_file=None, pass_exception=False): + """Return the path to a file. + + If no file is found the system will exit. + The file lookup will be done in the following directories: + /etc/rpc_deploy/ + $HOME/rpc_deploy/ + $(pwd)/rpc_deploy/ + + :param filename: ``str`` Name of the file to find + :param user_file: ``str`` Additional localtion to look in FIRST for a file + """ + file_check = [ + os.path.join( + '/etc', 'rpc_deploy', filename + ), + os.path.join( + os.environ.get('HOME'), 'rpc_deploy', filename + ), + os.path.join( + os.getcwd(), filename + ) + ] + + if user_file is not None: + file_check.insert(0, os.path.expanduser(user_file)) + + for f in file_check: + if os.path.isfile(f): + return f + else: + if pass_exception is False: + raise SystemExit('No file found at: %s' % file_check) + else: + return False + + +def recursive_list_removal(inventory, purge_list): + for item in purge_list: + for _item in inventory: + if item == _item: + inventory.pop(inventory.index(item)) + + +def recursive_dict_removal(inventory, purge_list): + for key, value in inventory.iteritems(): + if isinstance(value, dict): + for _key, _value in value.iteritems(): + if isinstance(_value, dict): + for item in purge_list: + if item in _value: + del(_value[item]) + elif isinstance(_value, list): + recursive_list_removal(_value, purge_list) + elif isinstance(value, list): + recursive_list_removal(value, purge_list) + + +def args(): + """Setup argument Parsing.""" + parser = argparse.ArgumentParser( + usage='%(prog)s', + description='Rackspace Openstack, Inventory Generator', + epilog='Inventory Generator Licensed "Apache 2.0"') + + parser.add_argument( + '-f', + '--file', + help='Inventory file.', + required=True, + default=None + ) + + exclusive_action = parser.add_mutually_exclusive_group(required=True) + exclusive_action.add_argument( + '-r', + '--remove-item', + help='host name to remove from inventory, this can be used multiple' + ' times.', + action='append', + default=[] + ) + exclusive_action.add_argument( + '-l', + '--list-host', + help='', + action='store_true', + default=False + ) + + return vars(parser.parse_args()) + + +def print_inventory(inventory): + _meta_data = inventory['_meta']['hostvars'] + required_list = [ + 'container_name', + 'is_metal', + 'component', + 'physical_host', + 'tunnel_address', + 'ansible_ssh_host', + 'container_types' + ] + table = prettytable.PrettyTable(required_list) + for key, values in _meta_data.iteritems(): + for rl in required_list: + if rl not in values: + values[rl] = None + else: + row = [] + for _rl in required_list: + if _rl == 'container_name': + if values.get(_rl) is None: + values[_rl] = key + + row.append(values.get(_rl)) + else: + table.add_row(row) + for tbl in table.align.keys(): + table.align[tbl] = 'l' + table.sortby = 'component' + return table + + +def main(): + """Run the main application.""" + # Parse user args + user_args = args() + + # Get the contents of the system environment json + environment_file = file_find(filename=user_args['file']) + with open(environment_file, 'rb') as f: + inventory = json.loads(f.read()) + + if user_args['list_host'] is True: + print(print_inventory(inventory)) + else: + recursive_dict_removal(inventory, user_args['remove_item']) + with open(environment_file, 'wb') as f: + f.write(json.dumps(inventory, indent=2)) + print('Success. . .') + +if __name__ == "__main__": + main() diff --git a/scripts/labdelete.sh b/scripts/labdelete.sh new file mode 100755 index 0000000000..fa87774bfe --- /dev/null +++ b/scripts/labdelete.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +set -e -u -v -x +LAB=${1:-"uklab16_20"} +# Go to rpc_deployment directory +pushd ../rpc_deployment + +# Delete all containers +ansible-playbook -i inventory/${LAB}.yml \ + -e dinv=inventory/host_vars/${LAB}.yml \ + -e @inventory/overrides/${LAB}.yml \ + -e group=all \ + setup/destroy-containers.yml + +popd diff --git a/scripts/maas_remove.sh b/scripts/maas_remove.sh new file mode 100755 index 0000000000..e660e29ad0 --- /dev/null +++ b/scripts/maas_remove.sh @@ -0,0 +1,11 @@ +# Put your cloud account username in here +USERNAME='' +# Put your cloud account API Key in here +APIKEY='' +# Specify the string for which to match (on entity names) and remove all alarm/schecks for those enttities +STRING_MATCH='THIS WILL NEVER MATCH ONLY CHANGE THIS TO A SENSIBLE VALUE' + +# NB - use with caution, will remove all alarms/checks for enttities that are matched. +ENTITIES=$(raxmon-entities-list --username $USERNAME --api-key $APIKEY | grep $STRING_MATCH | awk '{print $2}' | cut -d = -f2) + +for e in $ENTITIES; do CHECKS=$(raxmon-checks-list --username $USERNAME --api-key $APIKEY --entity-id $e | grep Check | awk '{print $2}' | cut -d = -f 2); for c in $CHECKS; do raxmon-checks-delete --username $USERNAME --api-key $APIKEY --entity-id $e --id $c; done; done diff --git a/scripts/maassetup.sh b/scripts/maassetup.sh new file mode 100755 index 0000000000..2c66713577 --- /dev/null +++ b/scripts/maassetup.sh @@ -0,0 +1,16 @@ +set -x + +# Install all the things +pushd /root/ansible-lxc-rpc/rpc_deployment + # Setup the MaaS/Raxmon stuff + ansible-playbook -e @vars/user_variables.yml playbooks/monitoring/raxmon-setup.yml + + # Setup Local tests + ansible-playbook -e @vars/user_variables.yml playbooks/monitoring/maas_local.yml + + # Setup Global Tests + ansible-playbook -e @vars/user_variables.yml playbooks/monitoring/maas_remote.yml + + # Setup Dell OpenManage Tests (Uncomment this if you want to install those monitors) + ansible-playbook -e @vars/user_variables.yml playbooks/monitoring/maas_dell_hardware.yml +popd diff --git a/scripts/pw-token-gen.py b/scripts/pw-token-gen.py new file mode 100755 index 0000000000..eb7d8d6f24 --- /dev/null +++ b/scripts/pw-token-gen.py @@ -0,0 +1,200 @@ +#!/usr/bin/env python +# Copyright 2014, Rackspace US, Inc. +# +# 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. +# +# (c) 2014, Kevin Carter +import argparse +import datetime +import hashlib +import os +import random +import tarfile + +from Crypto import Random +try: + import yaml +except ImportError: + raise SystemExit('Missing Dependency, "PyYAML"') + + +class CredentialGenerator(object): + """Credential generator class. + + This class is simply a method to generate random secrets. This class will + NOT encrypt values rather it creates the values which will be used as + secrets within an application. The credential generator will return + strings in various sizes based on the requested secret type. + + There are four secret types that can be used within the class; `password`, + `token`, 'secret', and `key`. These types return variable lengths of data. + + password: 16 - 64 character string + secret: 16 - 64 character string + token: 64 - 72 character string + key: 24, or 32 character string (Needs to be AES compatible) + + Usage: + >>> generator = CredentialGenerator() + >>> token = generator.generator('token') + """ + def generator(self, pw_type): + """Generate new secret string. + + The generator method will check for a known method type and if found + generates a hashed string which is then routed to the appropriate + method. + + :param pw_type: ``str`` Type of secret to generate. + :returns: ``str`` + """ + if hasattr(self, '_%s_gen' % pw_type): + encoded_bytes = self._encode_bytes() + func = getattr(self, '_%s_gen' % pw_type) + return func(encoded_bytes=encoded_bytes) + else: + raise SystemExit('Unknown secrete type passed. [ %s ]' % pw_type) + + @staticmethod + def _random_bytes(): + """Returns 1024 random bytes of data.""" + return Random.get_random_bytes(1024) + + def _encode_bytes(self): + """Builds random strings based on random data. + + `_encode_bytes` will ensure that there's never an opportunity for + duplicate data. Once the bytes are generated, they are hashed using + SHA512 and the returned as a **hex** digest. + """ + random_bytes = self._random_bytes() + hash_obj = hashlib.sha512(random_bytes) + return hash_obj.hexdigest() + + def _password_gen(self, encoded_bytes): + """Returns ``str`` with a length between 16 and 64. + + :param encoded_bytes: ``str`` must be at least 64 charters long + """ + return encoded_bytes[:random.randrange(16, 64)] + + def _token_gen(self, encoded_bytes): + """Returns ``str`` with a length between 48 and 64. + + :param encoded_bytes: ``str`` must be at least 72 charters long + """ + return encoded_bytes[:random.randrange(64, 72)] + + def _key_gen(self, encoded_bytes): + """Returns ``str`` with a length of 24 or 32. + + Length restriction are required for key type secrets because of + requirements in AES. + + :param encoded_bytes: ``str`` must be at least 32 charters long + """ + return encoded_bytes[:random.choice([24, 32])] + + +def args(): + """Setup argument Parsing.""" + parser = argparse.ArgumentParser( + usage='%(prog)s', + description='Rackspace Openstack, Token Password and Key Generator', + epilog='Inventory Generator Licensed "Apache 2.0"' + ) + parser.add_argument( + '--file', + help='User defined configuration file', + required=True, + default=None + ) + parser.add_argument( + '--regen', + help='Regenerate all passwords', + action='store_true', + default=False + ) + + return vars(parser.parse_args()) + + +def main(): + """Run the main Application. + + This will open a file that was specified on the command line. The file + specified is assumed to be in valid YAML format, which is used in ansible. + When the YAML file will be processed and any key with a null value that + ends with 'password', 'token', or 'key' will have a generated password set + as the value. + + The main function will create a backup of all changes in the file as a + tarball in the same directory as the file specified. + + Command line usage has one required argument and one optional. The + argument ``--file`` is used to specify the file which passwords will be + generated within. The argument ``--regen`` is used to regenerate all + secrets within a file even if they were already set. + """ + all_args = args() + user_vars_file = all_args['file'] + user_vars_file = os.path.abspath( + os.path.expanduser( + user_vars_file + ) + ) + + with open(user_vars_file, 'rb') as f: + user_vars = yaml.safe_load(f.read()) + + changed = False + generator = CredentialGenerator() + for entry, value in user_vars.iteritems(): + if value is None or all_args['regen'] is True: + if entry.endswith('password') or entry.endswith('secret'): + changed = True + user_vars[entry] = generator.generator(pw_type='password') + elif entry.endswith('token'): + changed = True + user_vars[entry] = generator.generator(pw_type='token') + elif entry.endswith('key'): + changed = True + user_vars[entry] = generator.generator(pw_type='key') + + # If changed is set to True, this will archive the old passwords + if changed is True: + user_vars_tar_file = '%s.tar' % user_vars_file + print('Creating backup file [ %s ]' % user_vars_tar_file) + # Create a tarball if needed + with tarfile.open(user_vars_tar_file, 'a') as tar: + basename = os.path.basename(user_vars_file) + # Time stamp the password file in UTC + utctime = datetime.datetime.utcnow() + utctime = utctime.strftime('%Y%m%d_%H%M%S') + backup_name = '%s-%s' % (basename, utctime) + tar.add(user_vars_file, arcname=backup_name) + + with open(user_vars_file, 'wb') as f: + f.write( + yaml.safe_dump( + user_vars, + default_flow_style=False, + width=1000 + ) + ) + + print('Operation Complete, [ %s ] is ready' % user_vars_file) + + +if __name__ == '__main__': + main() diff --git a/scripts/uklabsetup.sh b/scripts/uklabsetup.sh new file mode 100755 index 0000000000..2cacc5eeca --- /dev/null +++ b/scripts/uklabsetup.sh @@ -0,0 +1,36 @@ +set -x +LAB=${1:-"uklab16_20"} + +function key_create(){ + ssh-keygen -t rsa -f /root/.ssh/id_rsa -N '' +} + +# Make the system key used for adding to containers +pushd /root/.ssh/ +if [ ! -f "id_rsa" ];then + key_create +fi + +if [ ! -f "id_rsa.pub" ];then + rm "id_rsa" + key_create +fi + +# Install all the things +pushd /root/ansible-lxc-rpc + # Ensure that the scripts python requirements are installed + pip install -r requirements.txt + pushd /root/ansible-lxc-rpc/rpc_deployment + # Base Setup + ansible-playbook -e @/etc/rpc_deploy/user_variables.yml playbooks/setup/host-setup.yml + + # Infrastructure Setup + ansible-playbook -e @/etc/rpc_deploy/user_variables.yml playbooks/infrastructure/infrastructure-setup.yml + + # HAProxy Setup (Only for NON-HW LB, NON Production installs) + ansible-playbook -e @/etc/rpc_deploy/user_variables.yml playbooks/infrastructure/haproxy-install.yml + + # Openstack Service Setup + ansible-playbook -e @/etc/rpc_deploy/user_variables.yml playbooks/openstack/openstack-setup.yml + popd +popd diff --git a/ssh/README.rst b/ssh/README.rst new file mode 100644 index 0000000000..b149f52845 --- /dev/null +++ b/ssh/README.rst @@ -0,0 +1,10 @@ +Example SSH config file +####################### +:date: 2013-09-05 09:51 +:tags: rackspace, lxc, openstack, cloud, ansible +:category: \*nix + + +Adding the option in your ssh config file will allow ansible to function without verifying host keys. +While this is great for testing and or use where you don't want to be prompted, I **would not** recommend +using this option in production. diff --git a/ssh/config b/ssh/config new file mode 100644 index 0000000000..b34c69cb05 --- /dev/null +++ b/ssh/config @@ -0,0 +1 @@ +StrictHostKeyChecking no \ No newline at end of file diff --git a/tools/README.md b/tools/README.md new file mode 100644 index 0000000000..29467ea7c1 --- /dev/null +++ b/tools/README.md @@ -0,0 +1,21 @@ +# Ansible-LXC-RPC Tools + +## install.py + +Installs or updates an Ansible-LXC-RPC installation. Does not install or verify pre-requisites. It is (intended to be) 100% idempotent and appears to be so. Can be used for production or testing environments. + +### Usage + +``` +Usage: install.py [OPTIONS] + +Options: + --haproxy / --no-haproxy Should we install Haproxy? Defaults to no. + --galera / --no-galera Should we install Galera? Defaults to no. + --rabbit / --no-rabbit Should we install RabbitMQ? Defaults to no. + --retries INTEGER Number of retries to attempt on an Ansible + playbook before giving up. + --help Show this message and exit. +``` + + Please note that the --haproxy option is for development/testing environments only. Our haproxy installation is __NOT__ intended for production use. diff --git a/tools/install.py b/tools/install.py new file mode 100755 index 0000000000..f3a6bc748f --- /dev/null +++ b/tools/install.py @@ -0,0 +1,301 @@ +#!/usr/bin/env python +# Copyright 2014, Rackspace US, Inc. +# +# 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. + +# Python Standard Libraries +import os +import sys +import time +import os.path +import logging +import functools +import subprocess +import logging.handlers + +# PIP Libraries +import click +import pexpect + + +# Configuration +playbook_cmd = "ansible-playbook %s -e @/etc/rpc_deploy/user_variables.yml %s" +restart_containers_sleep_seconds = 120 +color_codes_to_strip_from_log = [ + '\033[0m', + '\033[0;31m', + '\033[0;32m', + '\033[0;33m', + '\033[0;34m', + '\033[0;36m'] + + +class LXCNotInstalledOrNotRunnableError(Exception): + def __init__(self, error, output): + self.error = error + self.output = output + + def __str__(self): + return repr("%s: %s" % (self.error, self.output)) + + +class TooManyPlaybookFailuresError(Exception): + def __init__(self, playbook, retries): + self.playbook = playbook + self.retries = retries + + def __str__(self): + return repr([self.playbook, self.retries]) + + +class ChildProcessReturnedNonZeroError(Exception): + def __init__(self, errorcode): + self.errorcode = errorcode + + def __str__(self): + return repr(self.errorcode) + + +class StripColorCodesFormatter(logging.Formatter): + def format(self, record): + for code_to_strip in color_codes_to_strip_from_log: + record.msg = record.msg.replace( + code_to_strip, '') + return logging.Formatter.format(self, record) + + +def configure_logger(log_file): + logger = logging.getLogger('OpenStackInstaller') + + log_formatter = StripColorCodesFormatter( + "%(name)s: %(asctime)s - %(levelname)s: %(message)s") + + file_handler = logging.handlers.RotatingFileHandler( + log_file, maxBytes=104857600, backupCount=10) + file_handler.setFormatter(log_formatter) + file_handler.setLevel(logging.DEBUG) + + stream_handler = logging.StreamHandler(sys.stdout) + stream_handler.setFormatter(log_formatter) + stream_handler.setLevel(logging.INFO) + + logger.setLevel(logging.DEBUG) + logger.addHandler(file_handler) + logger.addHandler(stream_handler) + return logger + + +def execute(command): + """ + Executes a command, polling for output and printing the output as it runs. + """ + child = pexpect.spawn(command) + while True: + try: + child.expect('\n', timeout=None) + click.echo(child.before) + LOG.debug(child.before) + except pexpect.EOF: + break + child.close() + if child.exitstatus != 0: + raise ChildProcessReturnedNonZeroError(child.exitstatus) + + +def scriptdir(): + """ + Returns the directory where this script is located. + """ + return os.path.dirname(os.path.realpath(__file__)) + + +def rundir(): + """ + Returns the directory where our ansible playbooks should be executed from. + """ + return os.path.realpath( + os.path.join(scriptdir(), '../rpc_deployment')) + + +def get_container_name(containerstring): + """ + Returns the container name that contains containerstring. In the case + where there are multiple containers matching containerstring, returns only + the first one. Returns None for no match. + """ + try: + containers = subprocess.check_output( + 'lxc-ls', + stderr=subprocess.STDOUT).split('\n') + except subprocess.CalledProcessError as e: + raise LXCNotInstalledOrNotRunnableError(e.returncode, e.output) + except OSError as e: + raise LXCNotInstalledOrNotRunnableError(e.errno, e.strerror) + for line in containers: + if containerstring in line: + return line + return None + + +def print_status(haproxy, galera, rabbit, ansible_rundir, retries): + click.echo("Running ansible-lxc-rpc installer/updater.") + click.echo("About to install openstack.") + click.echo("Using %s as our ansible run directory" % ansible_rundir) + click.echo("Trying %s retries with each playbook" % retries) + if haproxy: + click.echo("We will install haproxy. Do not use this in a " + "production environment.") + else: + click.echo("NOT installing haproxy. This means you must have a " + "loadbalancer in place, configured separately.") + if galera: + click.echo("We will install galera.") + else: + click.echo("NOT installing galera. This means that you must " + "separately install and configure the database.") + if rabbit: + click.echo('We will install RabbitMQ.') + else: + click.echo("NOT installing RabbitMQ. This means you are " + "reponsible for installing and configuring it.") + + +def run_restart_containers_playbook(retries, ansible_rundir, galera): + run_playbook('setup/restart-containers.yml', retries, ansible_rundir) + LOG.debug("Sleeping %s seconds" % restart_containers_sleep_seconds) + time.sleep(restart_containers_sleep_seconds) + if galera: + # Restarting containers does not always restart galera, especially + # if it's an AIO. The system startup scripts do not have the bootstrap + # necessary for a single-node cluster. + run_playbook( + 'infrastructure/galera-startup.yml', retries, ansible_rundir) + + +def run_playbook(playbook, retries, ansible_rundir): + """ + Runs an individual playbook. Attempts multiple runs. + """ + extra_options = "" + success = False + attempt = 1 + os.chdir(ansible_rundir) + + playbook = os.path.join('playbooks', playbook) + os.environ["ANSIBLE_FORCE_COLOR"] = "true" + while not success: + playbook_full_cmd = playbook_cmd % (extra_options, playbook) + try: + LOG.info( + 'About to execute attempt %s of command: "%s"' % + (attempt, playbook_full_cmd)) + execute(playbook_full_cmd) + LOG.info('Successfully completed playbook "%s"' % playbook) + success = True + except ChildProcessReturnedNonZeroError: + attempt += 1 + pb_name = playbook.split('/')[-1].split('.')[0] + extra_options = "-vvvv --limit @/%s/%s.retry" % ( + os.path.expanduser("~"), pb_name) + os.environ["GIT_CURL_VERBOSE"] = "1" + if not success and attempt > retries: + raise TooManyPlaybookFailuresError(playbook, retries) + + +@click.command() +@click.option('--haproxy/--no-haproxy', + default=False, + help='Should we install Haproxy? Defaults to no.') +@click.option('--galera/--no-galera', + default=False, + help='Should we install Galera? Defaults to no.') +@click.option('--rabbit/--no-rabbit', + default=False, + help='Should we install RabbitMQ? Defaults to no.') +@click.option('--retries', + default=3, + help='Number of retries to attempt on an Ansible playbook ' + 'before giving up.') +def run_the_ansibles(haproxy, galera, rabbit, retries): + ansible_rundir = rundir() + print_status(haproxy, galera, rabbit, ansible_rundir, retries) + + run_p = functools.partial( + run_playbook, retries=retries, ansible_rundir=ansible_rundir) + run_p('setup/host-setup.yml') + run_p('setup/build-containers.yml') + run_restart_containers_playbook(retries, ansible_rundir, galera=False) + run_p('setup/host-common.yml') + + if galera: + galera_container = get_container_name('galera') + if galera_container is not None and os.path.isfile( + os.path.join('/openstack/', galera_container, 'galera.cache')): + run_p('infrastructure/galera-bootstrap.yml') + run_p('infrastructure/galera-config.yml') + run_p('infrastructure/galera-startup.yml') + else: + run_p('infrastructure/galera-install.yml') + run_p('infrastructure/galera-startup.yml') + + run_p('infrastructure/memcached-install.yml') + + if rabbit: + run_p('infrastructure/rabbit-install.yml') + + run_p('infrastructure/rsyslog-install.yml') + run_p('infrastructure/elasticsearch-install.yml') + run_p('infrastructure/logstash-install.yml') + run_p('infrastructure/kibana-install.yml') + run_p('infrastructure/rsyslog-config.yml') + run_p('infrastructure/es2unix-install.yml') + + if haproxy: + run_p('infrastructure/haproxy-install.yml') + + run_restart_containers_playbook(retries, ansible_rundir, galera) + + run_p('openstack/utility.yml') + run_p('openstack/openstack-common.yml') + run_p('openstack/keystone.yml') + run_p('openstack/keystone-add-all-services.yml') + run_p('openstack/keystone-add-users.yml') + run_p('openstack/glance-all.yml') + run_p('openstack/heat-all.yml') + run_p('openstack/nova-all.yml') + run_p('openstack/neutron-all.yml') + run_p('openstack/cinder-all.yml') + run_p('openstack/horizon.yml') + run_restart_containers_playbook(retries, ansible_rundir, galera) + + +LOG = configure_logger('/var/log/rpc-openstack-installer.log') + + +def main(): + try: + run_the_ansibles() + except TooManyPlaybookFailuresError as e: + LOG.critical( + "Failed running playbook '%s' %s times. Aborting..." % + (e.playbook, e.retries)) + sys.exit(50) + except LXCNotInstalledOrNotRunnableError as e: + LOG.critical( + 'Failed running lxc-ls. ' + 'Got return code %s and output "%s"' % (e.error, e.output)) + sys.exit(51) + + +if __name__ == '__main__': + main()