r4952 - trunk/wooly/python/wooly
by croberts@fedoraproject.org
Author: croberts
Date: 2011-09-07 17:22:59 +0000 (Wed, 07 Sep 2011)
New Revision: 4952
Modified:
trunk/wooly/python/wooly/forms.py
Log:
Changing write_hidden_inputs from using single quotes to double quotes to allow us to be able to handle apostrophe's in strings.
Modified: trunk/wooly/python/wooly/forms.py
===================================================================
--- trunk/wooly/python/wooly/forms.py 2011-09-06 20:06:39 UTC (rev 4951)
+++ trunk/wooly/python/wooly/forms.py 2011-09-07 17:22:59 UTC (rev 4952)
@@ -48,7 +48,7 @@
return writer.to_string()
def write_hidden_input(self, name, value, writer):
- writer.write("<input type='hidden' name='%s' value='%s'/>" \
+ writer.write("<input type=\"hidden\" name=\"%s\" value=\"%s\"/>" \
% (name, value))
class FormError(object):
12 years, 8 months
r4951 - trunk/cumin/python/cumin/grid
by croberts@fedoraproject.org
Author: croberts
Date: 2011-09-06 20:06:39 +0000 (Tue, 06 Sep 2011)
New Revision: 4951
Modified:
trunk/cumin/python/cumin/grid/tags.py
Log:
Now handling both "types" of errors that can come back for configuration activation. There is a map and a list that come back, if all goes well, they will both be empty. Otherwise, the map contains a set of wallaby nodes, which may each contain an error type, which could have a list of features asssociated with it. The list is just a list of warning strings. In either case, the errors will be converted to a FormError object that will bubble-up into a standard cumin form error in the UI.
Modified: trunk/cumin/python/cumin/grid/tags.py
===================================================================
--- trunk/cumin/python/cumin/grid/tags.py 2011-09-06 18:52:39 UTC (rev 4950)
+++ trunk/cumin/python/cumin/grid/tags.py 2011-09-06 20:06:39 UTC (rev 4951)
@@ -322,17 +322,32 @@
def validate(self, session):
results = self.app.wallaby.validate_configuration()
- if len(results[0]) > 0:
- #process the map
- log.info("Results from validate_configuration:")
-
- if len(results[1]) > 0:
- for error in results[1]:
- self.errors.add(session, FormError(error))
- log.info("Results from validate_configuration: %s" % error)
+
+ #handle the set of explanations that could come back if things didn't go well
+ try:
+ if len(results[0]) > 0:
+ error_string = ""
+ for error_host in results[0].keys():
+ for error_type in results[0][error_host].keys():
+ for error in results[0][error_host][error_type]:
+ error_string = error_string + "%s: %s: %s" % (error_host, error_type, error)
+ self.errors.add(session, FormError(error_string))
+ log.info("Results from validate_configuration: %s" % error_string)
+
+ # handle the set of warnings that come back if things didn't go well
+ if len(results[1]) > 0:
+ for error in results[1]:
+ self.errors.add(session, FormError(error))
+ log.info("Results from validate_configuration: %s" % error)
+ return False
+ else:
+ return True
+ except Exception, e:
+ error_msg = "Errors encountered parsing results of configuration activation"
+ log.error(error_msg)
+ self.errors.add(session, FormError(error_msg))
return False
- else:
- return True
+
def render_title(self, session):
''' appears in the top "bar" of the form display '''
12 years, 8 months
r4950 - in trunk/cumin: model python/cumin/grid
by croberts@fedoraproject.org
Author: croberts
Date: 2011-09-06 18:52:39 +0000 (Tue, 06 Sep 2011)
New Revision: 4950
Modified:
trunk/cumin/model/cumin.xml
trunk/cumin/python/cumin/grid/tags.py
Log:
Now using "host" instead of "name" for wallaby nodes.
Modified: trunk/cumin/model/cumin.xml
===================================================================
--- trunk/cumin/model/cumin.xml 2011-09-06 18:44:02 UTC (rev 4949)
+++ trunk/cumin/model/cumin.xml 2011-09-06 18:52:39 UTC (rev 4950)
@@ -55,7 +55,7 @@
</class>
<class name="Node" storage="none">
- <property name="Name" type="sstr"/>
+ <property name="Host" type="sstr"/>
<property name="Tags" type="sstr"/>
<property name="Checkin" type="sstr"/>
<property name="Features" type="sstr"/>
Modified: trunk/cumin/python/cumin/grid/tags.py
===================================================================
--- trunk/cumin/python/cumin/grid/tags.py 2011-09-06 18:44:02 UTC (rev 4949)
+++ trunk/cumin/python/cumin/grid/tags.py 2011-09-06 18:52:39 UTC (rev 4950)
@@ -112,7 +112,7 @@
'''
def process_record(self, key, record):
""" Take the get_data response and process it for viewing by nodes """
- return [record["Name"],record["Tags"],record["Checkin"]]
+ return [record["Host"],record["Tags"],record["Checkin"]]
def do_get_data(self, values):
'''
@@ -122,7 +122,7 @@
wallaby_nodes = self.app.wallaby.get_data(WBTypes.NODES)
data = []
for i, node in enumerate(wallaby_nodes):
- data.append({'Name':node.name, 'Tags':self.app.wallaby.get_tag_names(node), 'Checkin':node.last_checkin})
+ data.append({'Host':node.name, 'Tags':self.app.wallaby.get_tag_names(node), 'Checkin':node.last_checkin})
return data
@@ -234,7 +234,7 @@
# link = TaskLink(app, "node_tag_edit", edit_node_tags_task)
# self.links.add_child(link)
- col = self.NodeColumn(app, "nodecol", cls.Name)
+ col = self.NodeColumn(app, "nodecol", cls.Host)
self.add_column(col)
self.add_search_filter(col)
@@ -324,13 +324,12 @@
results = self.app.wallaby.validate_configuration()
if len(results[0]) > 0:
#process the map
- log.debug("Results from validate_configuration:")
- if len(results[1]) > 0:
- #process the list
- log.debug("Results from validate_configuration: %s" % results[1][0])
+ log.info("Results from validate_configuration:")
if len(results[1]) > 0:
- self.errors.add(session, FormError(results[1][0]))
+ for error in results[1]:
+ self.errors.add(session, FormError(error))
+ log.info("Results from validate_configuration: %s" % error)
return False
else:
return True
@@ -633,7 +632,7 @@
return value
def render_title(self, session):
- return "Node name"
+ return "Host name"
class DisabledInput(StringInput):
pass
@@ -730,7 +729,7 @@
return items
def render_title(self, session):
- return "Update nodes"
+ return "Update hosts"
class NodeName(StringField):
def __init__(self, app, name):
@@ -743,7 +742,7 @@
value = self.input.get(session)
if not value or value == "":
- value = "No nodes currently selected"
+ value = "No hosts currently selected"
return value
@@ -753,7 +752,7 @@
return value
def render_title(self, session):
- return "Current nodes"
+ return "Current hosts"
class DisabledInput(StringInput):
pass
@@ -898,7 +897,7 @@
self.visible = False
def get_title(self, session):
- return "Change tags associated with this node"
+ return "Change tags associated with this host"
def do_enter(self, session, osession):
self.form.tags.set(session, self.form.tags.get(osession))
12 years, 8 months
r4949 - trunk/cumin/python/cumin/grid
by croberts@fedoraproject.org
Author: croberts
Date: 2011-09-06 18:44:02 +0000 (Tue, 06 Sep 2011)
New Revision: 4949
Modified:
trunk/cumin/python/cumin/grid/job.strings
Log:
Lower-casing the 'A' in the "Edit Attributes" button.
Modified: trunk/cumin/python/cumin/grid/job.strings
===================================================================
--- trunk/cumin/python/cumin/grid/job.strings 2011-09-06 17:49:16 UTC (rev 4948)
+++ trunk/cumin/python/cumin/grid/job.strings 2011-09-06 18:44:02 UTC (rev 4949)
@@ -20,7 +20,7 @@
[JobAdsEditButton.html]
<ul class="actions">
- <li><a class="nav" href="{edit_ads_url}">Edit Attributes</a></li>
+ <li><a class="nav" href="{edit_ads_url}">Edit attributes</a></li>
</ul>
[JobAdsGroups.css]
12 years, 8 months
r4948 - trunk/cumin/python/cumin/grid
by croberts@fedoraproject.org
Author: croberts
Date: 2011-09-06 17:49:16 +0000 (Tue, 06 Sep 2011)
New Revision: 4948
Modified:
trunk/cumin/python/cumin/grid/tags.py
Log:
Spelling tweaks for correctness and consistency.
Modified: trunk/cumin/python/cumin/grid/tags.py
===================================================================
--- trunk/cumin/python/cumin/grid/tags.py 2011-09-06 17:47:31 UTC (rev 4947)
+++ trunk/cumin/python/cumin/grid/tags.py 2011-09-06 17:49:16 UTC (rev 4948)
@@ -381,7 +381,7 @@
self.help = "*Comma separated list"
def render_title(self, session):
- return("Tag name(s): ")
+ return("Tag names: ")
class RemoveTags(ObjectTaskForm):
'''
@@ -413,7 +413,7 @@
class TagNamesField(StringField):
def render_title(self, session):
- return("Tag name(s): ")
+ return("Tag names: ")
class TagsList(PageableFilteredSelect):
'''
@@ -651,7 +651,7 @@
def get(self,session):
value = self.input.get(session)
if not value or value == "":
- value = "No tagss currently selected"
+ value = "No tags currently selected"
return value
def render_inputs(self, session, *args):
@@ -1027,7 +1027,7 @@
self.form = CreateTags(app, self.name, self, cls)
def get_title(self, session, object):
- return "Create tag(s)"
+ return "Create tags"
def do_invoke(self, session, object, invoc, tag):
tags = [x.strip() for x in tag.split(',')]
@@ -1088,7 +1088,7 @@
self.form = RemoveTags(app, self.name, self, cls)
def get_title(self, session, object):
- return "Delete tag(s)"
+ return "Delete tags"
def do_invoke(self, session, object, invoc, tags):
try:
12 years, 8 months
r4947 - trunk/cumin/python/cumin
by croberts@fedoraproject.org
Author: croberts
Date: 2011-09-06 17:47:31 +0000 (Tue, 06 Sep 2011)
New Revision: 4947
Modified:
trunk/cumin/python/cumin/objectselector.py
Log:
Correcting spelling of "succeeded"
Modified: trunk/cumin/python/cumin/objectselector.py
===================================================================
--- trunk/cumin/python/cumin/objectselector.py 2011-09-06 14:15:49 UTC (rev 4946)
+++ trunk/cumin/python/cumin/objectselector.py 2011-09-06 17:47:31 UTC (rev 4947)
@@ -661,7 +661,7 @@
error = "There are no %s" % title
if store.status == "OK":
- details = "The call to get the data suceeded, but no results were returned."
+ details = "The call to get the data succeeded, but no results were returned."
else:
details = "The call status is <span>%s</span>" % store.status
self.status_msg.set(session, details)
12 years, 8 months
r4946 - in trunk: cumin/python/cumin/grid wooly/python/wooly
by croberts@fedoraproject.org
Author: croberts
Date: 2011-09-06 14:15:49 +0000 (Tue, 06 Sep 2011)
New Revision: 4946
Modified:
trunk/cumin/python/cumin/grid/tags.py
trunk/wooly/python/wooly/forms.py
trunk/wooly/python/wooly/forms.strings
Log:
Adding functionality to activate the current wallaby configuration. As part of this, I've also created a new "label" class in forms that is used to just show text on a form without an associated value.
Modified: trunk/cumin/python/cumin/grid/tags.py
===================================================================
--- trunk/cumin/python/cumin/grid/tags.py 2011-09-01 15:16:18 UTC (rev 4945)
+++ trunk/cumin/python/cumin/grid/tags.py 2011-09-06 14:15:49 UTC (rev 4946)
@@ -161,6 +161,10 @@
remove_node_tags_task = RemoveNodeTags(app)
link = TaskLink(app, "tag_remove", remove_node_tags_task)
self.links.add_child(link)
+
+ self.activate_config_task = ActivateConfigTask(app)
+ link = TaskLink(app, "actlink", self.activate_config_task)
+ self.links.add_child(link)
col = self.TagColumn(app, "tagcol", cls.Tags)
col.width = "20%"
@@ -170,7 +174,9 @@
col = self.FeatureColumn(app, "featcol", cls.Features)
col.width = "80%"
self.add_column(col)
- #self.add_search_filter(col)
+ #self.add_search_filter(col)
+
+
def render_title(self, session):
return "Tags"
@@ -288,7 +294,59 @@
self.frame.tag.set_tags.form.tags.set(session, tags)
href = self.frame.tag.set_tags.get_href(session)
return fmt_link(href, node_name)
+
+class ActivateConfigurationForm(ObjectTaskForm):
+ '''
+ This form is used to display a button that will trigger activation of the current wallaby configuration.
+ '''
+ def __init__(self, app, name, task, cls):
+ super(ActivateConfigurationForm, self).__init__(app, name, task, cls)
+
+ self.label = self.LabelField(app, "labelf")
+ self.add_field(self.label)
+
+ def render_submit_content(self, session):
+ ''' overriding base method to control the label on the submit button '''
+ return "Activate"
+
+ def process_submit(self, session):
+ if not self.validate(session):
+ log.debug("Wallaby configuration activation errors")
+ # do something to capture error
+ if not self.errors.get(session):
+ # do the actual activation
+ self.task.invoke(session, None)
+ #look at result of invoke....if good, proceed, otherwise might need to ramain on form
+ url = self.return_url.get(session)
+ self.page.redirect.set(session, url)
+
+ def validate(self, session):
+ results = self.app.wallaby.validate_configuration()
+ if len(results[0]) > 0:
+ #process the map
+ log.debug("Results from validate_configuration:")
+ if len(results[1]) > 0:
+ #process the list
+ log.debug("Results from validate_configuration: %s" % results[1][0])
+ if len(results[1]) > 0:
+ self.errors.add(session, FormError(results[1][0]))
+ return False
+ else:
+ return True
+
+ def render_title(self, session):
+ ''' appears in the top "bar" of the form display '''
+ return "Activate wallaby configuration"
+
+ class LabelField(Label):
+ ''' this is just text that appears in place of actual form fields '''
+ def __init__(self, app, name):
+ super(ActivateConfigurationForm.LabelField, self).__init__(app, name)
+ self.text = "Activate your current wallaby configuration? \
+ This will activate all changes (including those made outside of cumin) \
+ since your last activation."
+
class CreateTags(ObjectTaskForm):
'''
This form is used to display a single input field that will handle a comma separated
@@ -930,6 +988,35 @@
invoc.end()
+class ActivateConfigTask(Task):
+ '''
+ This task is used to activate the wallaby configuration.
+ '''
+ def __init__(self, app):
+ super(ActivateConfigTask, self).__init__(app)
+ cls = app.model.com_redhat_cumin_grid.Node
+ self.form = ActivateConfigurationForm(app, self.name, self, cls)
+
+ def get_title(self, session, object):
+ return "Activate wallaby configuration"
+
+ def do_invoke(self, session, object, invoc):
+
+ try:
+ results = self.app.wallaby.activate_configuration()
+ except Exception, e:
+ invoc.status = invoc.FAILED
+ log.exception(e)
+
+ if len(results[0]) > 0:
+ #process the map
+ log.debug("Results from validate_configuration:")
+ if len(results[1]) > 0:
+ #process the list
+ log.debug("Results from validate_configuration: %s" % results[1][0])
+
+ invoc.end()
+
class AddTags(Task):
'''
This task is used to create a tag in wallaby without assigning it to any nodes.
Modified: trunk/wooly/python/wooly/forms.py
===================================================================
--- trunk/wooly/python/wooly/forms.py 2011-09-01 15:16:18 UTC (rev 4945)
+++ trunk/wooly/python/wooly/forms.py 2011-09-06 14:15:49 UTC (rev 4946)
@@ -79,7 +79,7 @@
def render_item_content(self, session, item):
return item.get_message(session)
-
+
class FormInput(Widget):
def __init__(self, app, name, param):
super(FormInput, self).__init__(app, name)
@@ -88,8 +88,6 @@
self.tab_index = 100
self.disabled = False
- self.form = None
-
def init(self):
super(FormInput, self).init()
@@ -365,7 +363,7 @@
def render_help(self, session, *args):
return self.help
-
+
class FormFieldSet(Widget):
def __init__(self, app, name):
super(FormFieldSet, self).__init__(app, name)
@@ -401,6 +399,15 @@
return len(self.fields) and \
super(ShowableFieldSet, self).render(session) or ""
+class Label(FormField):
+ ''' this is a special field, with no values, used to show text on a form '''
+ def __init__(self, app, name):
+ super(Label, self).__init__(app, name)
+ self.text = ""
+
+ def render_value(self, session, *args):
+ return self.text
+
class ScalarField(FormField):
def __init__(self, app, name, input):
super(ScalarField, self).__init__(app, name)
Modified: trunk/wooly/python/wooly/forms.strings
===================================================================
--- trunk/wooly/python/wooly/forms.strings 2011-09-01 15:16:18 UTC (rev 4945)
+++ trunk/wooly/python/wooly/forms.strings 2011-09-06 14:15:49 UTC (rev 4946)
@@ -90,6 +90,9 @@
[RadioInputSet.html]
<ul>{items}</ul>
+[Label.html]
+<span class="{class}">{value}</span>
+
[RadioInputSet.item_html]
<li>
<input type="radio" name="{name}" value="{item_value}" tabindex="{tab_index}" {item_checked_attr} {disabled_attr}/>
12 years, 8 months
r4945 - trunk/cumin/bin
by tmckay@fedoraproject.org
Author: tmckay
Date: 2011-09-01 15:16:18 +0000 (Thu, 01 Sep 2011)
New Revision: 4945
Modified:
trunk/cumin/bin/cumin-admin
Log:
Add "external-user" command in preparation for optional external authentication patch. Zero length password field in User table will indicate external authentication (zero length password in DB previously not possible). This is distinquishable from a password of "" for a regular cumin user, which is crypted to a non-zero length password value in the DB.
Fix up import-users command and list-users to deal with external users.
Without additional (pending) changes, external users can be added but will not authenticate in cumin. This is fine.
This commit is standalone so that the ability to create external users can easily be included in a release or not, thereby gating the entire feature.
Modified: trunk/cumin/bin/cumin-admin
===================================================================
--- trunk/cumin/bin/cumin-admin 2011-09-01 14:17:26 UTC (rev 4944)
+++ trunk/cumin/bin/cumin-admin 2011-09-01 15:16:18 UTC (rev 4945)
@@ -94,6 +94,7 @@
lines.append("User commands:")
lines.append("")
lines.append(" add-user USER [PASSWORD] Add USER")
+ lines.append(" external-user USER Add USER with external authentication")
lines.append(" remove-user USER Remove USER")
lines.append(" add-assignment USER ROLE Add USER to ROLE")
lines.append(" remove-assignment USER ROLE Remove USER from ROLE")
@@ -161,24 +162,43 @@
def handle_list_users(app, cursor, opts, args):
- print " ID Name Roles"
- print "---- -------------------- --------------------"
+ print " ID Name Roles"
+ print "---- -------------------- --------------------"
users, roles_by_user_id = get_users(app, cursor)
-
+ externals = 0
for user in users:
try:
roles = ", ".join(roles_by_user_id[user._id])
except KeyError:
roles = ""
+ if len(user.password) == 0:
+ ex = "*"
+ externals += 1
+ else:
+ ex = " "
+ print "%4i %s %-20s %-20s" % (user._id, ex, user.name, roles)
- print "%4i %-20s %-20s" % (user._id, user.name, roles)
-
count = len(users)
print
print "(%i user%s found)" % (count, ess(count))
+ if externals > 0:
+ print "(%i external user%s, indicated by *)" % (externals, ess(externals))
+def handle_external_user(app, cursor, opts, args):
+ try:
+ name = args[0]
+ except IndexError:
+ error("USER is required")
+ role = app.admin.get_role(cursor, "user")
+ try:
+ user = app.admin.add_user(cursor, name, "")
+ except IntegrityError:
+ error("A user called '%s' already exists" % name)
+ app.admin.add_assignment(cursor, user, role)
+ print "External user '%s' is added" % name
+
def handle_add_user(app, cursor, opts, args):
try:
name = args[0]
@@ -189,18 +209,14 @@
password = args[1]
except IndexError:
password = prompt_password()
-
crypted = crypt_password(password)
role = app.admin.get_role(cursor, "user")
-
try:
user = app.admin.add_user(cursor, name, crypted)
except IntegrityError:
error("A user called '%s' already exists" % name)
-
app.admin.add_assignment(cursor, user, role)
-
print "User '%s' is added" % name
def handle_export_users(app, cursor, opts, args):
@@ -240,15 +256,19 @@
for info in user_data:
line += 1
+ count = 0
for field in info:
# Don't suppose it's possible for data to be anything other than
# strings from csv, but this is where such type checking goes
if type(field) != str:
error("Data error, line %u, fields must be strings" % line)
- if len(field) == 0:
- error("Data error, line %u, importer "\
- "does not allow empty fields" % line)
+ # Empty password field is external auth indicator, allow it
+ if len(field) == 0 and count != 1:
+ error("Data error, line %u, field %u, importer "\
+ "does not allow empty field" % (line, field+1))
+ count += 1
+
if len(info) < 2:
error("Data error, line %u, not enough fields. "\
" User and password are required" % (line))
@@ -263,7 +283,7 @@
# before we get an integrity error
warn("A user called '%s' already exists, skipping" % info[0])
continue
-
+
try:
user = app.admin.add_user(cursor, info[0], info[1])
except IntegrityError:
@@ -284,10 +304,12 @@
error("USER is required")
user = app.admin.get_user(cursor, name)
- user.delete(cursor)
+ if user is None:
+ print "No such user '%s'" % name
+ else:
+ user.delete(cursor)
+ print "User '%s' is removed" % name
- print "User '%s' is removed" % name
-
def handle_list_roles(app, cursor, opts, args):
cls = app.model.com_redhat_cumin.Role
roles = cls.get_selection(cursor)
12 years, 8 months
r4944 - trunk/sage/python/sage/wallaby
by tmckay@fedoraproject.org
Author: tmckay
Date: 2011-09-01 14:17:26 +0000 (Thu, 01 Sep 2011)
New Revision: 4944
Modified:
trunk/sage/python/sage/wallaby/wallabyoperations.py
Log:
Add is_store_valid(), activate_configuration(), validate_configuration().
Better handling of invalid store object in a few places.
Invalidate store object on stop().
Modified: trunk/sage/python/sage/wallaby/wallabyoperations.py
===================================================================
--- trunk/sage/python/sage/wallaby/wallabyoperations.py 2011-08-31 20:30:52 UTC (rev 4943)
+++ trunk/sage/python/sage/wallaby/wallabyoperations.py 2011-09-01 14:17:26 UTC (rev 4944)
@@ -208,6 +208,7 @@
# Clear cache if we have been stopped....
for attr in self._cache:
self._set_cache(attr, [])
+ self._store = None
#end maintain_cache
def get_values(attr, call, *args):
@@ -258,7 +259,7 @@
Note, for the moment start() and stop() are not thread safe. They
should only be called from a single thread.
'''
- if self.maintain_cache is not None:
+ if self._maintain_cache is not None:
self._condition.acquire()
self._stop = True
self._condition.notify()
@@ -412,6 +413,10 @@
Refresh the cached lists of groups and tags.
'''
+ if self._store is None:
+ log.debug("WallabyOperations: create_tag, store object not yet created")
+ return False
+
try:
self._store.addTag(name)
self.refresh(WBTypes.GROUPS,WBTypes.TAGS)
@@ -428,6 +433,10 @@
tag name first. Refresh cached lists of
groups, tags, and nodes.
'''
+ if self._store is None:
+ log.debug("WallabyOperations: remove_tag, store object not yet created")
+ return False
+
if self.get_tag_by_name(name) is not None:
try:
self._store.removeGroup(name)
@@ -528,8 +537,39 @@
self._cache[which].interval = refresh
self._lock.release()
- # Super secret private implementation stuff. Don't look!
+ def activate_configuration(self):
+ '''
+ Call activateConfiguration on the store object.
+ Returns None if the store is not valid, otherwise
+ returns result of store.activateConfiguration.
+ '''
+ if self._store is not None:
+ return self._store.activateConfiguration()
+ else:
+ log.debug("WallabyOperations: activate_configuration," \
+ " store object not yet created")
+ def validate_configuration(self):
+ '''
+ Call validateConfiguration on the store object.
+ Returns None if the store is not valid, otherwise
+ returns result of store.validateConfiguration.
+ '''
+ if self._store is not None:
+ return self._store.validateConfiguration()
+ else:
+ log.debug("WallabyOperations: validate_configuration," \
+ " store object not yet created")
+
+ def is_store_valid(self):
+ '''
+ Return True if contact has been made with the Wallaby agent
+ and a store object has been created.
+ '''
+ return self._store is not None
+
+# Super secret private implementation stuff. Don't look!
+
def _find_min_remaining(self, min):
# None indicates forever, the biggest value
# Note though that None < int is True in Python!
@@ -658,6 +698,9 @@
def get_tag_by_name(self, *args, **kwargs):
return None
+ def get_feature_by_name(self, *args, **kwargs):
+ return None
+
def get_node_names(self, *args, **kwargs):
return []
@@ -673,5 +716,19 @@
def edit_tags(self, *args, **kwargs):
return False
+ def edit_features(self, *args, **kwargs):
+ return False
+
def set_interval(self, *args, **kwargs):
pass
+
+ def activate_configuration(self, *args, **kwargs):
+ return None
+
+ def validate_configuration(self, *args, **kwargs):
+ return None
+
+ def is_store_valid(self):
+ return False
+
+
12 years, 8 months