What are you working on for 1.8?
by Michael DeHaan
I have the roadmap page here where I'm trying to list all the cool
things I know of that are going on for the devel branch and who is
working on them currently.
https://fedorahosted.org/cobbler/wiki/TheRoadmap
If I've left something off you might be working on, let me know on this
list.
I hope this also gives folks and idea of all that's pouring into 1.8.
This looks to be a very exciting release -- lots of big, long running
features -- not just small stuff. I am excited.
1.6 was mainly a performance release (though also contained a lot of
nice mini-features, and the new s390 PXE simulator), but I think this
one will be bigger and better.
--Michael
15 years, 1 month
using github -- please help
by Corey Osman
Hi,
Ok I have spent too much time trying to figure out how the hell to add
cobbler to my github account. Can someone please provide a step-by-
step list of what to do.
Here is some background:
git://github.com/icontender/cobbler.git
I have already done my first commit on my github master branch
I have clone the fedorahosted cobbler branch
I have made some commits to the "official devel branch"
I then did a rebase and resolved conflicts.
Now I want to sent that devel-branch to my personal github master
branch.
I added my remote branch to the same directory where the "official
cobbler branch" is located
I then switched branches and tried to do a push. git push cosman
( this didn't work)
This is my config file
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = git://git.fedorahosted.org/cobbler
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[branch "my-devel"]
remote = origin
merge = refs/heads/devel
[remote "cosman"]
url = git@github.com:icontender/cobbler.git
fetch = +refs/heads/*:refs/remotes/cosman/*
Then I tried to push:
[root@cobbler cobbler]# git push cosman
To git@github.com:icontender/cobbler.git
! [rejected] master -> master (non-fast forward)
error: failed to push some refs to 'git@github.com:icontender/
cobbler.git'
How do I get this work?
15 years, 1 month
[PATCH] Cobbler reporting + XMLRPC
by Adam Rosenwald
Tested against commit b2aaf2b3f5c8d758825028dacdeadbdd2e50e4a8, with my
earlier reporting fixes patch
(0001-Fixed-issues-when-reporting-on-a-set-of-fields-that.patch
<https://fedorahosted.org/pipermail/cobbler-devel/attachments/20090406/c0c...>)
already applied. Please commit this patch AFTER committing the previous
patch.
So, now one can issue XMLRPC calls to retrieve reports from remote
cobbler servers.
E.g. client usage:
---
import xmlrpclib
remote =
xmlrpclib.ServerProxy("http://<remote_cobbler_server>/cobbler_api",
allow_none=True)
# get a 'cobbler report --what=systems' report (no headers)
report1 = remote.report(True, 'systems', None, 'text', 'all', None)
# get a 'cobbler report --name=hp_003 --format=mediawiki' report (no
headers)
report2 = remote.report(True, None, 'hp_003', 'mediawiki', None)
# get a 'cobbler report --what=distros --format=csv
--fields='name,ks_meta[tree]' report (with headers)
report3 = remote.report(True, 'distros', None, 'csv',
'name,ks_meta[tree]', False)
---
The 'function prototype' for the remote function (from remote.py) is the
following:
###
def
report(self,api=True,what=None,name=None,type=None,fields=None,noheaders=None,**rest):
###
I haven't figured out how to get xmlrpclib to recognize the positional
parameters -- hence the odd client examples (all args are listed and are
listed in order). Perhaps one of you might be able to figure this out,
since it's annoying to have to remember the prototype every time you
want to invoke an XMLRPC reporting call.
Cheers,
- A.
>From 888b569e91009dcb6212e4164ab437144733a9cc Mon Sep 17 00:00:00 2001
From: Adam Rosenwald <thestrider(a)gmail.com>
Date: Tue, 7 Apr 2009 03:23:09 -0400
Subject: [PATCH] Enabled XMLRPC reporting function.
ARos
---
cobbler/action_report.py | 91 +++++++++++++++++++++++-----------------------
cobbler/api.py | 4 +-
cobbler/remote.py | 6 +++
3 files changed, 54 insertions(+), 47 deletions(-)
diff --git a/cobbler/action_report.py b/cobbler/action_report.py
index 9f4367e..8d27ccf 100644
--- a/cobbler/action_report.py
+++ b/cobbler/action_report.py
@@ -214,20 +214,18 @@ class Report:
return opentable + outputheaders + outputbody + closetable
- def print_formatted_data(self, data, order, report_type, noheaders):
+ def get_formatted_data(self, data, order, report_type, noheaders):
"""
Used for picking the correct format to output data as
"""
if report_type == "csv":
- print self.reporting_csv(data, order, noheaders)
+ return self.reporting_csv(data, order, noheaders)
if report_type == "mediawiki":
- print self.reporting_mediawiki(data, order, noheaders)
+ return self.reporting_mediawiki(data, order, noheaders)
if report_type == "trac":
- print self.reporting_trac(data, order, noheaders)
+ return self.reporting_trac(data, order, noheaders)
if report_type == "doku":
- print self.reporting_doku(data, order, noheaders)
-
- return True
+ return self.reporting_doku(data, order, noheaders)
def reporting_sorter(self, a, b):
"""
@@ -235,26 +233,28 @@ class Report:
"""
return cmp(a.name, b.name)
- def reporting_print_sorted(self, collection):
+ def reporting_get_sorted(self, collection):
"""
Prints all objects in a collection sorted by name
"""
collection = [x for x in collection]
collection.sort(self.reporting_sorter)
+ str = ""
for x in collection:
- print x.printable()
- return True
+ str += x.printable() + "\n"
+ return str
def reporting_list_names2(self, collection, name):
"""
Prints a specific object in a collection.
"""
obj = collection.find(name=name)
+ str = ""
if obj is not None:
- print obj.printable()
- return True
+ str += obj.printable() + "\n"
+ return str
- def reporting_print_all_fields(self, collection, report_name, report_type, report_noheaders):
+ def reporting_get_all_fields(self, collection, report_name, report_type, report_noheaders):
"""
Prints all fields in a collection as a table given the report type
"""
@@ -264,7 +264,7 @@ class Report:
if collection:
collection = [collection]
else:
- return
+ raise CX(_("%s is not a valid item." % report_name))
collection = [x for x in collection]
collection.sort(self.reporting_sorter)
@@ -282,12 +282,12 @@ class Report:
for (device, info) in value.iteritems():
for (info_header, info_value) in info.iteritems():
item[info_header] = str(device) + ': ' + str(info_value)
- # needs to create order list for print_formatted_fields
+ # needs to create order list for get_formatted_fields
if count == 0:
out_order.append(info_header)
else:
item[key] = value
- # needs to create order list for print_formatted_fields
+ # needs to create order list for get_formatted_fields
if count == 0:
out_order.append(key)
@@ -295,11 +295,9 @@ class Report:
data.append(item)
- self.print_formatted_data(data = data, order = out_order, report_type = report_type, noheaders = report_noheaders)
-
- return True
+ return self.get_formatted_data(data = data, order = out_order, report_type = report_type, noheaders = report_noheaders)
- def reporting_print_x_fields(self, collection, report_name, report_type, report_fields, report_noheaders):
+ def reporting_get_x_fields(self, collection, report_name, report_type, report_fields, report_noheaders):
"""
Prints specific fields in a collection as a table given the report type
"""
@@ -309,7 +307,7 @@ class Report:
if collection:
collection = [collection]
else:
- return
+ raise CX(_("%s is not a valid item." % report_name))
collection = [x for x in collection]
collection.sort(self.reporting_sorter)
@@ -321,13 +319,11 @@ class Report:
item = self.fielder(structure, fields_list)
data.append(item)
- self.print_formatted_data(data = data, order = fields_list, report_type = report_type, noheaders = report_noheaders)
-
- return True
+ return self.get_formatted_data(data = data, order = fields_list, report_type = report_type, noheaders = report_noheaders)
# -------------------------------------------------------
- def run(self, report_what = None, report_name = None, report_type = None, report_fields = None, report_noheaders = None):
+ def run(self, api = False, report_what = None, report_name = None, report_type = None, report_fields = None, report_noheaders = None):
"""
Get remote profiles and distros and sync them locally
"""
@@ -338,38 +334,39 @@ class Report:
3. Handles specific fields of report outputs as table given a format
"""
+ str = ""
if report_type == 'text' and report_fields == 'all':
if report_what in [ "all", "distros", "distro" ]:
if report_name:
- self.reporting_list_names2(self.api.distros(), report_name)
+ str += self.reporting_list_names2(self.api.distros(), report_name)
else:
- self.reporting_print_sorted(self.api.distros())
+ str += self.reporting_get_sorted(self.api.distros())
if report_what in [ "all", "profiles", "profile" ]:
if report_name:
- self.reporting_list_names2(self.api.profiles(), report_name)
+ str += self.reporting_list_names2(self.api.profiles(), report_name)
else:
- self.reporting_print_sorted(self.api.profiles())
+ str += self.reporting_get_sorted(self.api.profiles())
if report_what in [ "all", "systems", "system" ]:
if report_name:
- self.reporting_list_names2(self.api.systems(), report_name)
+ str += self.reporting_list_names2(self.api.systems(), report_name)
else:
- self.reporting_print_sorted(self.api.systems())
+ str += self.reporting_get_sorted(self.api.systems())
if report_what in [ "all", "repos", "repo" ]:
if report_name is not None:
- self.reporting_list_names2(self.api.repos(), report_name)
+ str += self.reporting_list_names2(self.api.repos(), report_name)
else:
- self.reporting_print_sorted(self.api.repos())
+ str += self.reporting_get_sorted(self.api.repos())
if report_what in [ "all", "images", "image" ]:
if report_name is not None:
- self.reporting_list_names2(self.api.images(), report_name)
+ str += self.reporting_list_names2(self.api.images(), report_name)
else:
- self.reporting_print_sorted(self.api.images())
+ str += self.reporting_get_sorted(self.api.images())
elif report_type == 'text' and report_fields != 'all':
raise CX(_("The 'text' type can only be used with field set to 'all'"))
@@ -377,33 +374,37 @@ class Report:
elif report_type != 'text' and report_fields == 'all':
if report_what in [ "all", "distros", "distro" ]:
- self.reporting_print_all_fields(self.api.distros(), report_name, report_type, report_noheaders)
+ str += self.reporting_get_all_fields(self.api.distros(), report_name, report_type, report_noheaders)
if report_what in [ "all", "profiles", "profile" ]:
- self.reporting_print_all_fields(self.api.profiles(), report_name, report_type, report_noheaders)
+ str += self.reporting_get_all_fields(self.api.profiles(), report_name, report_type, report_noheaders)
if report_what in [ "all", "systems", "system" ]:
- self.reporting_print_all_fields(self.api.systems(), report_name, report_type, report_noheaders)
+ str += self.reporting_get_all_fields(self.api.systems(), report_name, report_type, report_noheaders)
if report_what in [ "all", "repos", "repo" ]:
- self.reporting_print_all_fields(self.api.repos(), report_name, report_type, report_noheaders)
+ str += self.reporting_get_all_fields(self.api.repos(), report_name, report_type, report_noheaders)
if report_what in [ "all", "images", "image" ]:
- self.reporting_print_all_fields(self.api.images(), report_name, report_type, report_noheaders)
+ str += self.reporting_get_all_fields(self.api.images(), report_name, report_type, report_noheaders)
else:
if report_what in [ "all", "distros", "distro" ]:
- self.reporting_print_x_fields(self.api.distros(), report_name, report_type, report_fields, report_noheaders)
+ str += self.reporting_get_x_fields(self.api.distros(), report_name, report_type, report_fields, report_noheaders)
if report_what in [ "all", "profiles", "profile" ]:
- self.reporting_print_x_fields(self.api.profiles(), report_name, report_type, report_fields, report_noheaders)
+ str += self.reporting_get_x_fields(self.api.profiles(), report_name, report_type, report_fields, report_noheaders)
if report_what in [ "all", "systems", "system" ]:
- self.reporting_print_x_fields(self.api.systems(), report_name, report_type, report_fields, report_noheaders)
+ str += self.reporting_get_x_fields(self.api.systems(), report_name, report_type, report_fields, report_noheaders)
if report_what in [ "all", "repos", "repo" ]:
- self.reporting_print_x_fields(self.api.repos(), report_name, report_type, report_fields, report_noheaders)
+ str += self.reporting_get_x_fields(self.api.repos(), report_name, report_type, report_fields, report_noheaders)
if report_what in [ "all", "images", "image" ]:
- self.reporting_print_x_fields(self.api.images(), report_name, report_type, report_fields, report_noheaders)
+ str += self.reporting_get_x_fields(self.api.images(), report_name, report_type, report_fields, report_noheaders)
+ if api:
+ return str
+ else:
+ print str
diff --git a/cobbler/api.py b/cobbler/api.py
index a4b44c5..ee4d652 100644
--- a/cobbler/api.py
+++ b/cobbler/api.py
@@ -702,12 +702,12 @@ class BootAPI:
include_systems = systems
)
- def report(self, report_what = None, report_name = None, report_type = None, report_fields = None, report_noheaders = None):
+ def report(self, api=False, report_what = None, report_name = None, report_type = None, report_fields = None, report_noheaders = None):
"""
Report functionality for cobbler
"""
reporter = action_report.Report(self._config)
- return reporter.run(report_what = report_what, report_name = report_name,\
+ return reporter.run(api = api, report_what = report_what, report_name = report_name,\
report_type = report_type, report_fields = report_fields,\
report_noheaders = report_noheaders)
diff --git a/cobbler/remote.py b/cobbler/remote.py
index 43e9c0a..2f81ad9 100644
--- a/cobbler/remote.py
+++ b/cobbler/remote.py
@@ -553,6 +553,12 @@ class CobblerXMLRPCInterface:
self._log("version",token=token)
return self.api.version(extended=True)
+ def report(self,api=True,what=None,name=None,type=None,fields=None,noheaders=None,**rest):
+ """
+ Returns a cobbler report as a string
+ """
+ return self.api.report(api,what,name,type,fields,noheaders)
+
def get_distros(self,page=None,results_per_page=None,token=None,**rest):
"""
Returns all cobbler distros as an array of hashes.
--
1.5.5.1
15 years, 1 month
A preview of the deployment functions for 1.8
by Michael DeHaan
Not quite entirely finished yet, but he's a walk through of the
deployment feature in 1.8, brought to you by Scott Henson and myself.
Comments welcome.
Ok, so here's the deal. The best way to create virtual deployments in
cobbler has always been to make sure you have system records for each
VM. However
cobbler doesn't do a great job of telling you where you deployed those
VMs, and deploying those VMs has been up to you. This is all about to
change for the better.
# cobbler system list
alpha
beta
gamma
virt-foo
virt-bar
# we'll require that the hostname fields are set for the systems
cobbler system edit --name=alpha --hostname=alpha.example.org
cobbler system edit --name=beta--hostname=alpha.example.org
cobbler system edit --name=gamma --hostname=alpha.example.org
# now let's bring a virt system to life!
# cobbler deploy --system=virt-bar --virt-host=gamma [--method=ssh|func]
(koan runs and installs system record on gamma, using the --hostname set
for gamma)
# Now, imagine we have the following ... two groups of machines where we
could possibly install a virt instance
cobbler system edit --name=alpha --virt-group=labA
cobbler system edit --name=beta --virt-group=labA
cobbler system edit --name=gamma --virt-group=labB
# Let's make it happen
# cobbler deploy --system=virt-bar --virt-group=labB
# Now, I'm curious, where did I deploy the system named "virt-bar" ?
# cobbler system report | grep virt-host
gamma
Wow, cobbler recorded where we deployed the system since we used cobbler
deploy to deploy it. (We may also support reinstalling the virt system
in the future...)
This will allow deploying the system record to the most "free" system in
labB. (Some work on this pending).
Current deployment methods include SSH and Func, both requiring koan.
Something using libvirt-remote and/or libvirt-qmf is very likely in the
future.
Currently the heuristic for virt groups is "pick a random system", we're
working on that also. We'll include our own lightweight options and be
able to use external options as well.
And all of this will also work over the Python and XMLRPC APIs just like
the above.
--Michael
15 years, 1 month
ESX integration - ideas?
by Jasper Capel
Hi all,
Me and Joep Piscaer are planning on doing some Cobbler + ESX/vCenter
integration. We'd like to be able to deploy virtuals like we can on
xen/kvm using Koan.
However, we're not going to be able to run a tool like Koan on a vCenter
server, so we'd have to talk to VMware through some sort of API from
another host.
Keeping this in mind, how much sense does it make to still implement
this in Koan? Wouldn't Cobbler be a better place for this piece of code
to live?
I'd like some input on this. :)
Cheers,
Jasper
15 years, 1 month
[PATCH] traceback on generating dhcp config
by Jasper Capel
Hi all,
In my capel-master and capel-devel branches is a fix for a traceback
that occurs when the dhcp config is generated, and a bonding slave
device's specified master device does not exist.
git://bender.newnewyork.nl/cobbler.git
Cheers,
Jasper
15 years, 1 month
webui session information
by Vreman, Peter
Can a hash for a session be added to store user changes of the webui.
Example is the page, limit and filter settings during in the list. When an operation is done and returned to the list the old settings are reused.
The hash can contain things like:
System_list_page
System_list_limit
System_list_filtername
Distro_list_page
Distro_list_limit
Using the session will also cleanup the URLs.
E.g. after a search execute you can do the following commands to show the results:
self.session['system_list_filtername']='newsearchXXXX'
return self.__redirect('system_list')
Thoughts?
Regards,
Peter
This e-mail and any attachment is for authorised use by the intended recipient(s) only. It may contain proprietary material, confidential information and/or be subject to legal privilege. It should not be copied, disclosed to, retained or used by, any other party. If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender. Thank you.
15 years, 1 month
cobbler nouns wrapper method creation
by Vreman, Peter
Dynamic method creation can be used to create the methods for the cobbler nouns. A single loop can create all the wrappers:
Adding the following code to api.__init__ will create all the find_xxxx() methods:
for what in ['distro','profile','system','repo','image','network']:
codestr='''
def find_%s(self, name=None, return_list=False, no_errors=False, **kargs):
return self._config.%ss().find(name=name, return_list=return_list, no_errors=no_errors, **kargs)
''' % (what,what)
d={}
exec codestr.strip() in d
setattr(self.__class__, 'find_%s' % what, d['find_%s' % what])
Regards,
Peter
This e-mail and any attachment is for authorised use by the intended recipient(s) only. It may contain proprietary material, confidential information and/or be subject to legal privilege. It should not be copied, disclosed to, retained or used by, any other party. If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender. Thank you.
15 years, 1 month
Re: WebUI search patch
by Michael DeHaan
Vreman, Peter - Acision wrote:
>
> Hi Michael,
>
> Please find attached the webui_search.diff patch as a regular diff.
> The git-format-patch doesn’t work for me.
>
> Features
>
> - paginate search results
>
> - quickfilter
>
> - allow ~ to negate a compare in search
>
> - minor log improvements
>
> Todos
>
> - Delete filters
>
> - Modify filters (Load filter does not work yet)
>
> - Allow filter names per collection only. I guess I Need to combine
> the filter.name with the filter.what field somehow.
>
> Please feel free to commit the current work if you like it.
>
> Regards,
>
> Peter
>
>
> This e-mail and any attachment is for authorised use by the intended
> recipient(s) only. It may contain proprietary material, confidential
> information and/or be subject to legal privilege. It should not be
> copied, disclosed to, retained or used by, any other party. If you are
> not an intended recipient then please promptly delete this e-mail and
> any attachment and all copies and inform the sender. Thank you.
Thanks for all the patches, Peter. I have applied all I could except the
filter one, which I explained why below. I'm definitely interested in
search upgrades, but am not sure we want a "filter" object.
I'm not saying that's final, it's just that I first would have to see
what some email/text demo of what a filter object would look like and
how some one would use it. Most likely I would like to see simpler
ways of implementing saved search, even if it's something that simply
saves them in a datastructure and not using the cobbler object system,
that would be ok... perhaps even Bookmarklets?
All of these are applied to the devel branch when I say "Applied". If
there are any fixes to the 1.6.2 search (i.e for bugs, those go against
master).
0001-allow-to-negate-a-compare-in-search.patch
Applied.
0002-log-name-and-prefix-REMOTE-for-remote-api.patch
Applied. The code to add the prefix "REMOTE" is probably not neccessary
because we log cobblerd actions to "cobblerd.log" presently, though I'd
like to eventually fix that to just have one API log in the future. So
this is good.
0003-remove-trailing-newline.patch
Applied.
0004-filter-objects-added.patch.gz
Not applied. In my previous email, I indicated we strongly didn't want
to introduce the concept of a new cobbler "noun" for something like
saved search results. A better way to do this would be to just have a
way to save search parameters in the settings file and let them show up
on the search page, perhaps as hyperlinks. We want to reserve cobbler
"nouns" for data that cobbler is trying to model. The main reason for
all this is that new object types require a tremendous amount of code
(that we eventually want to clean up), and we want to keep things as
simple as possible.
0005-check-for-None-before-checking-for.patch
Applied.
0006-save-dhcp.template-in-devinstall.patch
Applied.
0007-use-field-names-with-underscores.patch
Applied.
0008-use-redirects-to-return-to-list-page-after-operation.patch
This patch does not apply, probably because it requires some of patch
0004, so I could not successfully apply this.
0009-rename-with-same-name-does-nothing-instead-of-deleti.patch
Applied
15 years, 1 month
redirect patch
by Vreman, Peter
Please find attached the redirect patch that doesn't depend on the filtering
Peter
This e-mail and any attachment is for authorised use by the intended recipient(s) only. It may contain proprietary material, confidential information and/or be subject to legal privilege. It should not be copied, disclosed to, retained or used by, any other party. If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender. Thank you.
15 years, 1 month