imagr / imagr Goto Github PK
View Code? Open in Web Editor NEWHome Page: http://imagr.io
License: Other
Home Page: http://imagr.io
License: Other
At the end of a workflow, there's an option to 'Restart' and 'Shutdown'.
Selecting 'Shutdown' just returns me to the workflow selector(with the workflows greyed out).
Not an issue with Imagr, but writing it down here so I remember to follow it up. Imagr works when used with a DeployStudio NBI, so something is missing that is causing the postinstall script to fail. Need to find out what it is and put it in AutoNBI.
It would be nice if new workflows could be viewed without quitting Imagr.
I'm using the following in the workflow to prompt for computer name:
<dict>
<key>type</key>
<string>computer_name</string>
</dict>
The name is being set to iMac instead of the inputted name.. The OS the netinstall image was created on was OS X 10.10.4. The computers are the latest revision iMac's with fusion drives.
Not sure what logs to check to see what's it's trying to do.
This should be obvious since we aren't using UIDs, but if the name is equal to another, only one shows up.
Please add a license to the project!
Apache is best =)
my plist
https://gist.github.com/JDHatman/d90095854831359c9f1a
All pre_first_boot images/packages work.
All first_boot packages install successfully, one of which is a munki kickstart.
Before Imagr reboots from the first_boot installs, Munki has already started. Imagr reboots shortly into the Munki run.
After the reboot, Munki runs again. There is a second reboot, for no apparent reason. Again, interrupting the Munki run.
After the second reboot, the kickstart I initiated for Munki has just given up and Munki doesn't run. This leaves the computer is a pretty useless state since Munki installs all the relevant bits like accounts and such.
I can boot into Recovery and manually re-touch .com.googlecode.munki.checkandinstallatstartup and after rebooting Munki will run as expected and "finish" my imaging process.
I have two workflows. I noticed that the same pattern occurs when I use only the kickstart workflow (assuming there is a usable image already on the machine). However, using this workflow, the Munki run will continue even after getting interrupted by two reboots.
I realize that this isn't necessarily an issue with Imagr. More or less providing info from my experiences.
Because this is running on Linux and is hosted on a web server, it would be good to support json as a config file format.
One could imagine a web server piece that dynamically serves up the json file based upon various conditions (the netboot set location, some sort of fact, etc). Obviously this would be left up to the person implementing their imagr server.
I think using plist is fine because admins are familiar with it, but json is far more common on web servers and are even supported by the default python install on almost everything.
Since it seems like the goal is to provide meaningful progress feedback when a workflow runs, I think it might make more sense to build a single "runWorkflowOnThread" method that performs the various subtasks, updating the status display as it runs. This would eliminate a lot of code duplication for each of the 'doSubtaskOnThread" methods, and make it easier to do consistent progress feedback for the entire workflow.
This script would generate a NetBoot set similar to how DeployStudio's assistant does so. This should happen only after Imagr is mostly complete to make sure that we don't have people adopting it too early.
Perhaps this would be a seperate PyObjC GUI to ask for information and then build the NetBoot?
It would basically do what Graham has documented here: https://github.com/grahamgilbert/imagr#building-a-netinstall
Easy test. Add an extra undernearth a workflow and use the new Reload Workflows feature.
Imagr will hide all of the buttons and display a "No workflows found in the configuration plist" dialog box. After pressing "Okay" you are presented a blank Imagr with no buttons. Startup Disk will then open.
If you go back to Imagr (after fixing the plist) you can Command+R, but in my testing it still cannot resolve the .plist issue. Reloading Imagr/NBI will fix the issue.
Following de9d8f0, the password field doesn't have focus when the app opens. Also, an incorrect password error is given when the field gets focus.
Just opening an issue so this doesn't get forgotten
https://github.com/gregneagle/imagr
If you like the direction, I can open a pull request.
Main changes:
Imagr subscribes to NSWorkspace notifications to be notified when a new volume is mounted, an existing volume is unmounted, or a volume is renamed.
Target disk selection is moved to a popup menu in the same view as the workflow selection.
Other UI elements moved in the workflow selection view: Run Workflow moved to lower right, where an OK, Save, or other default "Perform the action" button is usually located in dialogs and assistant-type utilties. Other elements moved to adjust.
This is in reference to #64 and #75
When testing this, I changed the url path to the DMG to a 404. After failing to clone, Imagr offered to "reload the workflows". After reloading I was presented a "No writable volumes found" error.
This is due to the volume being unmounted but not remounted after a failure.
(this is so I don't forget).
Optional feature for script task names to allow more verbose messaging for Imagr-server.
I know you just added the feature...When the reporturl
key is set to the login page of your imagr-server, Imagr will hard crash. All other "random" variations I could come up with silently failed with the correct error message (time-out, server not available, etc.).
2015-06-10 17:56:55.292 Imagr[7869:61825] gurl options: {
file = "/tmp/tempdata";
"follow_redirects" = 0;
"logging_function" = "<objc.function 'NSLog' at 0x10a904cf0>";
"post_data" = "status=in_progress&serial=A12BCDE3FG45&message=Imagr+is+starting+up...";
url = "http://imagr:8000/";
}
2015-06-10 17:56:55.437 Imagr[7869:61825] An uncaught exception was raised
2015-06-10 17:56:55.437 Imagr[7869:61825] <type 'exceptions.ValueError'>: Too few arguments for format string [cur:1/len:1]
2015-06-10 17:56:55.438 Imagr[7869:61825] (
0 CoreFoundation 0x00007fff909a831c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff83d07c48 objc_exception_throw + 48
2 CoreFoundation 0x00007fff909a7eb9 -[NSException raise] + 9
3 _objc.so 0x000000010a34aba4 PyObjCErr_ToObjCWithGILState + 46
4 _objc.so 0x000000010a337792 PyObjCFFI_MakeClosure + 5033
5 libffi.dylib 0x00007fff858b9a24 ffi_closure_unix64_inner + 516
6 libffi.dylib 0x00007fff858b9096 ffi_closure_unix64 + 70
7 CFNetwork 0x00007fff854f47b2 -[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:] + 233
8 CFNetwork 0x00007fff854f46b7 -[NSURLConnectionInternal _withActiveConnectionAndDelegate:] + 48
9 CFNetwork 0x00007fff854f53d4 _ZL30_NSURLConnectionDidReceiveDataP16_CFURLConnectionPK8__CFDatalPKv + 79
10 CFNetwork 0x00007fff854f5067 ___ZN27URLConnectionClient_Classic29_delegate_didReceiveDataArrayEv_block_invoke + 293
11 CFNetwork 0x00007fff855cf7cd ___ZN27URLConnectionClient_Classic18_withDelegateAsyncEPKcU13block_pointerFvP16_CFURLConnectionPK33CFURLConnectionClientCurrent_VMaxE_block_invoke_2 + 100
12 libdispatch.dylib 0x00007fff8d7d1383 _dispatch_client_callout + 8
13 libdispatch.dylib 0x00007fff8d7e7672 _dispatch_block_invoke + 474
14 CFNetwork 0x00007fff854508c4 _ZN19RunloopBlockContext13_invoke_blockEPKvPv + 24
15 CoreFoundation 0x00007fff90886594 CFArrayApplyFunction + 68
16 CFNetwork 0x00007fff854507bd _ZN19RunloopBlockContext7performEv + 137
17 CFNetwork 0x00007fff85450598 _ZN17MultiplexerSource7performEv + 282
18 CFNetwork 0x00007fff854503ba _ZN17MultiplexerSource8_performEPv + 72
19 CoreFoundation 0x00007fff908b97a1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
20 CoreFoundation 0x00007fff908abf9c __CFRunLoopDoSources0 + 556
21 CoreFoundation 0x00007fff908ab4bf __CFRunLoopRun + 927
22 CoreFoundation 0x00007fff908aaeb8 CFRunLoopRunSpecific + 296
23 Foundation 0x00007fff8f8dfd42 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 270
24 Foundation 0x00007fff8f8fd677 -[NSRunLoop(NSRunLoop) runUntilDate:] + 108
25 libffi.dylib 0x00007fff858b8f14 ffi_call_unix64 + 76
26 ??? 0x00007fb9777bef90 0x0 + 140434550288272
)
2015-06-10 17:56:55.438 Imagr[7869:61825] *** Terminating app due to uncaught exception 'OC_PythonException', reason: '<type 'exceptions.ValueError'>: Too few arguments for format string [cur:1/len:1]'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff909a831c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff83d07c48 objc_exception_throw + 48
2 CoreFoundation 0x00007fff909a7eb9 -[NSException raise] + 9
3 _objc.so 0x000000010a34aba4 PyObjCErr_ToObjCWithGILState + 46
4 _objc.so 0x000000010a337792 PyObjCFFI_MakeClosure + 5033
5 libffi.dylib 0x00007fff858b9a24 ffi_closure_unix64_inner + 516
6 libffi.dylib 0x00007fff858b9096 ffi_closure_unix64 + 70
7 CFNetwork 0x00007fff854f47b2 -[NSURLConnectionInternal _withConnectionAndDelegate:onlyActive:] + 233
8 CFNetwork 0x00007fff854f46b7 -[NSURLConnectionInternal _withActiveConnectionAndDelegate:] + 48
9 CFNetwork 0x00007fff854f53d4 _ZL30_NSURLConnectionDidReceiveDataP16_CFURLConnectionPK8__CFDatalPKv + 79
10 CFNetwork 0x00007fff854f5067 ___ZN27URLConnectionClient_Classic29_delegate_didReceiveDataArrayEv_block_invoke + 293
11 CFNetwork 0x00007fff855cf7cd ___ZN27URLConnectionClient_Classic18_withDelegateAsyncEPKcU13block_pointerFvP16_CFURLConnectionPK33CFURLConnectionClientCurrent_VMaxE_block_invoke_2 + 100
12 libdispatch.dylib 0x00007fff8d7d1383 _dispatch_client_callout + 8
13 libdispatch.dylib 0x00007fff8d7e7672 _dispatch_block_invoke + 474
14 CFNetwork 0x00007fff854508c4 _ZN19RunloopBlockContext13_invoke_blockEPKvPv + 24
15 CoreFoundation 0x00007fff90886594 CFArrayApplyFunction + 68
16 CFNetwork 0x00007fff854507bd _ZN19RunloopBlockContext7performEv + 137
17 CFNetwork 0x00007fff85450598 _ZN17MultiplexerSource7performEv + 282
18 CFNetwork 0x00007fff854503ba _ZN17MultiplexerSource8_performEPv + 72
19 CoreFoundation 0x00007fff908b97a1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
20 CoreFoundation 0x00007fff908abf9c __CFRunLoopDoSources0 + 556
21 CoreFoundation 0x00007fff908ab4bf __CFRunLoopRun + 927
22 CoreFoundation 0x00007fff908aaeb8 CFRunLoopRunSpecific + 296
23 Foundation 0x00007fff8f8dfd42 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 270
24 Foundation 0x00007fff8f8fd677 -[NSRunLoop(NSRunLoop) runUntilDate:] + 108
25 libffi.dylib 0x00007fff858b8f14 ffi_call_unix64 + 76
26 ??? 0x00007fb9777bef90 0x0 + 140434550288272
)
libc++abi.dylib: terminating with uncaught exception of type NSException
make: *** [run] Error 134
This could take the form of a preference, or a key in the workflow.
When testing, it's helpful to be able to verify the results of a workflow before the restart occurs; I can just comment out the restart action in code right now, but would be nice to have more formal support.
here is the workflow I tested this with:
<dict>
<key>name</key>
<string>Mavericks - MunkiTools</string>
<key>description</key>
<string>Deploys the latest 10.9.x image. Munki tools and local admin account included.</string>
<key>components</key>
<array>
<dict>
<key>type</key>
<string>image</string>
<key>url</key>
<string>http://imagr.whitbyschool.net/images/osx_custom_141014-10.9.5-13F34.hfs.dmg</string>
</dict>
</array>
<key>restart_action</key>
<string>restart</string>
</dict>
The firstboot log opened at the same time as MSC.
From Graham: Using Gurl would get us server side verification
The first boot script will wait for the network to be available before installing anything. The source script allows for this to be disabled, so we need to have a key in the workflow to let this be disabled.
From Graham: The current method is just a hack - there's beach balling galore
When running a workflow with a pre_first_boot script component, if the pre_first_boot script exits non-zero (i.e. it fails) workflow execution continues and the user isn't notified the script failed.
An example workflow:
<dict>
<key>name</key>
<string>Test Script Error</string>
<key>description</key>
<string>Intentionally create an error in a script</string>
<key>components</key>
<array>
<dict>
<key>type</key>
<string>script</string>
<key>content</key>
<string>#!/bin/bash ; exit 1</string>
<key>pre_first_boot</key>
<true/>
</dict>
</array>
<key>restart_action</key>
<string>none</string>
</dict>
How do you feel about an optional text field that allows us to rename the computer on firstboot? Imagr could output a simple text file after the image process while your first-boot script could be modified to look for said file. That is the only missing feature that would allow me to drop DeployStudio.
Steps to reproduce:
Result: Selected workflow resets to the first workflow in the config.
This actually happens when you click on in the description field on the first workflow but cannot visually see it happen.
I've been amazed with the speed we've got Imagr from my crappy code to something useful, so I thought it would be helpful to start thinking about what is left to do before we can do an initial release. In my opinion, we need to:
Anything else?
If Imagr fails to pull down any component of the workflow, you do not have the ability to retry. You can hit "OK" Which will then bring up Startup Disk. Imagr is blank and only allows you to quit. Quitting Imagr (when using AutoNBI) causes it to load the normal recovery.
It would be nice to be able to include a workflow by name to another workflow.
Perhaps this would be best implemented if there was a hidden flag in the top dictionary of workflows.
So we can create workflows only meant for inclusion.
Latest pull of Imagr does not mount the volume after DMG ASR.
You can easily test this with the following workflow:
<dict>
<key>name</key>
<string>Yosemite 10.10.3 Basic</string>
<key>description</key>
<string>This is a basic test image.</string>
<key>components</key>
<array>
<dict>
<key>type</key>
<string>image</string>
<key>url</key>
<string>http://xxx/imagr/masters/OS_X_10.10.3-14D136.hfs.dmg</string>
</dict>
</array>
</dict>
After finishing, the volume is not mounted. Imagr will also complain that it cannot find any volumes if you attempt to run another workflow.
More advanced workflows calling preboot scripts will cause Imagr to immediately hard crash.
<dict>
<key>name</key>
<string>Yosemite 10.10.3 Basic</string>
<key>description</key>
<string>This is a basic test image with preboot script.</string>
<key>components</key>
<array>
<dict>
<key>type</key>
<string>image</string>
<key>url</key>
<string>http://xxx/imagr/masters/OS_X_10.10.3-14D136.hfs.dmg</string>
</dict>
<dict>
<key>type</key>
<string>script</string>
<key>content</key>
<string>#!/bin/bash
echo ""
exit 0
</string>
<key>first_boot</key>
<false/>
</dict>
</array>
</dict>
When the serverurl
is set correctly but Imagr is unable to access the server, Imagr will crash without a proper error message.
I have only seen this happen on physical clients and even then only a handful of times. After typing the password the main window loads however the "Choice Target" is blank. These machines only have one partition and Imagr is successfully resolving that partition (you are able to run the workflow with success). However the GUI element does not display the currently selected target disk.
Out of 40 clients (50 more tomorrow) I have seen this happen 4 times so enough that something is funky.
Build 240. Using AutoNBI NetInstall environment.
I can try and get more debug info if need just have to finish this roll out first.
The computer name field should be selected by default when the workflow opens the Computer Name view.
Improve launchApp behavior if app is already running thusly:
Imagr should subscribe to the following NSWorkspace notifications: NSWorkspaceDidRenameVolumeNotification, NSWorkspaceDidMountNotification, NSWorkspaceWillUnmountNotification and NSWorkspaceDidUnmountNotification
This would allow for rescanning available volumes "automatically".
I also wonder if perhaps the selection of the target volume doesn't need to be modal, and could just be a pop-up menu on the workflows screen...
I'm envisioning someone running Imagr, sitting at the workflows screen, then opening Disk Utility and repartitioning, or plugging in a USB drive. It would be nice if Imagr "automatically" noticed the change in available volumes and updated its pop-up menu accordingly.
I can work on this if you'd like, though I may not get to it until Monday.
If you run two workflows back-to-back it is currently possible for the LoginLog.app to be copied to the system twice causing a crash.
Error log
<type 'exceptions.OSError'>: [Errno 17] File exists: '/Library/PrivilegedHelperTools/LoginLog.app'
2015-04-26 12:40:43.968 Imagr[52121:2394065] (
0 CoreFoundation 0x00007fff94bb503c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff89fb576e objc_exception_throw + 43
2 CoreFoundation 0x00007fff94bb4bd9 -[NSException raise] + 9
3 _objc.so 0x0000000106431a8b PyObjCErr_ToObjCWithGILState + 46
4 _objc.so 0x000000010641e52d PyObjCFFI_MakeClosure + 5097
5 libffi.dylib 0x00007fff95468a07 ffi_closure_unix64_inner + 511
6 libffi.dylib 0x00007fff954680c6 ffi_closure_unix64 + 70
7 libsystem_pthread.dylib 0x00007fff8ecd6268 _pthread_body + 131
8 libsystem_pthread.dylib 0x00007fff8ecd61e5 _pthread_body + 0
9 libsystem_pthread.dylib 0x00007fff8ecd441d thread_start + 13
)
2015-04-26 12:40:43.968 Imagr[52121:2394065] *** Terminating app due to uncaught exception 'OC_PythonException', reason: '<type 'exceptions.OSError'>: [Errno 17] File exists: '/Library/PrivilegedHelperTools/LoginLog.app''
*** First throw call stack:
(
0 CoreFoundation 0x00007fff94bb503c __exceptionPreprocess + 172
1 libobjc.A.dylib 0x00007fff89fb576e objc_exception_throw + 43
2 CoreFoundation 0x00007fff94bb4bd9 -[NSException raise] + 9
3 _objc.so 0x0000000106431a8b PyObjCErr_ToObjCWithGILState + 46
4 _objc.so 0x000000010641e52d PyObjCFFI_MakeClosure + 5097
5 libffi.dylib 0x00007fff95468a07 ffi_closure_unix64_inner + 511
6 libffi.dylib 0x00007fff954680c6 ffi_closure_unix64 + 70
7 libsystem_pthread.dylib 0x00007fff8ecd6268 _pthread_body + 131
8 libsystem_pthread.dylib 0x00007fff8ecd61e5 _pthread_body + 0
9 libsystem_pthread.dylib 0x00007fff8ecd441d thread_start + 13
)
libc++abi.dylib: terminating with uncaught exception of type NSException
I'm not sure it is necessary to include the validateplist
script with the dmg. We are currently instructing users to git clone the repo from the wiki which will download the most up to date script.
Other thought would be to include the Makefile
which allows users to avoid git clone altogether.
Not sure what best practice would be...Imagr is in early development so I'll let you decide.
Imagr will present a cloning error dialog, which you can hit OK to and then reboot/select startup disk
Imagr should take you back to the workflow selection (this is similar to #64 )
I didn't make this a pull list because it might be not a direction you are interested in.
This moves the login and main views into a tab view, which makes switching views easier, and allows us to add more views without going crazy trying to edit them in InterfaceBuilder.
As an example I added a new startup view that replaces the sheet.
It might be nice to add an "empty" view or "error" view we switch to when we don't find a server url or any writable volumes, etc. (instead of trying to hide all the controls, etc)
Since this is a pretty dramatic set of changes I thought I'd let you look at my clone first before deciding if this is a direction that makes sense.
(There's additional cleanup to be done if you decide this is a direction you want to go, but I don't want to do all the cleanup work if you don't want to go this way.)
Hi, thanks for making imagr!
Were in the process of replacing DeployStudio with imagr and I have a few suggestions for improvements. I'm braking them up to different issues so you can consider them separately
It would be really nice if the $3 variable was set for script tasks.
I know i can use {{target_volume}} but it would be nice to be able to just use legacy scripts.
This might be NBI-dependent, but when testing on a DeployStudio NBI, Imagr takes upwards of 20+ seconds to become usable. A big chunk of that time is in macdisk.MountedVolumes().
Looking through the code, it ends up calling diskutil info -plist for every device id, which is incredibly slow.
I'd like to look at ways to speed this up.
@natewalck I choose you!
Imagr will currently crash when it cannot download or install workflow components. There should be an error displayed when this happens.
The goal is to allow an arbitrary script to run and select which image to use during the apply image step. It does not need to be exactly as listed below, but having the functionality is super helpful, especially if you want one master workflow for support folks to run.
An example workflow:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.