 All right, shall we get started? Yeah. OK, so to start off, my name's Michael. I work for Rackspace. I can't answer questions about a public cloud or anything like that because I work solely on OpenStack, the open source project, which is kind of cool. But it's nice that they fund my work. Now the point of this talk is getting code into OpenStack is actually kind of complicated. Mostly that's because it's a fairly large project. There's hundreds of developers, hundreds of thousands of lines of code. And to help that scale, we've got a bunch of process around how we do things. So for example, when you submit code, it goes for a whole bunch of automated tests before a human even looks at it to verify that it meets our style guide. Doesn't cause the smoke to come out, that kind of stuff. So getting set up for all of that is kind of complicated. And that's what I want to cover here. One of the reasons I want to cover it is because I don't know if you've noticed on the exhibition floor, but recruiting for OpenStack developers is a really big deal. There's a huge demand for it. And I think ultimately we need to grow the pool of developers because kind of borrowing developers off each other is not sustainable long term. So what I'm hoping is if I do talks like this, we'll end up with more developers over time. So there's a whole bunch of stuff you need to do before you can send off that first commit. And that's what we're going to cover in the talk. We have to sign up for some accounts. We need to assign copyright to the foundation. And then we need to set up a development environment with the right tools and that kind of stuff. So that's pretty much the agenda for today. But before we do that, I want to go off on a tangent for a second and say, I'm a Nova and Oslo core reviewer. This term causes a lot of confusion, so I just want to briefly try and explain what it means. Specifically, I'm a core reviewer, not a core developer. So the title that you hear people say, oh, I'm a Nova core, or he's an overcore, or she's an overcore, or whatever, it's not about me having written more of Nova than someone else. It's not about me having done anything particularly amazing, although we do expect core reviewers to have made a significant contribution to the code. What it actually means is that I've read more code than most people. So the core review groups are the people who can approve code going into the code base that users end up using. The groups tend to be fairly small. Nova has about 20 of us worldwide. And so our role is to read. We read every single change set, and two of us have to say yes before it hits the code base. So it's all about maintaining consistent style, and making sure things are tested, and making sure people have thought through the implications of their decisions. It's not about me being particularly smart, or anything like that. So the first thing you need to do is you need to sign up for a Launchpad account. Launchpad is a web service run by Canonical, and we use it for things like bug tracking, blueprints, which are our design documents, some mailing lists, some groups, stuff like that. It's absolutely mandatory that you have a Launchpad account, because all of our single sign-on stuff, everything else, hooks off of Launchpad. So you just can't avoid it. So each OpenStack project, like I said, has bugs and blueprints. We also have, each project has a page on Launchpad, which links to all of that stuff. So you don't need to remember a million URLs. You just need to remember the one overpage and go from there. Once you've signed up for your Launchpad account, then all the other systems will start to work magically for free. So it's kind of nice. So you really, really do need a Launchpad account. Luckily, they're not very hard to create. If you go to Launchpad.net, in the top right, there's a sign-in register link. You just click on that. I'm going to assume that you know how to fill out an account sign-up web form. I'm not going to lecture you on the topic. The next thing you need to do is you need to sign up for Jarrett. Jarrett is our online code review system. It was originally written for the Android project, but we've tweaked it a little. And by we, I mean the infrastructure group, I don't work on. And again, if you go to review.openstack.org, there's just a sign-up link at the top right. Now, like I said, Jarrett is the online code review system. So it's where once you've written your code and you submit it for review, the cause and other people are going to start reading it and commenting on it and looking at diffs and all that kind of stuff. To interact with Jarrett, you need to upload an SSH key, because the protocol Jarrett uses for everything is SSH. Now, that can be a key you generate, especially for this, or it can be a key you've used before. It kind of depends on how you feel about security, I suppose. But specifically, make sure you only upload the public key, right? We have no need for your private key. We don't want it. In fact, it won't work. So in Jarrett, if you hit the set, once you've logged in, the top right link becomes a settings link. And then, so you hit that. And you end up on a page with SSH keys on the left. And so you can just upload it. It's just a block of text in a text box. It's not very exciting. And then if you want to test it, you can SSH to Jarrett and start talking to it. Now, the only catch is Jarrett doesn't listen on the system SSH port. So you need to remember to have some SSH config, or you're going to be really confused. I put this in because I have wasted many minutes of my life trying to work out why Jarrett wasn't working. It's because I'm talking to the wrong SSH server. Now, to take that aside for a second, Jarrett is kind of cool. So this command line at the bottom here, SSHs to Jarrett and says, give me all the code reviews for NOVA as JSON. And what you get is just this big stream back of everything that's currently happening on the NOVA project in an easily parsable format. So that's kind of cool. So I have a bunch of scripts, for example, that will let me know when files I've previously modified are coming up for review again. So I can pay more attention, all of that kind of stuff. You can start to automate your world a little bit. One of the other NOVA cores actually does all his reviews through Jarrett as well, sorry, through this SSH interface. He doesn't use the website at all. That's a little bit awesome for me. So I tend to use the web interface. You also need to give the OpenSnack foundation a license to your copyright. So you do that by signing the copyright license agreement, which is, again, if you go to settings, it's a thing on the left in Jarrett. Yes, sorry. So the question is, is Jarrett always on that weird port number? And the answer is yes. And in fact, there was a thread a couple of weeks ago. People with corporate firewalls might have problems with that, but we don't have a good solution to work around that at the moment. So if you see documentation online that says, go to Rackspace and use this echo sign thing to sign the CLA, that's a fib because it's old. These days, you just do it in Jarrett. It's really easy. You say new copyright agreement. There's some text you read. You agree to it. You click OK. So it's not too bad. It gets a little bit more complicated if you're employed to work on OpenSnack, or if you have a contract with your employer that says they own everything you do. At that point, your employer needs to sign a copyright agreement as well, which is kind of outside the scope of this talk. It's documented on the OpenSnack wiki, but it's not too bad. Again, it's like a human reads a web page and clicks yes. If you're a US government employee, for reasons I can't explain because I've never been one, it's more complicated. Come and talk to me after if you work for the US government. There's some mailing lists you should be on. Now, I said we had some mailing lists on Launchpad. That's mostly historical. We've been moving them progressively over to the foundation now that we have one. But to talk about the foundation mailing lists server first, you need to be on the Announce and dev mailing lists. I think that's pretty much mandatory. I would be surprised if there was a developer who wasn't on the dev mailing list, for example, because it's how we talk about how should something be designed or what dependencies are OK and all of that kind of stuff. You'd be confused by what we were doing if you weren't. And then there's some other lists that are useful but not mandatory. For example, the foundation list or the operators list. If you're running OpenSnack, I would recommend that you be on the operators mailing list. It's not as active as I'd like it to be, but I'm hoping to make it more active by tricking you into joining it. So that's where operators are discussing stuff like, what's my deployment look like versus yours? How did that work out for you? What bugs are you seeing? How can I get around this problem that I've just encountered, all of that kind of stuff? Theoretically, I guess if you had a vendor who sold you OpenSnack, you can talk to your vendor as well. But if you're after peer advice, it's a good place to be. And then there's one mailing list left on Launchpad, and that's the OpenSnack list, which is moderate levels of traffic. It's not too bad. But notice that there's a tilde before OpenSnack to get to the list. And I would recommend joining that one as well, because, for example, when they announce early signup for developers for the summit and stuff like that, that's where it's going to go to. So you want to be on that list as well. Because we love talking and email isn't enough, there's also IRC channels. So if you have a quick question about, hey, how does Blar work, I have this weird test failure and a bit of code I didn't even touch, IRC is the right place to go. And so there's a bunch of channels. This is only a few of them. Pound OpenSnack is just general user questions. Pound OpenSnack dev is developers talking to each other. And then Pound OpenSnack infra is the team that runs all the automated testing. So if you had a problem where, for example, the tests pass on your machine, but not in the cloud, they're the people who can help you through that. And then the meeting channels are cool. All of the meetings for the projects are done in public on IRC. And there's, again, a Foundation Wiki page that lists what time of day you could go to each of these meetings. And there's nothing stopping users or fresh developers or whatever coming along and watching or interacting or whatever. That's totally cool. I guess hypothetically, if it left us in a situation where we couldn't get any actual development discussion done, that might be a problem. But that hasn't been a problem so far. And then each project also has a project specific channel. But people will tend to tell you about those as required. So if you ask a really specific question on the dev channel, they might say, hey, look, actually, you should go and ask that on the Nova channel. So that's a lot of setting stuff up before you've even written a line of code. And like I said, I think that's really about having a lot of developers and a lot of code. And so we've wrapped a lot of process around it. But I don't think it's a particular barrier. I think realistically, you could be signed up for everything you wanted in 20 or 30 minutes. And you really should do that first. So setting up a development environment. I'm going to assume Ubuntu 12.10, even though I'm using a Mac, because it's the environment I use. You can develop on Macs. You can develop on Fedora, whatever. It all works. It's just I don't want to give you bad Fedora advice because I don't actually do that. So if this stuff doesn't work for you, send me an email and I'll find someone who can help you out. So first off, you need Git and PIP. PIP is the way we install Python software that's not packaged by the OS. This matters more to developers than deployers, because we'll add dependencies, and then we'll give the distros a heads up that they need to package it. So we're often running in front of the distro. Specifically, you also need PIP because you need TOX, which is the build slash test system that we're using. So first off, install Git and PIP, and then install TOX. And then just trust me and type this big app to get line. Now, all it's installing is build dependencies, promise. It's not too scary. But yeah, you need things like Python. Obviously, you need MySQL and Postgres bindings, that kind of thing, before the unit tests will pass. And then we can finally fetch some code. So that's kind of exciting. Get reviews there, man. Dude, it's in the list. It's packaged now. So then if you've used Git before, this bit should not be surprising. You can just go off and clone the source code, and there it is. Because we use TOX, all of the unit tests, if you just wanted to grab the code and run the unit tests as a first step, that would be a reasonable thing to do. You need to know the right TOX command line, but I'll show you that later on. The other thing is that we do most of our development in branches. So for example, if I'm fixing a bug, the very first thing I do is create a topic branch, which is generally bug slash the bug number. Or if I was working on a blueprint, it would be a descriptive string that's probably the name of the blueprint. There's no actual particular requirement for that. But as you get more and more involved, you'll find that you have lots of branches. So I have a couple of hundred of them. And so starting off with good habits is going to make it easier later. So I promise to actually fix a bug. So cheating a little bit, this is a bug I actually fixed last week, I think it was. But we're going to walk through it and talk about the process and what needed to be done. So this person has a problem where he tried to live my great an instance, and it failed. And he got a weird error message back. He didn't get the error message he expected. Well, I guess you don't really expect an error message at all. He got a stack trace back instead. And so he's filed this bug. Now, someone has come along and they've set the importance to medium. It's an embarrassing bug. And then it's assigned to me, which means that I'm working on it. In fact, this one's in the fixed committed state, which means I've sent off a code review. It's been accepted through the review process and merged into trunk. The step after this is fixed release, which is when, say, grizzly ships or something like that. You can also see that Vish is working on this. So developers are generally working in trunk. So the thing that will eventually be called Havana. And so when we fixed this bug, we were like, oh, well, you know what? This one's pretty cut and dried. People using grizzly are going to be angry if they experience this bug. So it's been backported to grizzly, which is what you see happening there. Now, some bugs you'll see get backported to a whole series of releases. But it kind of depends on the bug. So security bugs, for instance, are going to get more backport than something else. Now, the bug report also included a stack trace. Now, it's in completely clear what the problem is now. It's actually more readable than I thought it would be. So because what's happened here is the client has done something, or requested something be done. It's made an RPC call, and then Nova Compute has experienced the problem and passed the error back over RPC. So there's actually a whole bunch of completely irrelevant stack trace here from the RPC system, which is very proud that it executed some code. And the relevant line is this last line. So here we see that a file called NovaVertLibVert driver.py in a method called pre-live migration. We used a key in a dictionary that doesn't exist, which is slightly embarrassing. But I promised to do this as performance art. So you can't laugh at me while I learn how to use a computer. I do not know why it's resized my virtual machine. Don't do that. Oh, really? It's going to be one of those days. Oh, there we go. It's a really big Emacs. Never do a live demo. We experienced an error. Let's pretend that didn't happen. Give me one second while I rearrange my windows. So this is my local checkout of the Nova source code. And you can see here that I actually have a branch for this bug already checked out. You guys can read that font, yeah? That's good enough? Cool. So before I said the stack trace was for a file called NovaVertLibVert driver.py. Really proud I remembered that. So the Nova code is broken up into sections. Vert is the hypervisor drivers. Vert LibVert is the LibVert hypervisor driver, which is generally used by people using KVM, although there are other hypervisors that LibVert supports. And then driver.py is just the driver interface layer that kind of normalizes the behavior of the hypervisors to what OpenStack expects. So if I didn't have such a huge Mungus window, I don't even know where that one went. I said this was performance art. Can we read that font? No? We can probably emigrate the font because Emacs is cool. Is that better? Cool. So this is pre-live migration. Now the reason I'm not too fixated on the line of code, like the exception message had a line of code, right? It said line number blah is the problem. The reason I'm not fixated on that is because it's going to be different. Some vendors have patches they apply before they ship the code, et cetera. So line number is not the world's most helpful piece of information. But what pre-live migration is doing is it's trying to work out if it can migrate this instance to another compute host. But that's actually irrelevant for the problem, which is, oh, I've made a mistake, actually, because this is performance art. What I'm showing you is post fix, which isn't actually going to help. Actually, it's because it gets in the wrong directory. This is how we're going to fill 40 minutes. Sorry, I need to show you the commit before I fixed it to show you the error because the error doesn't exist anymore. So let's just check out the commit before that. And then if we go back to Emacs and say, show me that again. So here is the error. So what the method was trying to do was it was trying to write a log message. The log message involves a string substitution called hostname. And because this code is horrible, it uses locals. This is Python's way of saying, hey, just give me all of the variables that are local to this method as a dictionary. So there is an assumption here that there is a local variable called hostname that we're going to use in this string. This is actually common in the code in OpenStack. The problem is somebody's gone along and refactored it and hostname got removed. And they didn't notice that this string is now wrong. So we're trying to move away from using locals, but it's everywhere, so it's going to take a while. So the real problem here is that we have an error message that involves a variable that no longer exists. So it's not too bad. I have to remember, oh no, it's going to be one of those days, never type in front of people. Check out. So now we're back with the version that has the fix. So if we reload the window, the fix is to just redo how this log message is done. So there's a couple of things happening here. We don't use locals anymore. We pass through a dictionary that actually contains the substitutions we expect to use. So now we'll get a flake error if we use a variable that doesn't exist, and we would notice this problem. The other thing is that error message didn't pass through the instance that experienced the error message. So operators wouldn't actually know which instance had the problem, which is kind of annoying. And so the fix is trivial. And really what I'm picking on here is this one, because it is relatively easy to show what the problem is. It's not thousands of lines of code, because I'm trying to talk about the process and the tools, not the code, if that makes sense. So I have a fix. The next step is I want to test my fix, right? So I said we use a tool called Tox. I'm just going to run the Python 2.7 tests. And I would expect anybody who's sending code to be reviewed to have done the unit tests and to have done a PEP 8 check. PEP 8 is the style checker that makes sure that your dog strings are in the format we expect and that you're using the right kind of tabs, not the wrong kind of tabs, and all that kind of mechanical stuff. And so Tox, believe it or not, I know it's kind of terse, is actually running now. Now what Tox does, because we're using Tester under the hood is kind of cool, is it's running a whole bunch of parallel unit tests. Because this is only a laptop, it's only running on three cores, which is going to be a bit slow. So on my eight core desktop at home, this would take about two and a half minutes. It's going to take a lot longer because I have fewer cores. So we're actually going to just pretend those tests would have passed, because otherwise we're standing here tiddling our thumbs for a bit. The other thing I said you needed to do was do the PEP checks. And this is a little bit faster. So the other thing, while this is being boring, is Tox is kind of cool. It's going to go and fetch any PIP packages that you need in order to run these tests. So these can take a little while. So that S dist rinse step can sometimes take minutes, because it's going off to the internet and fetching a bunch of software, and then uncompressing it, and compiling it, and installing it in the right places, and all that kind of stuff. So it can be a little bit slow. There's some tricks you can do with caching PIP as well that make it faster. But hopefully, this will be done in a second, so I can show you what passing looks like any time now. Yay, it's style compliant. And you'd be surprised how many commits aren't. So once you've done both of those, you're ready to send off the code review. So the first thing you have to do is commit the code. So you do a get commit minus a. I won't actually do it, because I'm going to show you a slide with what a commit message should look like in a second. And then you do a get review. And get review is a funky tool built by the infrateam that will take your most recent get commit, and it will send it off to Jarrett for review. So you don't actually have to do any talking to Jarrett yourself. It's all done by special magic, which is kind of nice. And we need to escape my virtual machine. So I guess what I'm trying to say is it's not that scary. You need a bunch of tools. You need a bunch of counts, but it's not too bad. And then you can just write Python code if you're a Python programmer. It shouldn't be too surprising. We try really hard to be idiomatic with the Python code. And then we've got unit tests to hold your hand and stuff. So often I'll make a change, and then I'll run the unit tests and discover it's broken other bits. And that's OK, because I have things that help me find the bits I broke. And then you can just iterate and fix all the tests as you go along, and then you're done. So this is what we just did before. So you run the unit tests, and then you do a pep check. Now the other thing you should do if you're a responsible adult is you should test your change in DevStack. Now DevStack is outside the scope of this talk. There's another talk later on today, Soup to Nuts by Sean, that we'll talk a little bit about that and then talk about the automated testing that we do using DevStack in the cloud for every commit. So I'm not going to dig too deep into that. I'm just going to say DevStack is an important testing tool. And I would be sad if complicated commits hadn't been sent through DevStack. In the case of the change I just made there, it's a single log message. There's a unit test covering it. You probably don't need to run DevStack. But if you were implementing, say, a new scheduling filter or something like that, I would expect it to have been through some testing. And so as I said, you upload your change for review with Git review. Now the other thing Git review is going to do is it's going to add a line to your review message that's an ID number. We need that, because the Git show might change. So if I as a reviewer say, well, I hate this bit, can you change it? Then if you go back and commit, Git commit minus a, minus minus amend, then the show has changed. So we need a unique identifier for the change. And so this is what a commit message looks like. Now there's a few things to point out here. The email address of the author must match the author in Jarrett, who has signed the copyright assignment agreement, or your change will get bounced by a machine. The first line should be a string that ends in a full stop, or you call them periods here I think, and be no more than 50 characters. So a short descriptive string. Generally there should be a comment that says something like resolves bug and the bug number or implements blueprint and the blueprint name, because we have tools that hook off of that. So that bug in launchpad ended up with a comment that said there's been a code review filed for this bug, and that all happens because I have that magic string in the commit. There's also another magic string, doc impact. And what I like to do is I write a sentence along the lines of doc impact, colon, exciting thing that I did. And the reason you want that is because the tech writers are then going to pick that up, and they're going to go and update release notes and manuals and stuff on the basis of the hints you've given them in the commit message. If you don't do that, they have to go and read your commit and try and guess what you did, which is not much fun. And then the last line is that change ID that we mentioned before. So the review process is not too bad, to be honest. So Git review sends the code off to Jarrett. Jarrett then uses Jenkins to run a bunch of tests. So it's going to run the unit tests. It runs a Python 2.6 version, a Python 2.7 version, checks for PEP compliance. It runs some lint style tools, all of that. It also does some really funky stuff. There was a press release put out recently saying that we spin up 700 clouds a day. That's done by this process. So there's a job called Tempest that picks up your change, puts it in DevStack, and then runs an entire cloud on a single machine, in virtual machines, to see that the world still works. And so it will use Cinder and try and mount a volume, and it will use the Amazon EC2 API and make sure that it still works and all of that kind of stuff. To be honest, it's not perfect, but it's a lot better than nothing. And so occasionally, you'll send off a commit and all the unit tests pass, but then Tempest will come back and say, you broke EC2. And that probably means that you didn't have enough unit test coverage, and hopefully when you fix that, you'll also add a test to stop regressions as well. Now because we do some really complicated stuff there, we actually run Tempest three times, for example. Those tests take about 45 minutes at the moment. So if you go and look at a change in Jarrett, there'll be a comment saying I've started running them, but then there's going to be a big gap while it goes off and actually runs them. Generally, code reviewers aren't going to read your code until it's passed that automated process. There's nothing stopping them from commenting earlier, but I think in general, most of us filter for that. So then what will happen is humans will come along and say, hey, it looks good to me, or I like this or not. And there's four possible scores you can get. Plus one means I like this code, but I'm not a core reviewer. Plus two means I like this code and I am a core reviewer. I think we should put this in the code base. And then you get the inverses as well. Minus one, I'm not a core reviewer, and I don't like this. Minus two, I'm a core reviewer. Actually, minus two is a little bit special. I'm a core reviewer. I hate this code. Do not submit it without my permission. So that's kind of a big deal. They're kind of rare. But in general, what they're saying is I think this is a bad idea and should not land without significant conversation. But I can show you, oh, I wonder if the internet works. If I start, oh, this is a little bit brave. I didn't practice this bit. So this is a real live gerrit. No gerrits were harmed in the making of this. So let's just pick a random change to the top one. I don't care. So this is a real change. So this one, in fact, I'd say, oh, you need a full stop. But you can see that there's a blueprint linked. You can see here that there's been multiple versions of this change. So generally, as a conversation happens with the reviewers, you'll tweak it. You'll upload another version. You can see the files that were changed in the change. And you can get a side by side, differ them, obviously. And that's actually a kind of big change. That's 1,000 lines of delta. And so here's Jenkins. So Jenkins ran a bunch of tests. And it said, oh, the Python unit test failed. And if we clicked on that, we'd get a log, but it would tell us what tests failed and all that kind of stuff. But you can see a conversation happening with humans. And then the end state is when you have two cores that have said plus two, the last one of those cores will say approved. And then a robot will go and merge it all. So it's kind of funny. I never merge in Git because I have a machine to do it for me. So when friends ask me how Git works, I'm like, I don't know anything about that bit because I don't do it. But yeah, the other thing is I wasn't logged in there. I don't normally use Safari. The reason I use Safari is I didn't want you to see my Google Reader or whatever. So anybody can go and see what code reviews are out there at the moment and what's happening. In fact, anyone, if you have a Launchpad account, can go and comment. You don't have to be specially blessed. You don't have to be fantastic. In fact, the way you become a core reviewer is by doing a lot of reviews. So for Nova, for instance, the rule is you have to have done at least two code reviews per day on average for, say, the three months beforehand or whatever. So the way you become a core reviewer is by you've got to write some Nova code, but you've also got to go and do a bunch of reviews. So you do see people just popping up and saying, hey, what about this? And occasionally, it's really cool. You'll see operators pop up and say, this would break my environment, and that's really nice. So I'd like to encourage that behavior. And then, as I said, once two cores have said yes and it's been approved, it gets merged by a robot, and it just magically appears on trunk. And then it's all good. So I have, allegedly, about five minutes. So I just want to have a quick mention of the vulnerability management team. The other hat I wear is there's a very small group of people who do security vulnerability management for OpenStack. Generally, the process is if you find a security bug in OpenStack, you should file a private security bug. The reason you have to file a private security bug is we have a policy that if you file it in the open, we will never close it. It's out there already, right? So if you think this is something really important, that people should get warning before we publicly disclose it, it needs to be a private bug. So you file one of these, and then the vulnerability management team do all the boring stuff for you. We do the triage and decide this is a really bad bug or not. We go and find a developer who's going to fix the bug. We trick them into fixing it, because generally it's not sexy. They have to go and then backport it to all of the stable releases, which is sometimes horrible. Because, for example, the code can be very different between the releases. So I actually did one of these a few weeks ago where I ended up having to write the same patch three times from Scratch, which was not the most exciting week I've ever had. And then we go and disclose it to the distros and the large public clouds and that kind of stuff. And they generally get a heads up so that they can package stuff, so that on the agreed announcement date, the packages are all ready to go. And we hit the big red button. It gets publicly disclosed. The patches go through the same Jarrett process, except because we've shown them to people beforehand, it's a bit more like performance art, because they'll say, oh, yes, that looks good very quickly. And then off we go. So if you find a security bug, file it in private, please. The other thing is if we think it doesn't need to be in private, because say it's more, for example, more best practice than security, we'll say that. We'll say, we think this should be public. Our general default response is public, because this is an open source project. But if you file things as public, you remove our ability to warn distros before we disclose. So yeah, we do have security vulnerabilities in OpenStack. Let's be honest about it. It's a lot of code. They do happen. I think we're actually pretty responsive about fixing them. You can see that in that we've disclosed a few this year already. The distros have been very good about shipping fixes for them very quickly. So if you have a deployment in the real world, you should have security updates turned on. And yeah, it's not too bad. I guess if it's a private cloud where everybody works for your company, maybe you can be a bit less concerned. But then again, what if you have an employee ego rogue? It's probably best off installing security updates. So thank you very much for listening to my boring rant.