*** This is the DRAFT VERSION 0.3 ALPHA of the Minimum Common Oncology Data Elements (mCODE™) implementation guide. ***
Tumor and molecular markers are key prognostic factors in calculating cancer staging, identifying treatment options, and monitoring progression of disease. This IG distinguishes tumor marker from genomics as follows:
mCODE identifies a dedicated FHIR profile called TumorMarker for the identification of cancer tumor markers.
mCODE focuses on cancer genomics - the study of the totality of DNA sequence and gene expression differences between tumour cells and normal host cells. It aims to understand the genetic basis of tumour cell proliferation and the evolution of the cancer genome under mutation and selection by the body environment, the immune system and therapeutic interventions (source: Nature).
mCODE will only include the minimal set of genetic related elements relevant to capture in an EHR to drive treatment options.
mCODE aligns with the Sync for Genes approach to adopting a layered-based adoption model. With mCODE's initial emphasis on a minimal set of elements to drive treatment, there is no immediate need to model and store whole sequence reads that would be sent from an NGS labs. Rather, only the relevant genetics labs test results and variant names and interpretation, noted by Sync for Genes as levels 1 and 2, would suffice. Subsequently, the mCODE implementation mapped to the observation-genetics profile as much as possible.
mCODE aligns with the Genetic Test Registry (GTR) as the primary source for identifying genetic tests, assigning the relevant GTR ID to the GeneticMarkerAnalysisResult.code element.
The GeneticMarkerAnalysisResult profile provides an extensible value set of genetic tests related to cancer-linked molecular markers. The initial terms in this value set were curated based on the following filter criteria in the GTR TestVersion data:
The geneticsGene attribute is not bound to a cancer-specific value set at this time. Nevertheless, we provide a recommended value set of cancer-related genes in the CancerGeneVS value set.
The CancerGeneVS value set includes the HUGO approved symbol rather than the full representation of the Gene ID (in the format approved_symbol:identifier). This choice was pragmatic since a certain number of systems store the symbol rather than the non-semantic identifier assigned by HUGO. Nevertheless, the approved symbol for the gene is unique so it is possible to derive the identifier from the HUGO dataset if needed.
References used in the mCODE biomarker model include:


| Module | FunctionalTestHelpers::ClassMethods |
| In: |
lib/functional_test_helpers.rb
|
This module provides basic functional level test helpers to test the various aspects of a controller. Many of these tests will correspond to the standard actions that rails places in a controller. The tests will automatically log in and log out of the application as needed unless instructed not to. If these helpers do not cover a required test that falls outside of the standard patterns, you can leverage the underlying test helper instance methods in FunctionalTestHelpers and build your own. All of the helpers rely on a definition of a DefaultValue at the test class level. This is to be a hash of attribute value pairs that match the model.
Example:
class ItemsControllerTest < ActionController::TestCase DefaultValues = { :name => "Some Name", :location => "123 Main", :color => "Blue" } use_defaults test_index test_new test_create test_show test_edit test_update :name => 'Sum Name' test_destroy test_shouldnt_create :name => nil test_shouldnt_update :name => nil end
Create the test setup method that defines the controller, request, and response instance variables. Then login to the application. To skip the login, pass the symbol :without_login or a hash value of :without_login => true. If you need to do additional steps before or after the setup, use the :prefix hash value. This will prefix the method name with the string passed. Then you can call this generated method anywhere in your own setup method. All other parameters will be passed to FunctionalTestHelpers#login. If you are going to use both the default_setup and default_teardown see use_defaults.
Example:
class ItemsControllerTest < ActionController::TestCase default_setup end
or
class ItemsControllerTest < ActionController::TestCase default_setup :without_login end
# File lib/functional_test_helpers.rb, line 220 220: def default_setup(*args) 221: options = args.last.is_a?(Hash) ? args.last.dup : {} 222: args.each { |arg| options[arg] = true if arg.is_a?(Symbol) } 223: method_name = "#{options[:prefix]}setup".to_sym 224: unless options[:without_login] 225: load_users_fixture 226: define_method(method_name) do 227: @controller = self.class.target.new 228: @request = ActionController::TestRequest.new 229: @response = ActionController::TestResponse.new 230: login options 231: end 232: else 233: define_method(method_name) do 234: @controller = self.class.target.new 235: @request = ActionController::TestRequest.new 236: @response = ActionController::TestResponse.new 237: end 238: end 239: end
Logoff the user after the test unless the :without_login symbol or :without_login => true hash value is passed. If the :without_login parameter is used, an empty teardown will still be generated. If you need to do additional steps before or after the teardown, use the :prefix hash value. This will prefix the method name with the string passed. Then you can call this generated method anywhere in your own teardown method. If you are going to use both the default_setup and default_teardown see use_defaults.
Example:
class ItemsControllerTest < ActionController::TestCase default_teardown end
# File lib/functional_test_helpers.rb, line 254 254: def default_teardown(*args) 255: options = args.last.is_a?(Hash) ? args.last.dup : {} 256: args.each { |arg| options[arg] = true if arg.is_a?(Symbol) } 257: method_name = "#{options[:prefix]}teardown".to_sym 258: unless options[:without_login] 259: define_method(method_name) { logout options } 260: else 261: define_method(method_name) {} 262: end 263: end
Returns the default values to be used in tests. The default values are declared as a constant hash with the name DefaultValues in the test class.
Example:
class ItemsControllerTest < ActionController::TestCase DefaultValues = { :name => "Some Name", :location => "123 Main", :color => "Blue" } def self.default_name default_values[:name] #=> "Some Name" end end
# File lib/functional_test_helpers.rb, line 108 108: def default_values 109: resolve_delayed_fixtures const_get(:DefaultValues) 110: end
Loads the fixtures for the users if they have not already been loaded. The fixtures to be loaded are determined from the user_symbol.
# File lib/functional_test_helpers.rb, line 192 192: def load_users_fixture 193: unless @users_fixture_loaded 194: self.method(:fixtures).call(user_symbol.to_s.pluralize.to_sym) 195: @users_fixture_loaded = true 196: end 197: end
Returns whether or not this is a singleton resource. The default is nil. To define that a resource is a singleton, declare the constant SingletonResource as true in your test class. Alternately you can use the singleton_resource= method as well. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase SingletonResource true def self.the_current_singleton_setting singleton_resource # => true end end
# File lib/functional_test_helpers.rb, line 70 70: def singleton_resource 71: const_defined?(:SingletonResource) ? const_get(:SingletonResource) : @singleton_resource 72: end
Defines the tested resource as a singleton. The default is nil. Normally this is done by setting the constant SingletonResource to true in your test class. However, if for some reason that is not feasible, you may use this setter. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase singleton_resource = true end
# File lib/functional_test_helpers.rb, line 86 86: def singleton_resource=(new_value) 87: @singleton_resource = new_value unless const_defined?(:SingletonResource) 88: end
Returns whether or not the resource being tested is a singleton resource. If the singularity has not been expressly set by the constant SingletonResource or the method single_resource= then this method will attempt to dynamically determine if the resource is a singleton by comparing the singular resource name against the plural. If they match then the resource is considered a singleton. Obviously in the case of irregular nouns like "sheep" this will be incorrect. In that case, explicitly set the singleton to false.
Example:
class ItemsControllerTest < ActionController::TestCase def self.am_I_alone? singleton_resource? #=> false end end
# File lib/functional_test_helpers.rb, line 280 280: def singleton_resource? 281: tester_klass = name.classify.constantize 282: if tester_klass.singleton_resource.nil? 283: if name[0..-15] != name[0..-15].pluralize 284: tester_klass.singleton_resource = true 285: else 286: tester_klass.singleton_resource = false 287: end 288: end 289: tester_klass.singleton_resource 290: end
Returns the target of the test. The default is determined from the name of the test. Thus, ItemsControllerTest becomes ItemsController. To change the target either set the constant Target to the correct controller in your test class or use the target= method. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase def self.what_am_I_testing target #=> ItemsController end end
# File lib/functional_test_helpers.rb, line 305 305: def target(*args) 306: if args.blank? 307: const_defined?(:Target) ? const_get(:Target) : (@target || name[0..-5].classify.constantize) 308: else 309: self.target = args.first 310: end 311: end
Sets the target of the test. The default is determined from the name of the test. Thus, ItemsControllerTest becomes ItemsController. Normally this is done by setting the constant Target to the correct controller in your test class. However, if for some reason that is not feasible, you may use this setter. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase target = ThingsController end
# File lib/functional_test_helpers.rb, line 325 325: def target=(new_value) 326: @target = new_value unless const_defined?(:Target) 327: end
Returns the model that accompanies the controller target of the test. The default is determined from the target. Thus, ItemsController becomes Item. To change the target model either set the constant TargetModel to the correct model in your test class or use the target_model= method. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase def self.what_model_am_I_using target_model #=> Item end end
# File lib/functional_test_helpers.rb, line 342 342: def target_model(*args) 343: if args.blank? 344: const_defined?(:TargetModel) ? const_get(:TargetModel) : (@target_model || target.name[0..-11].classify.constantize) 345: else 346: self.target_model = args.first 347: end 348: end
Sets the model that accompanies the controller target of the test. The default is determined from the target. Thus, ItemsController becomes Item. Normally this is done by setting the constant TargetModel to the correct model in your test class. However, if for some reason that is not feasible, you may use this setter. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase target_model = Thing end
# File lib/functional_test_helpers.rb, line 362 362: def target_model=(new_value) 363: @target_model = new_value unless const_defined?(:TargetModel) 364: end
Returns the human readable name that is used in error messages. The default is determined from the target_model. To change the target name either set the constant TargetName to the correct name in your test class or use the target_name= method. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase def self.what_name_am_I_using target_name #=> "Item" end end
# File lib/functional_test_helpers.rb, line 379 379: def target_name(*args) 380: if args.blank? 381: (const_defined?(:TargetName) ? const_get(:TargetName) : (@target_name || target_model.name.underscore.titleize)).to_s 382: else 383: self.target_name = args.first 384: end 385: end
Sets the human readable name that is used in error messages. The default is determined from the target_model. Normally this is done by setting the constant TargetName to the correct model in your test class. However, if for some reason that is not feasible, you may use this setter. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase target_name = "Some Special Thing" end
# File lib/functional_test_helpers.rb, line 399 399: def target_name=(new_value) 400: @target_name = new_value unless const_defined?(:TargetName) 401: end
Returns the human readable plural name that is used in error messages. The default is determined from the target_name. To change the target name either set the constant TargetNamePlural to the correct plural name in your test class or use the target_name= method. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase def self.what_plural_name_am_I_using target_name #=> "Items" end end
# File lib/functional_test_helpers.rb, line 416 416: def target_name_plural(*args) 417: if args.blank? 418: (const_defined?(:TargetNamePlural) ? const_get(:TargetNamePlural) : (@target_name_plural || target_name.pluralize)).to_s 419: else 420: self.target_name_plural = args.first 421: end 422: end
Sets the human readable plural name that is used in error messages. The default is determined from the target_name. Normally this is done by setting the constant TargetNamePlural to the correct plural name in your test class. However, if for some reason that is not feasible, you may use this setter. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase target_plural_name = "Some Special Things" end
# File lib/functional_test_helpers.rb, line 436 436: def target_name_plural=(new_value) 437: @target_name_plural = new_value unless const_defined?(:TargetNamePlural) 438: end
Returns the symbol name that is used for parameter and assigns checks. The default is determined from the target_model. To change the target name either set the constant TargetSymbol to the correct symbol in your test class or use the target_name= method. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase def self.what_parameter_am_I_using target_symbol #=> :item end end
# File lib/functional_test_helpers.rb, line 453 453: def target_symbol(*args) 454: if args.blank? 455: (const_defined?(:TargetSymbol) ? const_get(:TargetSymbol) : (@target_symbol || target_model.name.underscore)).to_sym 456: else 457: self.target_symbol = args.first 458: end 459: end
Sets the symbol name that is used for parameter and assigns checks. The default is determined from the target_model. Normally this is done by setting the constant TargetSymbol to the correct symbol in your test class. However, if for some reason that is not feasible, you may use this setter. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase target_symbol = :thingamabob end
# File lib/functional_test_helpers.rb, line 473 473: def target_symbol=(new_value) 474: @target_symbol = new_value unless const_defined?(:TargetSymbol) 475: end
Returns the plural symbol name that is used for parameter and assigns checks. The default is determined from the target_symbol. To change the target name either set the constant TargetSymbolPlural to the correct symbol in your test class or use the target_name= method. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase def self.what_plural_parameter_am_I_using target_symbol #=> :items end end
# File lib/functional_test_helpers.rb, line 490 490: def target_symbol_plural(*args) 491: if args.blank? 492: (const_defined?(:TargetSymbolPlural) ? const_get(:TargetSymbolPlural) : (@target_symbol_plural || target_symbol.to_s.pluralize)).to_sym 493: else 494: self.target_symbol_plural = args.first 495: end 496: end
Sets the plural symbol name that is used for parameter and assigns checks. The default is determined from the target_symbol. Normally this is done by setting the constant TargetSymbolPlural to the correct symbol in your test class. However, if for some reason that is not feasible, you may use this setter. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase target_symbol_plural = :thingamabobs end
# File lib/functional_test_helpers.rb, line 510 510: def target_symbol_plural=(new_value) 511: @target_symbol_plural = new_value unless const_defined?(:TargetSymbolPlural) 512: end
Test for standard resource creation using the default values and any additional value hashes given. Each additional hash will be merged with the default values and will result in additional creation checks. The expected redirect after each creation is also checked. If the location is different from the standard, then use the :redirect_to hash value to specify the new desired location. The following example will attempt to create two seperate resources that are only different in color.
Example:
class ItemsControllerTest < ActionController::TestCase DefaultValues = { :name => "Some Name", :location => "123 Main", :color => "Blue" } use_defaults test_create :color => "Red" end
# File lib/functional_test_helpers.rb, line 535 535: def test_create(*values_hashes) 536: values_hashes.unshift default_values 537: define_method("test_should_create_#{target_symbol}".to_sym) do 538: values_hashes.each do |values_hash| 539: assert_kind_of Hash, values_hash, "Cannot test with a #{values_hash.class.name}. Hashes are required. Value given: #{values_hash.inspect}" 540: values_hash = resolve_delayed_fixtures(default_values.merge(values_hash)) 541: old_count = target_model.count if target_model.respond_to?(:count) 542: post :create, target_symbol => values_hash 543: assert_equal old_count+1, target_model.count, "Failed to create a #{target_name} with #{values_hash.inspect}." if target_model.respond_to?(:count) 544: redirect_target = values_hash.delete(:redirect_to) { send("#{target_symbol}_path".to_sym, assigns(target_symbol)) } 545: assert_redirected_to redirect_target 546: end 547: end 548: end
Test for standard resource destruction using the ids or fixture names given. If nothing is given, the fixture labeled :one will be used. The count of the remaining object will be checked. By default this is expected to be one less than what was present before. This can be changed by passing a hash value for :difference. The expected redirect after each creation is also checked. If the location is different from the standard, then use the :redirect_to hash value to specify the new desired location. Arrays can also be used to specify the id, difference, and redirection. The following example will attempt to destroy six seperate resources. Two of them expect differences other than 1.
Example:
class ItemsControllerTest < ActionController::TestCase DefaultValues = { :name => "Some Name", :location => "123 Main", :color => "Blue" } use_defaults test_destroy :this_one, 5, {:id => :that_one, :difference => 8}, 3, [:another, 4], items(:last_one).id end
# File lib/functional_test_helpers.rb, line 573 573: def test_destroy(*ids_and_counts) 574: ids_and_counts.push :one if ids_and_counts.empty? 575: ids_and_counts.map! do |idc| 576: idc = case idc 577: when Array then [idc.first || :one, idc[1] || 1, idc[2]] 578: when Hash then [idc[:id] || :one, idc[:difference] || 1, idc[:redirect_to]] 579: else [idc, 1, nil] 580: end 581: idc[0] = send(target_model.name.tableize.to_sym, idc[0]).id if idc.first.is_a?(Symbol) 582: idc 583: end 584: define_method("test_should_destroy_#{target_symbol}".to_sym) do 585: ids_and_counts.each do |idc| 586: id, count_difference, redirect_target = idc 587: original_id = original_id.is_a?(Symbol) ? "#{original_id.inspect} " : "" 588: id = resolve_delayed_fixtures(id) 589: redirect_target = send("#{target_symbol_plural}_path".to_sym) unless redirect_target 590: old_count = target_model.count if target_model.respond_to?(:count) 591: delete :destroy, :id => id 592: expected_count = old_count - count_difference if target_model.respond_to?(:count) 593: assert_equal expected_count, target_model.count, "Failed to properly destroy #{target_name} #{original_id}(id: #{id}). Expected #{expected_count} items remaining. Found #{target_model.count} instead." if target_model.respond_to?(:count) 594: assert_redirected_to redirect_target, "Failed to destroy #{target_name} #{original_id}with id #{id}." 595: end 596: end 597: end
Test for standard resource edit form using the ids or fixture names given. If nothing is given, the fixture labeled :one will be used.
Example:
class ItemsControllerTest < ActionController::TestCase DefaultValues = { :name => "Some Name", :location => "123 Main", :color => "Blue" } use_defaults test_edit :this_one, :that_one, 5, 7, 1, 3, :another, items(:last_one).id end
# File lib/functional_test_helpers.rb, line 616 616: def test_edit(*ids) 617: ids.push :one if ids.empty? 618: original_ids = ids.dup 619: ids.map! { |id| id.is_a?(Symbol) ? send(target_model.name.tableize.to_sym, id).id : id } 620: define_method("test_should_get_edit_#{target_symbol}".to_sym) do 621: ids.each_with_index do |id, i| 622: original_id = original_ids[i].is_a?(Symbol) ? "#{original_ids[i].inspect} " : "" 623: id = resolve_delayed_fixtures(id) 624: error_message = "Could not edit #{target_name} #{original_id}with id #{id}." 625: get :edit, :id => id 626: assert_response :success, error_message 627: end 628: end 629: end
Test for standard index retrieval and instance variable assignment.
Example:
class ItemsControllerTest < ActionController::TestCase DefaultValues = { :name => "Some Name", :location => "123 Main", :color => "Blue" } use_defaults test_index end
# File lib/functional_test_helpers.rb, line 648 648: def test_index 649: define_method("test_should_get_#{target_symbol_plural}_index".to_sym) do 650: get :index 651: assert_response :success#, "Failed to get #{target_name} index." 652: unless singleton_resource? 653: assert assigns.has_key?(target_symbol_plural.to_s), "@#{target_symbol_plural} was not assigned in the index." 654: else 655: assert assigns.has_key?(target_symbol.to_s), "@#{target_symbol} was not assigned in the index." 656: end 657: end 658: end
Test for standard new resource prototype using the default values and any additional value hashes given. Each additional hash will be merged with the default values and will result in additional prototype checks. The following example will attempt to prototype two seperate resources that are only different in color.
Example:
class ItemsControllerTest < ActionController::TestCase DefaultValues = { :name => "Some Name", :location => "123 Main", :color => "Blue" } use_defaults test_new :color => "Red" end
# File lib/functional_test_helpers.rb, line 679 679: def test_new(*values_hashes) 680: values_hashes.unshift default_values 681: define_method("test_should_get_new_#{target_symbol}".to_sym) do 682: values_hashes.each do |values_hash| 683: assert_kind_of Hash, values_hash, "Cannot test with a #{values_hash.class.name}. Hashes are required. Value given: #{values_hash.inspect}" 684: values_hash = resolve_delayed_fixtures(default_values.merge(values_hash)) 685: get :new, values_hash 686: assert_response :success, "Failed to get a new #{target_name} with values #{values_hash.inspect}." 687: end 688: end 689: end
Test for standard resource creation failure using the value hashes given.. Each hash given will be merged with the default values and will result in additional creation failure checks.
Example:
class ItemsControllerTest < ActionController::TestCase DefaultValues = { :name => "Some Name", :location => "123 Main", :color => "Blue" } use_defaults test_shouldnt_create :name => nil end
# File lib/functional_test_helpers.rb, line 790 790: def test_shouldnt_create(*bad_values_hashes) 791: define_method("test_shouldnt_create_#{target_symbol}".to_sym) do 792: assert bad_values_hashes.size > 0, "Must provide at least one hash of values to test with." 793: bad_values_hashes.each do |bad_values_hash| 794: assert_kind_of Hash, bad_values_hash, "Cannot test with a #{bad_values_hash.class.name}. Hashes are required. Value given: #{bad_values_hash.inspect}" 795: values = resolve_delayed_fixtures(default_values.merge(bad_values_hash)) 796: required_response = values.delete(:assert) { :success } 797: old_count = target_model.count if target_model.respond_to?(:count) 798: post :create, target_symbol => values 799: assert_equal old_count, target_model.count, "Should not have created a #{target_name} with #{values.inspect}." if target_model.respond_to?(:count) 800: assert_response required_response 801: end 802: end 803: end
Test for standard resource update failure using the value hashes given. Each hash will will result in additional update checks. The fixture labeled :one will be the the resource updated. If a different resource is desired, pass an :id hash value.
Example:
class ItemsControllerTest < ActionController::TestCase DefaultValues = { :name => "Some Name", :location => "123 Main", :color => "Blue" } use_defaults test_update :name => nil end
# File lib/functional_test_helpers.rb, line 824 824: def test_shouldnt_update(*bad_values_hashes) 825: define_method("test_shouldnt_update_#{target_symbol}".to_sym) do 826: assert bad_values_hashes.size > 0, "Must provide at least one hash of values to test with." 827: bad_values_hashes.each do |bad_values_hash| 828: assert_kind_of Hash, bad_values_hash, "Cannot test with a #{bad_values_hash.class.name}. Hashes are required. Value given: #{bad_values_hash.inspect}" 829: values = resolve_delayed_fixtures(bad_values_hash) 830: id = values.delete(:id) { send(target_model.name.tableize.to_sym, :one).id } 831: required_response = values.delete(:assert) { :success } 832: old_values = target_model.find(id) 833: post :update, :id => id, target_symbol => values 834: assert_equal old_values, target_model.find(id), "Should not have updated a #{target_name} (id: #{id}) with #{values.inspect}." 835: assert_response required_response 836: end 837: end 838: end
Test for standard resource retrieval using the ids or fixture names given. If nothing is given, the fixture labeled :one will be used.
Example:
class ItemsControllerTest < ActionController::TestCase DefaultValues = { :name => "Some Name", :location => "123 Main", :color => "Blue" } use_defaults test_show :this_one, :that_one, 5, 7, 1, 3, :another, items(:last_one).id end
# File lib/functional_test_helpers.rb, line 708 708: def test_show(*ids) 709: ids.push :one if ids.empty? 710: original_ids = ids.dup 711: ids.map! { |id| id.is_a?(Symbol) ? send(target_model.name.tableize.to_sym, id).id : id } 712: define_method("test_should_show_#{target_symbol}".to_sym) do 713: ids.each_with_index do |id, i| 714: original_id = original_ids[i].is_a?(Symbol) ? "#{original_ids[i].inspect} " : "" 715: id = resolve_delayed_fixtures(id) 716: error_message = "Could not show #{target_name} #{original_id}with id #{id}." 717: get :show, :id => id 718: assert_response :success, error_message 719: end 720: end 721: end
Test for standard resource update using the value hashes given. Each hash will will result in additional update checks. The fixture labeled :one will be the the resource updated. If a different resource is desired, pass an :id hash value. The expected redirect after each update is also checked. If the location is different from the standard, then use the :redirect_to hash value to specify the new desired location.
Example:
class ItemsControllerTest < ActionController::TestCase DefaultValues = { :name => "Some Name", :location => "123 Main", :color => "Blue" } use_defaults test_update :name => "Sum Name" end
# File lib/functional_test_helpers.rb, line 744 744: def test_update(*changed_values_hashes) 745: define_method("test_should_update_#{target_symbol}".to_sym) do 746: assert changed_values_hashes.size > 0, "Must provide at least one hash of values to test with." 747: changed_values_hashes.each do |changed_values_hash| 748: assert_kind_of Hash, changed_values_hash, "Cannot test with a #{changed_values_hash.class.name}. Hashes are required. Value given: #{changed_values_hash.inspect}" 749: values = resolve_delayed_fixtures(changed_values_hash) 750: original_id = values.delete(:id) { :one } 751: if original_id.is_a?(Symbol) 752: id = send(target_model.name.tableize.to_sym, original_id).id 753: original_id = "#{original_id.inspect} " 754: else 755: id = original_id 756: original_id = "" 757: end 758: id = resolve_delayed_fixtures(id) 759: post :update, :id => id, target_symbol => values 760: assert assigns(target_symbol), "Update failed to assign @#{target_symbol} when updating #{target_name} #{original_id}(id: #{id}) with #{values.inspect}." 761: if singleton_resource? 762: redirect_target = changed_values_hash.delete(:redirect_to) { send("#{target_symbol}_path".to_sym) } 763: assert_redirected_to redirect_target, "Failed to update a #{target_name} #{original_id}(id: #{id}) with #{values.inspect}." 764: else 765: redirect_target = changed_values_hash.delete(:redirect_to) { send("#{target_symbol}_path".to_sym, assigns(target_symbol)) } 766: assert_redirected_to redirect_target, "Failed to update a #{target_name} #{original_id}(id: #{id}) with #{values.inspect}." 767: end 768: end 769: end 770: end
Shortcut for specifying both default_setup and default_teardown. Arguments will be passed to both methods.
Example:
class ItemsControllerTest < ActionController::TestCase use_defaults :without_login end
# File lib/functional_test_helpers.rb, line 849 849: def use_defaults(*args) 850: default_setup(*args) 851: default_teardown(*args) 852: end
Returns the model representing the users of the application. The default is User. To change the model used either set the constant UserModel to the correct model in your test class or use the user_model= method. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase UserModel = Plebeian def self.the_model_is user_model #=> Plebeian end end
# File lib/functional_test_helpers.rb, line 127 127: def user_model(*args) 128: if args.blank? 129: const_defined?(:UserModel) ? const_get(:UserModel) : (@user_model || User) 130: else 131: self.user_model = args.first 132: end 133: end
Sets the model representing the users of the application. The default is User. Normally this is done by setting the constant UserModel to the correct model in your test class. However, if for some reason that is not feasible, you may use this setter. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase user_model = Plebeian end
# File lib/functional_test_helpers.rb, line 147 147: def user_model=(new_value) 148: @user_model = new_value unless const_defined?(:UserModel) 149: @users_fixture_loaded = false 150: load_users_fixture 151: end
Returns the symbol for the user model of the test. The default is determined from the user_model. To change the target either set the constant UserSymbol to the correct symbol in your test class or use the user_symbol= method. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase def self.the_symbol_of_the_people user_symbol #=> :user end end
# File lib/functional_test_helpers.rb, line 166 166: def user_symbol(*args) 167: if args.blank? 168: const_defined?(:UserSymbol) ? const_get(:UserSymbol) : (@user_symbol || user_model.name.tableize.singularize.to_sym) 169: else 170: self.target = args.first 171: end 172: end
Sets the symbol for the user model of the test. The default is determined from the user_model. Normally this is done by setting the constant UserSymbol to the correct symbol in your test class. However, if for some reason that is not feasible, you may use this setter. The constant definition takes presence over the attribute.
Example:
class ItemsControllerTest < ActionController::TestCase user_symbol = :plebeian end
# File lib/functional_test_helpers.rb, line 186 186: def user_symbol=(new_value) 187: @user_symbol = new_value unless const_defined?(:UserSymbol) 188: end


Click on the class to get directions
Class List
Update your class list by making class changes below.
Update this course data.


Proof Diagram
Create Node
Attach References
Inference Rule
Reiteration
Or Intro
Or Elim
And Intro
And Elim
Not Intro
Not Elim
Contradiction Intro
Contradiction Elim
Implication Intro
Implication Elim
Biconditional Intro
Biconditional Elim


When it comes to deciding what to transfer and what to discard, a manual migration can be more flexible. Some users may want to keep everything, and others may want to take the opportunity to clean up their drives. Your IT department can have support teams visit users or set up support centers for users to bring their PCs to the support team. Users and the IT department will need to work together in moving the desired files and settings to the updated Windows 10 system.
Whether the manual approach is an option in your organization depends on the scale of your migration. Remember the natural limitations of the time and logistics involved in working directly with users, understanding their needs, and copying files across to their updated workspaces. Some organizations take a standardized approach for all users to make the migration as efficient as possible while meeting business requirements.
For large-scale deployments, you can automate much of the process using task sequence-based automation tools like Microsoft Endpoint Configuration Manager or the Microsoft Deployment Toolkit (MDT). Both these solutions use the User State Migration Tool (USMT) as part of the end-to-end deployment process. USMT, part of the Windows Assessment and Deployment Kit (Windows ADK), captures user accounts, user files, operating system settings, and application settings, and then migrates them to a new Windows installation. It also gives you control of exactly what gets migrated – you can exclude unwanted file types, like audio and video files, or executables.
During the migration process, you need to have sufficient server storage capacity available to act as a temporary migration store, which is where USMT offers two important features:
If you’re performing a PC refresh and not reformatting the primary Windows partition, you also have the option of using a hard-link migration store with USMT. This process preserves the user state on the PC while the old operating system and apps are removed and refreshed. With the restore process coming from the same local partition, this option offers significant improvements in performance and reduces network traffic.
View a video version of the interactive guide (captions available in more languages).
Be sure to click the full-screen option in the video player. When you're done, use the Back arrow in your browser to come back to this page.
If your organization is using OneDrive or is adding OneDrive as part of a deployment, there’s a new option available for migration. Using the cloud to synchronize user files, the OneDrive known folder move feature provides a level of flexibility not possible with local network-based file migration options. If it’s enabled before migration, it provides secure access on new or refreshed PCs, and it eliminates the need to create temporary migration stores on your own servers. It also has the potential to be completely transparent to the user.
Within OneDrive and SharePoint, users can select the folders and locations they want to move to their updated systems, but that puts the burden on the end user. With a known folder move, you as an admin target the documents, desktop, and pictures folders within a user profile and protect it all on OneDrive using Group Policy settings.
Users don’t need to change their workflow – everything looks the same before, during, and after synchronization with OneDrive. Through Group Policy you can choose whether to notify users that their documents, pictures, and desktop are protected in OneDrive, as the process happens in the background. As soon as a user signs into their OneDrive account, these files are restored to their new PC. Using OneDrive also means users can access their files securely at any time from their phones and other devices.
Authentication for OneDrive is powered by Azure Active Directory, so for extra security and to limit network activity, you can enable multi-factor authentication and set policies to control the upload and download bandwidth OneDrive uses.
View a video version of the interactive guide (captions available in more languages).
Be sure to click the full-screen option in the video player. When you're done, use the Back arrow in your browser to come back to this page.


Features
- Practice conjugating verbs in 12 tenses.
- Keep track of your current and best streaks.
- Learn sentence structure and grammar.
- Multiple difficulty settings for students of all levels.
- Track your learning progress for the week, month, or year.
-
Interactive dashboard allows your to visualize your progress.
- See which tenses you know best.
-
Filter answers by tense to focus your studying.
About Us
Daniel Martin
UI Developer
Farjad Fazli
UI Developer
Matheus Silva
React Developer


Knowledge Graphs are gaining in popularity; their ability to merge and connect information from different domains has many applications. However, although the technology has been around for a while, it still does not present interfaces that are easy to use and understand. This workshop aims at bringing HCI and KG communities together to discuss how HCI methods could help identify and overcome the issues that keep Knowledge Graphs from better user interfaces.
Sponsors
Mondeca, Making sense of content
Semantic technology for business problems. Mondeca's software
helps organizations across the private, public and academic
sectors benefit from Semantic Technologies. The systems they offer
make computer systems understand content like text, voice, image
or video. Their products help maintain meaningful business data,
manage enterprise taxonomy, categorize content, define its
subjects, discover items of interests, identify relationships and
much more.
mondeca.com


For each of the field->value pairs in fieldValues, looks up the analyzer mapped to the field from the configured analysis schema, and uses it to perform analysis on the value.
For each of the field->value pairs in fieldValues, looks up the analyzer mapped to the field from the configured analysis schema, and uses it to perform analysis on the value. Returns a map from the fields to the produced token sequences.
Looks up the analyzer mapped to the given field from the configured analysis schema, uses it to perform analysis on the given reader, returning the produced token sequence.
Looks up the analyzer mapped to the given field from the configured analysis schema, uses it to perform analysis on the given string, returning the produced token sequence.
Java-friendly version: for each of the field->value pairs in fieldValues, looks up the analyzer mapped to the field from the configured analysis schema, and uses it to perform analysis on the value.
Java-friendly version: for each of the field->value pairs in fieldValues, looks up the analyzer mapped to the field from the configured analysis schema, and uses it to perform analysis on the value. Returns a map from the fields to the produced token sequences.
Java-friendly version: looks up the analyzer mapped to the given field from the configured analysis schema, uses it to perform analysis on the given reader, returning the produced token sequence.
Java-friendly version: looks up the analyzer mapped to the given field from the configured analysis schema, uses it to perform analysis on the given string, returning the produced token sequence.
For each of the field->multi-value pairs in fieldValues, looks up the analyzer mapped to the field from the configured analysis schema, and uses it to perform analysis on the each of the values.
For each of the field->multi-value pairs in fieldValues, looks up the analyzer mapped to the field from the configured analysis schema, and uses it to perform analysis on the each of the values. Returns a map from the fields to the flattened concatenation of the produced token sequences.
Looks up the analyzer mapped to the given field from the configured analysis schema, uses it to perform analysis on each of the given values, and returns the flattened concatenation of the produced token sequence.
Java-friendly version: for each of the field->multi-value pairs in fieldValues, looks up the analyzer mapped to the field from the configured analysis schema, and uses it to perform analysis on each of the values.
Java-friendly version: for each of the field->multi-value pairs in fieldValues, looks up the analyzer mapped to the field from the configured analysis schema, and uses it to perform analysis on each of the values. Returns a map from the fields to the flattened concatenation of the produced token sequences.
Java-friendly version: looks up the analyzer mapped to the given field from the configured analysis schema, uses it to perform analysis on each of the given values, and returns the flattened concatenation of the produced token sequence.
Returns the analyzer mapped to the given field in the configured analysis schema, if any.
Looks up the analyzer mapped to the given field from the configured analysis schema, uses it to perform analysis on the given reader, and returns a PreAnalyzedField-compatible JSON string with the following serialized attributes:
Looks up the analyzer mapped to the given field from the configured analysis schema, uses it to perform analysis on the given reader, and returns a PreAnalyzedField-compatible JSON string with the following serialized attributes:
- CharTermAttribute (token text), - OffsetAttribute (start and end position) - PositionIncrementAttribute (token position relative to the previous token)
If stored = true, the original reader input value, read into a string, will be included as a value to be stored. (Note that the Solr schema for the destination Solr field must be configured to store the value; if it is not, then the stored value included in the JSON will be ignored by Solr.)
Looks up the analyzer mapped to the given field from the configured analysis schema, uses it to perform analysis on the given string, and returns a PreAnalyzedField-compatible JSON string with the following serialized attributes:
Looks up the analyzer mapped to the given field from the configured analysis schema, uses it to perform analysis on the given string, and returns a PreAnalyzedField-compatible JSON string with the following serialized attributes:
If stored = true, the original string input value will be included as a value to be stored. (Note that the Solr schema for the destination Solr field must be configured to store the value; if it is not, then the stored value included in the JSON will be ignored by Solr.)
Looks up the analyzer mapped to fieldName
and returns a org.apache.lucene.analysis.TokenStream
for the analyzer to tokenize the contents of reader
.
Looks up the analyzer mapped to fieldName
and returns a org.apache.lucene.analysis.TokenStream
for the analyzer to tokenize the contents of text
.
This class allows simple access to custom Lucene text processing pipelines, a.k.a. text analyzers, which are specified via a JSON schema that hosts named analyzer specifications and mappings from field name(s) to analyzer(s).
Here's an example schema with descriptions inline as comments:


Edit the text:
The significant problems we face cannot be solved at the same level of thinking we were at when we created them. —Albert Einstein
Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away. —Antoine de Saint Exupery
If you want to make an apple pie from scratch, you must first create the universe. —Carl Sagan


Vendor Name: |
PITNEY BOWES OF CANADA |
Reference Number: |
4500048072 |
Contract Date: |
2004-07-02 |
Description of Work: |
0533 RENTAL MACHINERY, OFFICE
|
Contract Period: |
7/2/2004 to 6/29/2007 |
Delivery Date: |
|
Contract Value: |
$35,148.60 |
Comments: |
Photocopier Rental |


Start Over
Front-End Quiz
Cascading Style Sheets
Combined Style Sheets
Cascading Short Styles
Concatinated Style Sheets
Cascading Style Sheets
Combined Style Sheets
Cascading Short Styles
Concatinated Style Sheets
Cascading Style Sheets
Combined Style Sheets
Cascading Short Styles
Concatinated Style Sheets
Cascading Style Sheets
Combined Style Sheets
Cascading Short Styles
Concatinated Style Sheets
Cascading Style Sheets
Combined Style Sheets
Cascading Short Styles
Concatinated Style Sheets


| JP GDP - Year on Year * | Actuals | |||||
| Release Date | For period | Kshitij Expectation | Market Expectation | Previous | Released | Revision |
| 7-Dec-17 | Q3 17 2nd Pre | - | - | 1.45% | 2.08% | 1.92% |
| 14-Feb-18 | Q4 17 1st Pre | 1.93% | - | 1.92% | 1.59% | - |
| 8-Mar-18 | Q4 17 2nd Pre | 1.61% | - | 1.59% | 2.06% | - |
| 8-Jun-18 | Q1 18 1st Pre | - | - | 2.06% | - | - |
| Copyright: Kshitij Consultancy Services |


Family Feuding Say It Isn't So
By Ross Anthony
Like "The Mexican," "Say It Isn't So" tries its hand at genre gender blending. In this case, the "American Pie" no-joke-is-too-low, male-oriented comedy is injected with a dose of good old-fashioned female-oriented love story (about 2 parts the former with one part the latter). Even the title chimes like a Freddie Prinze Jr. flick. And like "The Mexican," though not rock solid, this film finds a way to entertain.
The picture starts out with a bang. When dog-catcher Gilly (Chris Klein) joins his boss for a dysfunctional family dinner, insults are passed around the table like appetizers, while topics from sex to nipple-piercing comprise the main course of irreverency. You'll probably embarrass yourself by laughing at such lowbrow humor. After a strong first act in which Gilly falls in love with a lovely, though incompetent hairdresser, things simmer to nearly a lull after we learn a family secret that makes their love impossible. The enjoyment factor later elevates in time for the climax. Will Jo marry the wrong guy in Beaver, Oregon? Or will Gilly with the steadfast assistance of loyal friend "Dig," find a way to set things right?
Shameless, the picture finds its humor anywhere it can - often in genital areas. In fact, I suspect, one spot too hairy for the censors was yanked from the final version. Still, don't let the physical comedy eclipse the clever-er one-liners.
Here are a couple of lines that resonate the funny bone via the skull...
After Gilly's awkward dining experience with the boss' psycho family he suggests, "Maybe you should hire a professional..." The boss responds without missing a beat and stone cold serious, "You mean ... hitman?"
Then after Jo accidentally lops off a chunk of Gill's gill (ear), she invites him to dinner, "What are you doing tonight?"
"Healing mostly." Gill shyly replies.
There's more where those came from, some too obscene to mention here.
Though easily missed because of its genre, the picture and lighting quality are very very sweet.
Some gags drop like dead flies, while others are laugh-out-loud uproarious. In the end, an above average night at the movies.
Say It Isn't So. Copyright © 2001. Rated R. * Starring Chris Klein, Heather Graham, Orlando Jones, Sally Field, Richard Jenkins, John Rothman, Jack Plotnick, Eddie Cibrian. * Directed by J.B. Rogers. * Written by Peter Gaulke & Gerry Swallow. * Produced by Bobby Farrelly, Bradley Thomas, Peter Farrelly at 20th Cent. Fox/Conundrum Ent.
Grade..........................B+
-- Copyright © 2000. Ross Anthony, currently based in Los Angeles, has scripted and shot documentaries, music videos, and shorts in 35 countries across North America, Europe, Africa and Asia.
For more reviews visit: http://www.RossAnthony.com
The review above was posted to the
rec.arts.movies.reviews newsgroup (de.rec.film.kritiken for German reviews).
The Internet Movie Database accepts no responsibility for the contents of the
review and has no editorial control. Unless stated otherwise, the copyright
belongs to the author.
Please direct comments/criticisms of the review to relevant newsgroups.
Broken URLs inthe reviews are the responsibility of the author.
The formatting of the review is likely to differ from the original due
to ASCII to HTML conversion.
Related links: index of all rec.arts.movies.reviews reviews


{% extends "profiles/base_profile_edit.html" %} {% load i18n %} {% block title %}{% trans "API Tokens" %}{% endblock %} {% block profile-admin-tokens %}active{% endblock %} {% block edit_content_header %} {% trans "API Tokens" %} {% endblock %} {% block edit_content %}
{% blocktrans trimmed with<EMAIL_ADDRESS>%} API Tokens are currently an invite-only Beta feature. In case you want to test APIv3 and give us feedback on it, please email us. {% endblocktrans %}
Personal Access Token are tokens that allow you to use the Read the Docs APIv3 being authenticated as yourself. See APIv3 documentation for more information.
{% trans 'No API Tokens currently configured.' %}


Deputies: Man gropes Disney character at Magic Kingdom
by WFTV.comBAY LAKE, Fla. -
A 51-year-old Orlando man groped a Disney character Saturday at Walt Disney World, the Orange County Sheriff's Office said.
Deputies said they were called shortly before 12:15 p.m. to the Magic Kingdom after Brian Thomas Sherman placed his arm around the costumed character's shoulders and groped her breast.
Sherman and his wife were escorted into a meet and greet area, and they sat on either side of the victim, an arrest report said.
The report said Sherman sat down beside the victim more quickly than she expected.
"This left the victim physically stuck in between the defendant on her left and his wife on her right," according to the report.
The report said Sherman repeatedly told the victim that the character she was playing is his favorite, and he placed his arm around her shoulders.
The victim said she was trained to know that it is inappropriate to be photographed with a visitor's arm wrapped around her and that she was uncomfortable but was unable to move, the report said.
It said Sherman moved his arm lower so that he could cup the victim's bra with his hand.
A co-worker could tell that the victim was uncomfortable and told Sherman to change his pose, but he cupped and lifted her breast for several seconds, the report said.
"When the defendant left the room, the victim began shaking and crying," the report said.
Deputies said Sherman was identified through a picture taken by a Disney photographer.
He was booked into the Orange County Jail on charges of battery.
Records said Sherman was convicted in 1991 of sexual battery on a victim under 12 in Polk County.
Anyone else whom Sherman might have inappropriately touched is asked to call the Sheriff's Office at<PHONE_NUMBER>.


Hangman Game!!
PRESS ANY KEY TO GUESS WHO THESE ONE-NAMED CELEBS ARE
Guesses Remaining
Current Word
Letters Guessed


Links
A linear regulator
http://www.sparkfun.com/commerce/product_info.php?products_id=107
Sparkfun tutorial on howto getting regulated from un-regulated
http://www.sparkfun.com/commerce/tutorial_info.php?tutorials_id=57
Tutorial from Sparkfun
http://www.sparkfun.com/commerce/tutorial_info.php?tutorials_id=103
Explanation of Unregulated
http://www.apogeekits.com/power_adapter_selection.htm


Congrats, you are now up and running!
This is a highly opinionated set of boilerplate code for starting off any
kind of project utilising the MEAN stack
(MongoDB,
Express,
AngularJS and
Node.js).
Aims
- Create a set of reusable components that are applicable to most projects (parts can easily be removed if you don't want them).
- Create a logical and well thought out file structure that makes it easy to find the right piece of code.
- Minimise require() on the backend as much as possible. So many node projects start off every file with a dozen lines of requiring other files - this is gross!
- Minimise the task of writing boilerplate code to add new functionality to be as simple and enjoyable as possible.
- Implement a truly stateless backend REST API - all templating is done via AngularJS and there are no sessions involved thanks to JWT.
- Promises everywhere via bluebird. Having to use the async library for control flow feels a lot clunkier compared to just using promises.
Features
- Automatic file watching, code linting and build process via Gulp.
- Command line utility via commander.
- Crons and background workers thanks to Kue and Node Cron
- Angular inspired dependency injection but on the backend server thanks to Express DI and Dependable
- Translation on both the frontend and backend thanks to i18n-2 and angular-translate.
- Mongo ODM thanks to Mongoose
- Server logging via Winston and frontend errors logged via exceptions.js
- Frontend AngularJS routing powered by the ui-router
- Styling via LESS and Bootstrap
- Improved AngularJS controllers via angular classy
- Frontend data store and model system powered by angular-data
- And much more... (still to add)


all challenges
Baby's First
1: babycmd
1: babyecho
1: mathwhiz
1: r0pbaby
Coding Challenge
1: catwestern
Pwnable
2: cybergrandsandbox
2: wibbly wobbly timey wimey
3: fuckup
3: twentyfiveseventy
4: heapsoffun
4: tensixtyseven
4: thing2
5: hackercalc
5: int3rupted
6: secrf
Reverse Engineering
1: access control
1: knockedupd
2: pr0dk3y
3: Scrambler
3: klug
3: shitcpu
Web
2: Waiting for your Touch
Miscellaneous
2: blackbox
3: patcher


{% extends "global/Page.html" %} {% load otree static %} {% block title %} Feedback {% endblock %} {% block content %} {% if player.id_in_group == 1 %}
Thank you for participating in this study, your bonus amount will be determined after your worker has finished working on the task. Please note that any bonus payment must be approved before they are given. Your bonus amount (if any) will be paid in 24 hours.
{% formfield player.Feedback label="Did you have any questions, concerns or comments about this study? If so, enter them here. " %} {% else %}Thank you for participating in this experiment, Here is the summary of what happened in the experiment.
Bonus rate = {{group.piece_rate}} per 100 points scored
Points = {{group.points}}
{% if group.treatment == 'Three Stage' or group.treatment == 'Race Salient & Three Stage' %}Reward = {% if group.points > group.target_points %} {{reward}} {% else %} 0 {% endif %}
{% endif %}Your bonus payout = {{player.payoff}}
Your boss's bonus payout = {{player.get_partner.payoff}}
Please note that any bonus payment must be approved before they are given. Your bonus amount (if any) will be paid in 24 hours.
{% formfield player.Feedback label="Did you have any questions, concerns or comments about this study? If so, enter them here." %} {% endif %}On the next screen, you will be given a survey code that you must enter into the textbox on Mechanical Turk to get paid.
{% next_button %} {% endblock %}


Spain: Court extends jail for ex-colonel in priests' deaths
by Associated PressMADRID (AP) - Spain's National Court has extended the detention period for a former Salvadoran colonel who was allegedly involved in the massacre of five Spanish priests in El Salvador in 1989.
The court said Thursday that Inocente Orlando Montano could be kept in jail for another two years while his trial is prepared. It cited the seriousness of the charges and the risk of him fleeing if released.
The United States extradited Montano to Spain in 2017 to face charges of terrorist murder and crimes against humanity in the deaths of the priests. Montano served as vice minister for public security in the 1980s during El Salvador's civil war.
Father Ignacio Ellacuria and the other priests were helping organize peace talks to end the war. Their housekeeper and her daughter were also killed.
Copyright 2019 The Associated Press. All rights reserved. This material may not be published, broadcast, rewritten or redistributed.


Samsung Mobile Computing IoT Platform is an information exchanging platform which provides intellectual services based on analytic data of the surrounding environment collected from connected objects and people.Samsung IoT Platform provides standardized connections between various devices on smart device or hub. It simplifies new service development for developers and partners by collecting and processing all kinds of data (service data, sensor data, etc) from users’ IoT related services.Developers can use Samsung IoT Platform commonly applied to Samsung’s future smart devices such as smartphones or smart appliances to easily develop services. Developers do not need to analyze or setup the complex infrastructure of inter-device connectivity or user data on cloud storage. They can also minimize the trial and error process of operating a system for large scale clients.


|
Billiard
1
A Gym Environment with a ball pushing arm
|
Public Member Functions | |
| def | __init__ (self, seed=None, max_steps=500) |
| def | seed (self, seed=None) |
| def | reset (self) |
| def | arm_ball1_contacts (self) |
| def | step (self, action) |
| def | render (self, mode='human') |
Public Attributes | |
| screen | |
| params | |
| physics_eng | |
| observation_space | |
| Ball XY positions can be between -1.5 and 1.5. More... | |
| action_space | |
| Joint commands can be between [-1, 1]. More... | |
| steps | |
| ball0_in_hole | |
| ball1_in_hole | |
| state | |
| clock | |
Static Public Attributes | |
| dictionary | metadata |
The goal is to send first ball 1 and then ball 0 in the holes. If the arm touches ball 1, is considered as failure. State is composed of: s = ([ball0_x, ball0_y], [ball1_x, ball1_y], [joint0_angle, joint1_angle], [joint0_speed, joint1_speed]) The values that these components can take are: ball_x, ball_y -> [-1.5, 1.5] joint0_angle -> [-pi/2, pi/2] joint1_angle -> [-pi, pi] joint0_speed, joint1_speed -> [-50, 50]
| def gym_billiard.envs.billiard_hard_env.BilliardHardEnv.__init__ | ( | self, | |
seed = None , |
|||
max_steps = 500 |
|||
| ) |
Constructor :param seed: the random seed for the environment :param max_steps: the maximum number of steps the episode lasts :return:
| def gym_billiard.envs.billiard_hard_env.BilliardHardEnv.arm_ball1_contacts | ( | self | ) |
This function checks what is having contacts with ball1. :return: True if arm touches the ball
| def gym_billiard.envs.billiard_hard_env.BilliardHardEnv.render | ( | self, | |
mode = 'human' |
|||
| ) |
Rendering function :param mode: if human, renders on screen. If rgb_array, renders as numpy array :return: screen if mode=human, array if mode=rgb_array
| def gym_billiard.envs.billiard_hard_env.BilliardHardEnv.reset | ( | self | ) |
Function to reset the environment. - If param RANDOM_BALL_INIT_POSE is set, the ball appears in a random pose, otherwise ball0 will appear at [-0.5, 0.2] and ball1 at [0, 1] - If param RANDOM_ARM_INIT_POSE is set, the arm joint positions will be set randomly, otherwise they will have [0, 0] :return: Initial observation
| def gym_billiard.envs.billiard_hard_env.BilliardHardEnv.seed | ( | self, | |
seed = None |
|||
| ) |
Function to seed the environment :param seed: The random seed :return: [seed]
| def gym_billiard.envs.billiard_hard_env.BilliardHardEnv.step | ( | self, | |
| action | |||
| ) |
Performs an environment step. :param action: Arm Motor commands. Can be either torques or velocity, according to TORQUE_CONTROL parameter :return: state, reward, final, info
| gym_billiard.envs.billiard_hard_env.BilliardHardEnv.action_space |
Joint commands can be between [-1, 1].
| gym_billiard.envs.billiard_hard_env.BilliardHardEnv.ball0_in_hole |
| gym_billiard.envs.billiard_hard_env.BilliardHardEnv.ball1_in_hole |
| gym_billiard.envs.billiard_hard_env.BilliardHardEnv.clock |
|
static |
| gym_billiard.envs.billiard_hard_env.BilliardHardEnv.observation_space |
Ball XY positions can be between -1.5 and 1.5.
Arm joint can have positons: Joint 0: [-Pi/2, Pi/2] Joint 1: [-Pi, Pi]
| gym_billiard.envs.billiard_hard_env.BilliardHardEnv.params |
| gym_billiard.envs.billiard_hard_env.BilliardHardEnv.physics_eng |
| gym_billiard.envs.billiard_hard_env.BilliardHardEnv.screen |
| gym_billiard.envs.billiard_hard_env.BilliardHardEnv.state |
| gym_billiard.envs.billiard_hard_env.BilliardHardEnv.steps |


4 references to Disconnecting
System.Management.Automation (4)
engine\hostifaces\LocalConnection.cs (1)
1426
case RunspaceState.
Disconnecting
:
engine\hostifaces\RunspacePool.cs (1)
167
return RunspaceState.
Disconnecting
;
engine\remoting\commands\ConnectPSSession.cs (1)
621
eArgs.RunspaceStateInfo.State == RunspaceState.
Disconnecting
||
engine\remoting\commands\DisconnectPSSession.cs (1)
445
if (eArgs.RunspaceStateInfo.State == RunspaceState.
Disconnecting
)


Class 1 Lab
Let's find out a little about you.
What's your name?
What's your favorite ice cream flavor?
What's your favorite movie?
What's your favorite day of the week?
Let's find out a little about you.
What's your name?
What's your favorite ice cream flavor?
What's your favorite movie?
What's your favorite day of the week?


Many tutorials cover the basics of OpenFlow. This is not such a tutorial. Rather, a knowledge of the basics of OpenFlow is a prerequisite. If you do not already understand how an OpenFlow flow table works, please go read a basic tutorial and then continue reading here afterward.
It is also important to understand the basics of Open vSwitch before
you begin. If you have never used ovs-vsctl
or ovs-ofctl
before,
you should learn a little about them before proceeding.
Most of the features covered in this tutorial are Open vSwitch extensions to OpenFlow. Also, most of the features in this tutorial are specific to the software Open vSwitch implementation. If you are using an Open vSwitch port to an ASIC-based hardware switch, this tutorial will not help you.
This tutorial does not cover every aspect of the features that it
mentions. You can find the details elsewhere in the Open vSwitch
documentation, especially ovs-ofctl(8)
and the comments in the
include/openflow/nicira-ext.h
header file.
In this tutorial, paragraphs set off like this designate notes with additional information that readers may wish to skip on a first read.
This is a hands-on tutorial. To get the most out of it, you will need
Open vSwitch binaries. You do not, on the other hand, need any
physical networking hardware or even supervisor privilege on your
system. Instead, we will use a script called ovs-sandbox
, which
accompanies the tutorial, that constructs a software simulated network
environment based on Open vSwitch.
You can use ovs-sandbox
three ways:
If you have already installed Open vSwitch on your system, then
you should be able to just run ovs-sandbox
from this directory
without any options.
If you have not installed Open vSwitch (and you do not want to
install it), then you can build Open vSwitch according to the
instructions in [INSTALL.md], without installing it. Then run
./ovs-sandbox -b DIRECTORY
from this directory, substituting
the Open vSwitch build directory for DIRECTORY
.
As a slight variant on the latter, you can run make sandbox
from an Open vSwitch build directory.
When you run ovs-sandbox
, it does the following:
CAUTION: Deletes any subdirectory of the current directory named "sandbox" and any files in that directory.
Creates a new directory "sandbox" in the current directory.
Sets up special environment variables that ensure that Open vSwitch programs will look inside the "sandbox" directory instead of in the Open vSwitch installation directory.
If you are using a built but not installed Open vSwitch,
installs the Open vSwitch manpages in a subdirectory of
"sandbox" and adjusts the MANPATH
environment variable to point
to this directory. This means that you can use, for example,
man ovs-vsctl
to see a manpage for the ovs-vsctl
program that
you built.
Creates an empty Open vSwitch configuration database under "sandbox".
Starts ovsdb-server
running under "sandbox".
Starts ovs-vswitchd
running under "sandbox", passing special
options that enable a special "dummy" mode for testing.
Starts a nested interactive shell inside "sandbox".
At this point, you can run all the usual Open vSwitch utilities from
the nested shell environment. You can, for example, use ovs-vsctl
to create a bridge:
ovs-vsctl add-br br0
From Open vSwitch's perspective, the bridge that you create this way
is as real as any other. You can, for example, connect it to an
OpenFlow controller or use ovs-ofctl
to examine and modify it and
its OpenFlow flow table. On the other hand, the bridge is not visible
to the operating system's network stack, so ifconfig
or ip
cannot
see it or affect it, which means that utilities like ping
and
tcpdump
will not work either.
When you're done using OVS from the sandbox, exit the nested shell (by
entering the "exit" shell command or pressing Control+D). This will
kill the daemons that ovs-sandbox
started, but it leaves the "sandbox"
directory and its contents in place.
The sandbox directory contains log files for the Open vSwitch dameons. You can examine them while you're running in the sandboxed environment or after you exit.
GDB support is not required to go through the tutorial. It is added in case user wants to explore the internals of OVS programs.
GDB can already be used to debug any running process, with the usual
'gdb
'ovs-sandbox' also has a '-g' option for launching ovs-vswitchd under GDB. This option can be handy for setting break points before ovs-vswitchd runs, or for catching early segfaults. Similarly, a '-d' option can be used to run ovsdb-server under GDB. Both options can be specified at the same time.
In addition, a '-e' option also launches ovs-vswitchd under GDB. However, instead of displaying a 'gdb>' prompt and waiting for user input, ovs-vswitchd will start to execute immediately. '-r' option is the corresponding option for running ovsdb-server under gdb with immediate execution.
To avoid GDB mangling with the sandbox sub shell terminal, 'ovs-sandbox' starts a new xterm to run each GDB session. For systems that do not support X windows, GDB support is effectively disabled.
When launching sandbox through the build tree's make file, the '-g' option can be passed via the 'SANDBOXFLAGS' environment variable. 'make sandbox SANDBOXFLAGS=-g' will start the sandbox with ovs-vswitchd running under GDB in its own xterm if X is available.
The goal of this tutorial is to demonstrate the power of Open vSwitch flow tables. The tutorial works through the implementation of a MAC-learning switch with VLAN trunk and access ports. Outside of the Open vSwitch features that we will discuss, OpenFlow provides at least two ways to implement such a switch:
An OpenFlow controller to implement MAC learning in a "reactive" fashion. Whenever a new MAC appears on the switch, or a MAC moves from one switch port to another, the controller adjusts the OpenFlow flow table to match.
The "normal" action. OpenFlow defines this action to submit a packet to "the traditional non-OpenFlow pipeline of the switch". That is, if a flow uses this action, then the packets in the flow go through the switch in the same way that they would if OpenFlow was not configured on the switch.
Each of these approaches has unfortunate pitfalls. In the first approach, using an OpenFlow controller to implement MAC learning, has a significant cost in terms of network bandwidth and latency. It also makes the controller more difficult to scale to large numbers of switches, which is especially important in environments with thousands of hypervisors (each of which contains a virtual OpenFlow switch). MAC learning at an OpenFlow controller also behaves poorly if the OpenFlow controller fails, slows down, or becomes unavailable due to network problems.
The second approach, using the "normal" action, has different problems. First, little about the "normal" action is standardized, so it behaves differently on switches from different vendors, and the available features and how those features are configured (usually not through OpenFlow) varies widely. Second, "normal" does not work well with other OpenFlow actions. It is "all-or-nothing", with little potential to adjust its behavior slightly or to compose it with other features.
We will construct Open vSwitch flow tables for a VLAN-capable, MAC-learning switch that has four ports:
p1, a trunk port that carries all VLANs, on OpenFlow port 1.
p2, an access port for VLAN 20, on OpenFlow port 2.
p3 and p4, both access ports for VLAN 30, on OpenFlow ports 3 and 4, respectively.
The ports' names are not significant. You could call them eth1 through eth4, or any other names you like.
An OpenFlow switch always has a "local" port as well. This scenario won't use the local port.
Our switch design will consist of five main flow tables, each of which implements one stage in the switch pipeline:
Table 0: Admission control.
Table 1: VLAN input processing.
Table 2: Learn source MAC and VLAN for ingress port.
Table 3: Look up learned port for destination MAC and VLAN.
Table 4: Output processing.
The section below describes how to set up the scenario, followed by a section for each OpenFlow table.
You can cut and paste the ovs-vsctl
and ovs-ofctl
commands in each
of the sections below into your ovs-sandbox
shell. They are also
available as shell scripts in this directory, named t-setup
, t-stage0
,
t-stage1
, ..., t-stage4
. The ovs-appctl
test commands are intended
for cutting and pasting and are not supplied separately.
To get started, start ovs-sandbox
. Inside the interactive shell
that it starts, run this command:
ovs-vsctl add-br br0 -- set Bridge br0 fail-mode=secure
This command creates a new bridge "br0" and puts "br0" into so-called "fail-secure" mode. For our purpose, this just means that the OpenFlow flow table starts out empty.
If we did not do this, then the flow table would start out with a single flow that executes the "normal" action. We could use that feature to yield a switch that behaves the same as the switch we are currently building, but with the caveats described under "Motivation" above.)
The new bridge has only one port on it so far, the "local port" br0. We need to add p1, p2, p3, and p4. A shell "for" loop is one way to do it:
for i in 1 2 3 4; do
ovs-vsctl add-port br0 p$i -- set Interface p$i ofport_request=$i
ovs-ofctl mod-port br0 p$i up
done
In addition to adding a port, the ovs-vsctl
command above sets its
"ofport_request" column to ensure that port p1 is assigned OpenFlow
port 1, p2 is assigned OpenFlow port 2, and so on.
We could omit setting the ofport_request and let Open vSwitch choose port numbers for us, but it's convenient for the purposes of this tutorial because we can talk about OpenFlow port 1 and know that it corresponds to p1.
The ovs-ofctl
command above brings up the simulated interfaces, which
are down initially, using an OpenFlow request. The effect is similar
to ifconfig up
, but the sandbox's interfaces are not visible to the
operating system and therefore ifconfig
would not affect them.
We have not configured anything related to VLANs or MAC learning. That's because we're going to implement those features in the flow table.
To see what we've done so far to set up the scenario, you can run a
command like ovs-vsctl show
or ovs-ofctl show br0
.
Table 0 is where packets enter the switch. We use this stage to discard packets that for one reason or another are invalid. For example, packets with a multicast source address are not valid, so we can add a flow to drop them at ingress to the switch with:
ovs-ofctl add-flow br0 \
"table=0, dl_src=01:00:00:00:00:00/01:00:00:00:00:00, actions=drop"
A switch should also not forward IEEE 802.1D Spanning Tree Protocol (STP) packets, so we can also add a flow to drop those and other packets with reserved multicast protocols:
ovs-ofctl add-flow br0 \
"table=0, dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0, actions=drop"
We could add flows to drop other protocols, but these demonstrate the pattern.
We need one more flow, with a priority lower than the default, so that flows that don't match either of the "drop" flows we added above go on to pipeline stage 1 in OpenFlow table 1:
ovs-ofctl add-flow br0 "table=0, priority=0, actions=resubmit(,1)"
(The "resubmit" action is an Open vSwitch extension to OpenFlow.)
If we were using Open vSwitch to set up a physical or a virtual
switch, then we would naturally test it by sending packets through it
one way or another, perhaps with common network testing tools like
ping
and tcpdump
or more specialized tools like Scapy. That's
difficult with our simulated switch, since it's not visible to the
operating system.
But our simulated switch has a few specialized testing tools. The
most powerful of these tools is ofproto/trace
. Given a switch and
the specification of a flow, ofproto/trace
shows, step-by-step, how
such a flow would be treated as it goes through the switch.
Try this command:
ovs-appctl ofproto/trace br0 in_port=1,dl_dst=01:80:c2:00:00:05
The output should look something like this:
Flow: metadata=0,in_port=1,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=01:80:c2:00:00:05,dl_type=0x0000
Rule: table=0 cookie=0 dl_dst=01:80:c2:00:00:00/ff:ff:ff:ff:ff:f0
OpenFlow actions=drop
Final flow: unchanged
Datapath actions: drop
The first block of lines describes an OpenFlow table lookup. The first line shows the fields used for the table lookup (which is mostly zeros because that's the default if we don't specify everything). The second line gives the OpenFlow flow that the fields matched (called a "rule" because that is the name used inside Open vSwitch for an OpenFlow flow). In this case, we see that this packet that has a reserved multicast destination address matches the rule that drops those packets. The third line gives the rule's OpenFlow actions.
The second block of lines summarizes the results, which are not very interesting here.
Try another command:
ovs-appctl ofproto/trace br0 in_port=1,dl_dst=01:80:c2:00:00:10
The output should be:
Flow: metadata=0,in_port=1,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=01:80:c2:00:00:10,dl_type=0x0000
Rule: table=0 cookie=0 priority=0
OpenFlow actions=resubmit(,1)
Resubmitted flow: unchanged
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
Resubmitted odp: drop
No match
Final flow: unchanged
Datapath actions: drop
This time the flow we handed to ofproto/trace
doesn't match any of
our "drop" rules, so it falls through to the low-priority "resubmit"
rule, which we see in the rule and the actions selected in the first
block. The "resubmit" causes a second lookup in OpenFlow table 1,
described by the additional block of indented text in the output. We
haven't yet added any flows to OpenFlow table 1, so no flow actually
matches in the second lookup. Therefore, the packet is still actually
dropped, which means that the externally observable results would be
identical to our first example.
A packet that enters table 1 has already passed basic validation in table 0. The purpose of table 1 is validate the packet's VLAN, based on the VLAN configuration of the switch port through which the packet entered the switch. We will also use it to attach a VLAN header to packets that arrive on an access port, which allows later processing stages to rely on the packet's VLAN always being part of the VLAN header, reducing special cases.
Let's start by adding a low-priority flow that drops all packets, before we add flows that pass through acceptable packets. You can think of this as a "default drop" rule:
ovs-ofctl add-flow br0 "table=1, priority=0, actions=drop"
Our trunk port p1, on OpenFlow port 1, is an easy case. p1 accepts any packet regardless of whether it has a VLAN header or what the VLAN was, so we can add a flow that resubmits everything on input port 1 to the next table:
ovs-ofctl add-flow br0 \
"table=1, priority=99, in_port=1, actions=resubmit(,2)"
On the access ports, we want to accept any packet that has no VLAN header, tag it with the access port's VLAN number, and then pass it along to the next stage:
ovs-ofctl add-flows br0 - <<'EOF'
table=1, priority=99, in_port=2, vlan_tci=0, actions=mod_vlan_vid:20, resubmit(,2)
table=1, priority=99, in_port=3, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)
table=1, priority=99, in_port=4, vlan_tci=0, actions=mod_vlan_vid:30, resubmit(,2)
EOF
We don't write any rules that match packets with 802.1Q that enter this stage on any of the access ports, so the "default drop" rule we added earlier causes them to be dropped, which is ordinarily what we want for access ports.
Another variation of access ports allows ingress of packets tagged with VLAN 0 (aka 802.1p priority tagged packets). To allow such packets, replace "vlantci=0" by "vlantci=0/0xfff" above.
ofproto/trace
allows us to test the ingress VLAN rules that we added
above.
Here's a test of a packet coming in on the trunk port:
ovs-appctl ofproto/trace br0 in_port=1,vlan_tci=5
The output shows the lookup in table 0, the resubmit to table 1, and the resubmit to table 2 (which does nothing because we haven't put anything there yet):
Flow: metadata=0,in_port=1,vlan_tci=0x0005,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
Rule: table=0 cookie=0 priority=0
OpenFlow actions=resubmit(,1)
Resubmitted flow: unchanged
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
Resubmitted odp: drop
Rule: table=1 cookie=0 priority=99,in_port=1
OpenFlow actions=resubmit(,2)
Resubmitted flow: unchanged
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
Resubmitted odp: drop
No match
Final flow: unchanged
Datapath actions: drop
Here's a test of a valid packet (a packet without an 802.1Q header) coming in on access port p2:
ovs-appctl ofproto/trace br0 in_port=2
The output is similar to that for the previous case, except that it additionally tags the packet with p2's VLAN 20 before it passes it along to table 2:
Flow: metadata=0,in_port=2,vlan_tci=0x0000,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
Rule: table=0 cookie=0 priority=0
OpenFlow actions=resubmit(,1)
Resubmitted flow: unchanged
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
Resubmitted odp: drop
Rule: table=1 cookie=0 priority=99,in_port=2,vlan_tci=0x0000
OpenFlow actions=mod_vlan_vid:20,resubmit(,2)
Resubmitted flow: metadata=0,in_port=2,dl_vlan=20,dl_vlan_pcp=0,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
Resubmitted odp: drop
No match
Final flow: unchanged
Datapath actions: drop
This tests an invalid packet (one that includes an 802.1Q header) coming in on access port p2:
ovs-appctl ofproto/trace br0 in_port=2,vlan_tci=5
The output shows the packet matching the default drop rule:
Flow: metadata=0,in_port=2,vlan_tci=0x0005,dl_src=00:00:00:00:00:00,dl_dst=00:00:00:00:00:00,dl_type=0x0000
Rule: table=0 cookie=0 priority=0
OpenFlow actions=resubmit(,1)
Resubmitted flow: unchanged
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
Resubmitted odp: drop
Rule: table=1 cookie=0 priority=0
OpenFlow actions=drop
Final flow: unchanged
Datapath actions: drop
This table allows the switch we're implementing to learn that the packet's source MAC is located on the packet's ingress port in the packet's VLAN.
This table is a good example why table 1 added a VLAN tag to packets that entered the switch through an access port. We want to associate a MAC+VLAN with a port regardless of whether the VLAN in question was originally part of the packet or whether it was an assumed VLAN associated with an access port.
It only takes a single flow to do this. The following command adds it:
ovs-ofctl add-flow br0 \
"table=2 actions=learn(table=10, NXM_OF_VLAN_TCI[0..11], \
NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[], \
load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]), \
resubmit(,3)"
The "learn" action (an Open vSwitch extension to OpenFlow) modifies a flow table based on the content of the flow currently being processed. Here's how you can interpret each part of the "learn" action above:
table=10
Modify flow table 10. This will be the MAC learning table.
NXM_OF_VLAN_TCI[0..11]
Make the flow that we add to flow table 10 match the same VLAN
ID that the packet we're currently processing contains. This
effectively scopes the MAC learning entry to a single VLAN,
which is the ordinary behavior for a VLAN-aware switch.
NXM_OF_ETH_DST[]=NXM_OF_ETH_SRC[]
Make the flow that we add to flow table 10 match, as Ethernet
destination, the Ethernet source address of the packet we're
currently processing.
load:NXM_OF_IN_PORT[]->NXM_NX_REG0[0..15]
Whereas the preceding parts specify fields for the new flow to
match, this specifies an action for the flow to take when it
matches. The action is for the flow to load the ingress port
number of the current packet into register 0 (a special field
that is an Open vSwitch extension to OpenFlow).
A real use of "learn" for MAC learning would probably involve two additional elements. First, the "learn" action would specify a hardtimeout for the new flow, to enable a learned MAC to eventually expire if no new packets were seen from a given source within a reasonable interval. Second, one would usually want to limit resource consumption by using the FlowTable table in the Open vSwitch configuration database to specify a maximum number of flows in table 10.
This definitely calls for examples.
Try the following test command:
ovs-appctl ofproto/trace br0 in_port=1,vlan_tci=20,dl_src=50:00:00:00:00:01 -generate
The output shows that "learn" was executed, but it isn't otherwise informative, so we won't include it here.
The -generate
keyword is new. Ordinarily, ofproto/trace
has no
side effects: "output" actions do not actually output packets, "learn"
actions do not actually modify the flow table, and so on. With
-generate
, though, ofproto/trace
does execute "learn" actions.
That's important now, because we want to see the effect of the "learn"
action on table 10. You can see that by running:
ovs-ofctl dump-flows br0 table=10
which (omitting the "duration" and "idle_age" fields, which will vary based on how soon you ran this command after the previous one, as well as some other uninteresting fields) prints something like:
NXST_FLOW reply (xid=0x4):
table=10, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
You can see that the packet coming in on VLAN 20 with source MAC 50:00:00:00:00:01 became a flow that matches VLAN 20 (written in hexadecimal) and destination MAC 50:00:00:00:00:01. The flow loads port number 1, the input port for the flow we tested, into register 0.
Here's a second test command:
ovs-appctl ofproto/trace br0 in_port=2,dl_src=50:00:00:00:00:01 -generate
The flow that this command tests has the same source MAC and VLAN as example 1, although the VLAN comes from an access port VLAN rather than an 802.1Q header. If we again dump the flows for table 10 with:
ovs-ofctl dump-flows br0 table=10
then we see that the flow we saw previously has changed to indicate that the learned port is port 2, as we would expect:
NXST_FLOW reply (xid=0x4):
table=10, vlan_tci=0x0014/0x0fff,dl_dst=50:00:00:00:00:01 actions=load:0x2->NXM_NX_REG0[0..15]
This table figures out what port we should send the packet to based on the destination MAC and VLAN. That is, if we've learned the location of the destination (from table 2 processing some previous packet with that destination as its source), then we want to send the packet there.
We need only one flow to do the lookup:
ovs-ofctl add-flow br0 \
"table=3 priority=50 actions=resubmit(,10), resubmit(,4)"
The flow's first action resubmits to table 10, the table that the "learn" action modifies. As you saw previously, the learned flows in this table write the learned port into register 0. If the destination for our packet hasn't been learned, then there will be no matching flow, and so the "resubmit" turns into a no-op. Because registers are initialized to 0, we can use a register 0 value of 0 in our next pipeline stage as a signal to flood the packet.
The second action resubmits to table 4, continuing to the next pipeline stage.
We can add another flow to skip the learning table lookup for multicast and broadcast packets, since those should always be flooded:
ovs-ofctl add-flow br0 \
"table=3 priority=99 dl_dst=01:00:00:00:00:00/01:00:00:00:00:00 \
actions=resubmit(,4)"
We don't strictly need to add this flow, because multicast addresses will never show up in our learning table. (In turn, that's because we put a flow into table 0 to drop packets that have a multicast source address.)
Here's a command that should cause OVS to learn that f0:00:00:00:00:01 is on p1 in VLAN 20:
ovs-appctl ofproto/trace br0 in_port=1,dl_vlan=20,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01 -generate
Here's an excerpt from the output that shows (from the "no match" looking up the resubmit to table 10) that the flow's destination was unknown:
Resubmitted flow: unchanged
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
Resubmitted odp: drop
Rule: table=3 cookie=0 priority=50
OpenFlow actions=resubmit(,10),resubmit(,4)
Resubmitted flow: unchanged
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
Resubmitted odp: drop
No match
You can verify that the packet's source was learned two ways. The most direct way is to dump the learning table with:
ovs-ofctl dump-flows br0 table=10
which ought to show roughly the following, with extraneous details removed:
table=10, vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01 actions=load:0x1->NXM_NX_REG0[0..15]
If you tried the examples for the previous step, or if you did some of your own experiments, then you might see additional flows there. These additional flows are harmless. If they bother you, then you can remove them with
ovs-ofctl del-flows br0 table=10
.
The other way is to inject a packet to take advantage of the learning entry. For example, we can inject a packet on p2 whose destination is the MAC address that we just learned on p1:
ovs-appctl ofproto/trace br0 in_port=2,dl_src=90:00:00:00:00:01,dl_dst=f0:00:00:00:00:01 -generate
Here's an interesting excerpt from that command's output. This group of lines traces the "resubmit(,10)", showing that the packet matched the learned flow for the first MAC we used, loading the OpenFlow port number for the learned port p1 into register 0:
Resubmitted flow: unchanged
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
Resubmitted odp: drop
Rule: table=10 cookie=0 vlan_tci=0x0014/0x0fff,dl_dst=f0:00:00:00:00:01
OpenFlow actions=load:0x1->NXM_NX_REG0[0..15]
If you read the commands above carefully, then you might have noticed
that they simply have the Ethernet source and destination addresses
exchanged. That means that if we now rerun the first ovs-appctl
command above, e.g.:
ovs-appctl ofproto/trace br0 in_port=1,dl_vlan=20,dl_src=f0:00:00:00:00:01,dl_dst=90:00:00:00:00:01 -generate
then we see in the output that the destination has now been learned:
Resubmitted flow: unchanged
Resubmitted regs: reg0=0x0 reg1=0x0 reg2=0x0 reg3=0x0 reg4=0x0 reg5=0x0 reg6=0x0 reg7=0x0
Resubmitted odp: drop
Rule: table=10 cookie=0 vlan_tci=0x0014/0x0fff,dl_dst=90:00:00:00:00:01
OpenFlow actions=load:0x2->NXM_NX_REG0[0..15]
At entry to stage 4, we know that register 0 contains either the desired output port or is zero if the packet should be flooded. We also know that the packet's VLAN is in its 802.1Q header, even if the VLAN was implicit because the packet came in on an access port.
The job of the final pipeline stage is to actually output packets. The job is trivial for output to our trunk port p1:
ovs-ofctl add-flow br0 "table=4 reg0=1 actions=1"
For output to the access ports, we just have to strip the VLAN header before outputting the packet:
ovs-ofctl add-flows br0 - <<'EOF'
table=4 reg0=2 actions=strip_vlan,2
table=4 reg0=3 actions=strip_vlan,3
table=4 reg0=4 actions=strip_vlan,4
EOF
The only slightly tricky part is flooding multicast and broadcast packets and unicast packets with unlearned destinations. For those, we need to make sure that we only output the packets to the ports that carry our packet's VLAN, and that we include the 802.1Q header in the copy output to the trunk port but not in copies output to access ports:
ovs-ofctl add-flows br0 - <<'EOF'
table=4 reg0=0 priority=99 dl_vlan=20 actions=1,strip_vlan,2
table=4 reg0=0 priority=99 dl_vlan=30 actions=1,strip_vlan,3,4
table=4 reg0=0 priority=50 actions=1
EOF
Our rules rely on the standard OpenFlow behavior that an output action will not forward a packet back out the port it came in on. That is, if a packet comes in on p1, and we've learned that the packet's destination MAC is also on p1, so that we end up with "actions=1" as our actions, the switch will not forward the packet back out its input port. The multicast/broadcast/unknown destination cases above also rely on this behavior.
Try tracing a broadcast packet arriving on p1 in VLAN 30:
ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=30
The interesting part of the output is the final line, which shows that the switch would remove the 802.1Q header and then output the packet to p3 and p4, which are access ports for VLAN 30:
Datapath actions: pop_vlan,3,4
Similarly, if we trace a broadcast packet arriving on p3:
ovs-appctl ofproto/trace br0 in_port=3,dl_dst=ff:ff:ff:ff:ff:ff
then we see that it is output to p1 with an 802.1Q tag and then to p4 without one:
Datapath actions: push_vlan(vid=30,pcp=0),1,pop_vlan,4
Open vSwitch could simplify the datapath actions here to just "4,push_vlan(vid=30,pcp=0),1" but it is not smart enough to do so.
The following are also broadcasts, but the result is to drop the packets because the VLAN only belongs to the input port:
ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff
ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=55
Try some other broadcast cases on your own:
ovs-appctl ofproto/trace br0 in_port=1,dl_dst=ff:ff:ff:ff:ff:ff,dl_vlan=20
ovs-appctl ofproto/trace br0 in_port=2,dl_dst=ff:ff:ff:ff:ff:ff
ovs-appctl ofproto/trace br0 in_port=4,dl_dst=ff:ff:ff:ff:ff:ff
You can see the same behavior with multicast packets and with unicast packets whose destination has not been learned, e.g.:
ovs-appctl ofproto/trace br0 in_port=4,dl_dst=01:00:00:00:00:00
ovs-appctl ofproto/trace br0 in_port=1,dl_dst=90:12:34:56:78:90,dl_vlan=20
ovs-appctl ofproto/trace br0 in_port=1,dl_dst=90:12:34:56:78:90,dl_vlan=30
Let's follow the same pattern as we did for table 3. First learn a MAC on port p1 in VLAN 30:
ovs-appctl ofproto/trace br0 in_port=1,dl_vlan=30,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01 -generate
You can see from the last line of output that the packet's destination is unknown, so it gets flooded to both p3 and p4, the other ports in VLAN 30:
Datapath actions: pop_vlan,3,4
Then reverse the MACs and learn the first flow's destination on port p4:
ovs-appctl ofproto/trace br0 in_port=4,dl_src=20:00:00:00:00:01,dl_dst=10:00:00:00:00:01 -generate
The last line of output shows that the this packet's destination is known to be p1, as learned from our previous command:
Datapath actions: push_vlan(vid=30,pcp=0),1
Now, if we rerun our first command:
ovs-appctl ofproto/trace br0 in_port=1,dl_vlan=30,dl_src=10:00:00:00:00:01,dl_dst=20:00:00:00:00:01 -generate
we can see that the result is no longer a flood but to the specified learned destination port p4:
Datapath actions: pop_vlan,4
<EMAIL_ADDRESS>http://openvswitch.org/


About Us
Originally created as a personal snack, our organic, sugar free, and high protein cookies became an instant sensation between friends and family. Our mission was to make the perfect confection to be paired with a cup of coffee in the morning. As a family owned and operated business, Pat's Salmon Cookies is deeply rooted in the community, giving back a portion of every cookie sold to the less fortunate. So enjoy this delcious and nutricious way to start your day, while making a difference in your community.


About imalogit.com.
Log stuff quickly.
Many things are logged. One one end, the majority of logging is automated and handled by other systems. On the other end, there's specialized logging that varies from personal journals to videos and pictures and so on.
Ima Log It is about common logging. In essence: logs with dated entries consisting of a number, a note, or both. You could do this in various ways: pen and paper, text file, spreadsheet, etc. These methods often work fine, but then you want more, but not too much.
You want access from your phone. You want instant charts. You want access without having too much navigation. You want to export. You want the more important stuff (the signal) to pop out, while the less important stuff (the noise) to fade out. You want a sense of time. You want to compare two logs.
And you want it all fast, simple, and easy.
The logo has several basic elements.
The simplest element is the cylindrical shape like that of log from a tree.
That wood log ties in to the second element: The logging of events during the voyage of a ship. A floating chip log with a rope with knots at regular intervals (i.e. a log-line) was used to estimate a ship's speed. The logo is the log-line reel with the knotted log-line peeling off of it.
The third elment is that the log-line peeling off is plotted like the logarithm base 2, where the knots are at the points (2, 1), (4, 2), and (8, 3).
The fourth element is that the logo is like a smoking cannibis joint, which became legal in Illinois 2020-01, when imalogit.com was registered.
The first choice was Loggit (Logg.it) as a play on "dammit", but the domain name was taken.
The name "Ima Log It" is essentially "I'm gonna log it" or "I'm going to log it", but short and casual.