Tumblelog by Soup.io
Newer posts are loading.
You are at the newest post.
Click here to check if anything new just came in.

April 19 2017

April 06 2017

Ansible: Using host info on other hosts

Problem: you want to use data for one set of hosts to configure something on a different set of hosts. Specifically, there are some values in the host variables of the first group that you need to collect and use on one or more other hosts.

<!-- more -->

If you recall my previous post on registering multiple results in a variable, you’ll remember I had a YAML data structure that described the set of database instances on a host:

1
2
3
4
5
6
7

db_instances:

  instance1:

    shmmem: 8G

    uid: 6953

  instance2:

    shmmem: 16G

    uid: 6954


This is the same data structure, but with an extra field shown: the ‘uid’ value is the hardcoded user ID of the instance user account (which is named after the instance). Each database instance runs under a dedicated account (to which we apply the project resource limits previously covered). So on the host, we create user accounts based on the information for each instance:

1
2
3
4
5
6

- name: create DB instance user

  user:

    name: "{{ item.key }}"

    uid: "{{ item.value.uid }}"

    comment: "{{ item.key }} database user"

  with_dict: "{{ db_instances }}"


This is fine, but each of these hosts is actually a Solaris virtual zone running on one of a set of physical, clustered nodes. In Solaris by default, listing the processes in the global zone (the top level, ‘parent’ OS instance for the physical server) also shows all the processes running in the local zones attached to that node but crucially, the owning user IDs for those processes will be displayed numerically because those users don’t exist in the global zone’s namespace. The database administrators find this confusing and ugly; to fix it, we’ll need to create the same accounts with the same UIDs (for all the instances on all hosts) in the global zones. (Note that each instance UID is unique across the entire cluster.)

To achieve this in Ansible, we’ll need to access the db_instances data for all the database hosts, but for use on a different set of hosts. Normally, host variable data is considered specific to that host. My first thought was to reference it via the special hostvars dictionary. That turned out to be a non-starter, since I’d need to loop through the hostvars entries for all the relevant hosts within another loop applying that to the list of global zones. Ansible’s task loops are quite extensive but the more complex ones, such as with_nested, operate on lists rather than dictionaries, and both the structures in question here are of the latter form. (This is a good reason to sometimes prefer the former for structured data even when the latter feels more appropriate - there are more methods available to parse and iterate lists than dictionaries.)

It was then that I discovered playbook delegation, which allows you to run a task intended for the current host in play against a different host altogether. (One of the things I really like about Ansible is that one can always find a suitable filter or module to achieve even quite complex tasks that initially appear insurmountable. Studying the documentation in detail helps, but quite often some facets are only referenced in forum examples and ServerFault answers.)

The example use for delegation given in the manual is to update a central load balancer configuration when a backend node is added or removed. However, I can use it here to run the user creation task against the global zones as well as the database host zone. Here’s another task to do this:

1
2
3
4
5
6
7
8
9
10
11
12
13

- name: create dummy accounts for all database instance users on nodes

  delegate_to: "{{ item.0 }}" # run task on node, not this host

  user:

    name: "{{ item.1 }}"  # instance name (user name)

    uid: "{{ db_instances[item.1].uid }}" # instance UID value

    comment: "{{ item.1 }} database user"

    shell: '/bin/false'

  # run in nested loops:

  # for each <global_zone>:

  #   for each <db_instance>:

  with_nested:

    - "{{ global_zones }}"

    - "{{ db_instances.keys() }}"


It’s critical to note that this task is run against each database host. global_zones is a list of the hostnames for all the nodes; it’s actually taken from an existing Ansible host group, extracted from the groups dictionary. Within a nested loop, we delegate the user creation task to each global zone in turn, looping through the database instances defined for the host and creating ‘dummy’ accounts based on the instance name and assigned UID as before. These dummy accounts have an invalid shell (and could also share a common home directory), since they shouldn’t be used for login or program execution on the global zones; they’re purely to give the ps command something to map numeric UIDs against sensibly.

We loop over the defined instances by extracting the names of the keys from the db_instances dictionary; the keys() operator does this (and is a good example of a feature that is discussed in forums but not covered in the Ansible documentation, since it’s actually a Python dict method inherited from the underlying implementation). Within the loop, we can then use this instance name (assigned to item.1) to look up the uid value in the dictionary.

This solution works well, but one aspect of it makes me slightly uneasy. The use of delegation appears to break the (informal) contract with the Ansible user that a role is normally expected to operate (i.e. change state) only on the host(s) to which it is applied. In this case, we apply the role containing the task to one set of hosts (the database zones) but it actually creates users on a second, unrelated set of hosts (the global zones). True, the global_zones list has to be explicitly defined and passed across, but it feels somewhat non-intuitive. Additionally, a limited set of hosts specified via the --limit option to ansible-playbook will not work as might be expected in this case, since it won’t affect the global_zones list. (I did try using the intersection of this list with the ansible_play_hosts list, but the latter only contains the name of the host currently executing the role at any one time rather than all the hosts in scope; we need an ansible_limit_hosts magic variable too.)

In Ansible terms, it would be more typical if the role were applied to the global zones and referenced data from the database zones - but that gets us back to trawling through hostvars (oh, if only I hadn’t chosen a dictionary!) What I’ve done here isn’t against the letter of our coding standard, but it arguably violates the spirit of the standard (which is that tasks and roles should be as simple and transparent in their use as possible) significantly. (As I don’t kowtow religiously to that spirit anyway, I settled for adding a bold warning to the README - caveat emptor!)

April 05 2017

bigbubbles

Theresa May's supreme sacrifice?

I keep asking myself, "What's May's real strategy here?" Like most successful politicians, she's ambitious and opportunistic. It may be her only true competence is at pretending competence (as opposed to her actual record as Home Secretary), but I don't believe she's stupid. As a (former) Remainer, she's familiar with the arguments in favour of the EU because she used some of them herself during the referendum campaign (during her rare moments of visibility).

She must therefore know just how hopeless and fantastical the case for Brexit is. She's not an ideologue in the "unicorns and fairy dust will make it all wonderful" sense that oblivious zealots like Iain Duncan Smith and Liam Fox subscribe to. Some time ago, a rumour arose that May knew no deal was realistically possible that would satisfy both the Leave contingent and the EU, given the vast philosophical gulf between the two, and that her real strategy was therefore to make untenable demands before walking out of negotiations and putting the blame on the EU, while letting Britain crash out on WTO terms anyway. Now that the full horror of that scenario has been clearly spelt out by both a parliamentary committee and numerous economists and business people, that no longer seems feasible - hence the fact that some of the more extreme and rose-tinted rhetoric around this possibility has lately dried up or been moderated. Even if it were blamed on the EU, the resultant disaster would attach itself to May's government and the economy would still be wrecked.

I therefore wondered if, as a secret Remainer at heart, her strategy was to go full tilt towards hard Brexit, encountering and smashing into as many of the practical obstacles as possible early on so that the implications would become starkly obvious well before the two year deadline - rather like a driver heading for a brick wall and still pressing the accelerator down in the expectation that their passengers would demand or force a swerve away at the last minute. "Oh well, there you are. We did our best to implement Brexit but the state of our nosediving economy and the brutal realities mean it would be suicide." But again I suspect, having marched everyone up to the top of the hill, May would find herself carrying the can for the belated retreat after talking such a strong game earlier on.

Then again, is that still her plan? At the moment, May is vulnerable to the right wing of her party. If she falters, if she appears less than fully committed to Brexit at any point, she knows she would be deposed or forced to resign and replaced by one of the crazed ideologues who believe, like Gove, that we can simply tear up all existing treaties and agreements and walk away with no commitments immediately - which would be terminal to the nation's standing in the world, let alone Europe. She faces no true opposition to put the brake on things; the only way this process stops now is if the electorate comes to realise how badly it's going to go and begins screaming about it - i.e. the much-maligned 'will of the people' changes. By driving Brexit relentlessly until, with only the figleaf of a bad deal on offer and employers stampeding for the last helicopter off the embassy roof, it stands exposed as the utter shitshow it would be, she might not only trash the whole idea of leaving the EU but also the careers of Johnson, Fox and Davies, her current most likely rivals, along with that of anyone else who had been associated with the venture. This would leave the way for a more moderate successor who could, presumably bowing to general public demand by this point, withdraw the Article 50 notification within the deadline and declare the entire project a huge, misbegotten mistake (with the opprobrium to be heaped on those who had apparently "misled" the voters). Yes, that means Theresa May sacrifices her entire political career and legacy but, given the corner she's already painted into, can she realistically expect to get out of this mess covered in glory anyway? She would at least know she had been true to her country and to her Remain heart.

I mean, come on, if you were serious about striking a bunch of lucrative global trade deals to fill an imminent gaping hole in the national finances, you wouldn't put posterboy moron Liam Fox and pound shop Pennywise-the-clown Boris Johnson in charge, would you?

...Hoo boy, let's file this one under "bonkers Remainer conspiracy fantasy", shall we? But I'd be interested to hear any better theories as to what May's underlying strategy is, because at the moment her actions lack all rational expectation of success and, for all her faults, I don't believe her to be prey to this degree of self-delusion.

April 03 2017

bigbubbles

The state of us

Almost a week on from Trigger Day, the Article 50 notification, it appears to me that Brexit divides us into three:
  • Ardent, frothing Leavers: Mostly represented on Twitter and in the media, as they give good copy even if most of it is crazed, paranoid fantasising and provocative rants. Complete suckers for all the "return sovereignty, global free trade, do what we like, war with Spain" British imperial mythos. As they're so vocal and the media is egging them on, Theresa May is minded to keep them onside but despite this, they have little actual influence on events or, as it's known elsewhere, reality. RT and respond with facts as much as you like, they are immune to evidence or counterarguments, scornful of expertise and proudly ignorant. When the true Brexit nuts argue that even if it completely ruins the economy, it will be worth it for the figurative 'freedom' it gives us, you know they will never be argued out of this position rationally. Still unable to provide one single, clear, positive benefit of Brexit - but to them, that's just Not The Point.
  • Desperate Remainers: Also heavily represented on Twitter but less so in the media because uncontroversial facts are dull and nobody ever rallied behind a cry of "Let's leave things as they are!" As zealous as the Ardent Leavers but with more evidence on their side, although nobody else is listening. Liable to accept the worst case scenario of every little detail or setback, and convinced that every outcome can only be a bad one - and that Leave extremists will doom us all every time they fart on about kicking all the foreigners out or bringing back shillings and hanging. (Note: there is no other kind of Leave voter to a Remainer, because those are the only visible ones in social and news media.)
    Not wishing to diminish their points here, because the only thing I am sure of after reading a lot of Brexit articles is that, if you believe any aspect of it is remotely straightforward or simple, you simply haven't understood it. Brexit is fractal: every closer look reveals deeper levels of complexity and chaos.
  • The disinterested majority: Whether they voted Leave or Remain, it's all about as fascinating as most politics to them, which is to say not remotely. "We had the vote, now we do the thing that the result said we should do," as usually happens after general elections and similar. They generally realise that Farage is as shifty as any politician, although May looks competent (at a casual glance) so they're sure it will probably be alright in the end even if we don't actually leave the EU after all this (because "politicians do what they like anyway"). Won't reconsider any of this until it has a direct, tangible impact on their lives in some fashion and it is clear that Brexit was the cause (e.g. companies say that higher prices are due to Brexit; understaffing due to reduced migrant workforce; employer tells them they're losing their job because of European relocation; etc.). At this point, they will probably expect it all to be reversed as a matter of pure pragmatism because what kind of crazy idiot would press on with an evident disaster? Leavers are hoping this point will only be reached after March 2019; Remainers are hoping things become a lot worse a lot more quickly than that and to be fair, that's probably the only way we can now avoid an actual exit from the EU.

Entirely hypothetical thought experiment: if there was a military coup in the UK tomorrow, and a seemingly level-headed army general deposed the government and seized power, saying "We're not going to war with Spain, we're not going to destabilise the economy, we're going to continue to honour all existing treaties and alliances because Brexit is insane", how would you feel? (N.B. The last time we came anywhere close to a coup, it was a slightly ludicrous but sincere right wing plot against a left wing administration.) Weird times when one can sympathise with a 17th century peasant optimistically hoping that Cromwell's overthrow of the king may make your life better (narrator: "It didn't").

    March 16 2017

    March 15 2017

    Ade shared a quote
    5616906
    With Bruford, the album was One Of A Kind. All-instrumental, it possessed the kind of focused vision that allowed for no ifs or buts. With the unnerving confidence of youth, it had This Is What We Do And This Is How We Do It stamped all over it.Bill Bruford

    March 07 2017

    March 06 2017

    March 05 2017

    March 04 2017

    March 03 2017

    Older posts are this way If this message doesn't go away, click anywhere on the page to continue loading posts.
    Could not load more posts
    Maybe Soup is currently being updated? I'll try again automatically in a few seconds...
    Just a second, loading more posts...
    You've reached the end.

    Don't be the product, buy the product!

    Schweinderl