def load_builtin_scripts(): for script in BUILTIN_SCRIPTS: if script.inject_file: with open(script.inject_path, "r") as f: script.substitutes["inject_file"] = f.read() script_content = tempita.Template.from_filename( script.script_path, encoding="utf-8" ) script_content = script_content.substitute( {"name": script.name, **script.substitutes} ) try: script_in_db = Script.objects.get(name=script.name) except Script.DoesNotExist: form = ScriptForm( data={ "script": script_content, "comment": "Created by maas-%s" % get_running_version(), } ) # Form validation should never fail as these are the scripts which # ship with MAAS. If they ever do this will be cause by unit tests. if not form.is_valid(): raise Exception("%s: %s" % (script.name, form.errors)) script_in_db = form.save(commit=False) script_in_db.default = True script_in_db.save() else: if script_in_db.script.data != script_content: # Don't add back old versions of a script. This prevents two # connected regions with different versions of a script from # fighting with eachother. no_update = False for vtf in script_in_db.script.previous_versions(): if vtf.data == script_content: # Don't update anything if we detect we have an old # version of the builtin scripts no_update = True break if no_update: continue form = ScriptForm( instance=script_in_db, data={ "script": script_content, "comment": "Updated by maas-%s" % get_running_version(), }, edit_default=True, ) # Form validation should never fail as these are the scripts # which ship with MAAS. If they ever do this will be cause by # unit tests. if not form.is_valid(): raise Exception("%s: %s" % (script.name, form.errors)) script_in_db = form.save(commit=False) script_in_db.default = True script_in_db.save()
def test_uses_snappy_get_snap_version(self): self.patch(snappy, "running_in_snap").return_value = True self.patch(snappy, "get_snap_version").return_value = "2.10.0-456-g.deadbeef" maas_version = get_running_version() self.assertEqual(maas_version.short_version, "2.10.0") self.assertEqual(maas_version.extended_info, "456-g.deadbeef")
def register( self, system_id, hostname, interfaces, url, nodegroup_uuid=None, beacon_support=False, version=None, ): # Hold off on fabric creation if the remote controller # supports beacons; it will happen later when UpdateInterfaces is # called. create_fabrics = False if beacon_support else True result = yield self._register( system_id, hostname, interfaces, url, nodegroup_uuid=nodegroup_uuid, create_fabrics=create_fabrics, version=version, ) if beacon_support: # The remote supports beaconing, so acknowledge that. result["beacon_support"] = True if version: # The remote supports version checking, so reply to that. result["version"] = str(get_running_version()) return result
def test_method_is_cached(self): self.patch(snap, "running_in_snap").return_value = True mock_get_snap_versions = self.patch(snap, "get_snap_version") mock_get_snap_versions.return_value = snap.SnapVersion( version="2.10.0-456-g.deadbeef", revision="1234", ) version.get_running_version.cache_clear() first_return_value = version.get_running_version() second_return_value = version.get_running_version() # The return value is not empty (full unit tests have been performed # earlier). self.assertNotIn(first_return_value, [b"", "", None]) self.assertEqual(first_return_value, second_return_value) mock_get_snap_versions.assert_called_once()
def register( self, system_id, hostname, interfaces, url, nodegroup_uuid=None, beacon_support=False, version=None, ): result = yield self._register( system_id, hostname, interfaces, url, nodegroup_uuid=nodegroup_uuid, version=version, ) if beacon_support: # The remote supports beaconing, so acknowledge that. result["beacon_support"] = True if version: # The remote supports version checking, so reply to that. result["version"] = str(get_running_version()) return result
def test_uses_get_deb_versions_info(self): self.patch(version.deb, "get_deb_versions_info").return_value = deb.DebVersionsInfo( current=deb.DebVersion( version="2.10.0-456-g.deadbeef-0ubuntu1", )) maas_version = get_running_version() self.assertEqual(maas_version.short_version, "2.10.0") self.assertEqual(maas_version.extended_info, "456-g.deadbeef")
def test_uses_version_from_python(self): self.patch(version, "_get_version_from_apt").return_value = None self.patch(version, "DISTRIBUTION").parsed_version = parse_version("2.10.0b1") self.patch(version, "_get_maas_repo_hash").return_value = None maas_version = get_running_version() self.assertEqual(maas_version.short_version, "2.10.0~beta1") self.assertEqual(maas_version.extended_info, "")
def notification_available(notification_version): current_version = version.get_running_version() notification_version = version.MAASVersion.from_string( notification_version ) log.debug(f"Current MAAS version: {current_version}") log.debug(f"Notification version: {notification_version}") return notification_version > current_version
def test_method_is_cached(self): mock_apt = self.patch(version, "_get_version_from_apt") mock_apt.return_value = "1.8.0~alpha4+bzr356-0ubuntu1" version.get_running_version.cache_clear() first_return_value = version.get_running_version() second_return_value = version.get_running_version() # The return value is not empty (full unit tests have been performed # earlier). self.assertNotIn(first_return_value, [b"", "", None]) self.assertEqual(first_return_value, second_return_value) # Apt has only been called once. self.expectThat( mock_apt, MockCalledOnceWith(version.RACK_PACKAGE_NAME, version.REGION_PACKAGE_NAME), )
def get_maas_user_agent(): from maasserver.models import Config version = get_running_version() user_agent = f"maas/{version.short_version}/{version.extended_info}" uuid = Config.objects.get_config("uuid") if uuid: user_agent += f"/{uuid}" return user_agent
def inner_start_up(master=False): """Startup jobs that must run serialized w.r.t. other starting servers.""" # Register our MAC data type with psycopg. register_mac_type(connection.cursor()) # All commissioning and testing scripts are stored in the database. For # a commissioning ScriptSet to be created Scripts must exist first. Call # this early, only on the master process, to ensure they exist and are # only created once. If get_or_create_running_controller() is called before # this it will fail on first run. if master: load_builtin_scripts() # Ensure the this region is represented in the database. The first regiond # to pass through inner_start_up on this host can do this; it should NOT # be restricted to masters only. This also ensures that the MAAS ID is set # on the filesystem; it will be done in a post-commit hook and will thus # happen before `locks.startup` is released. node = RegionController.objects.get_or_create_running_controller() # Update region version ControllerInfo.objects.set_version(node, get_running_version()) # Ensure that uuid is created after creating RegionController.objects.get_or_create_uuid() # Only perform the following if the master process for the # region controller. if master: # Freshen the kms SRV records. dns_kms_setting_changed() # Make sure the commissioning distro series is still a supported LTS. commissioning_distro_series = Config.objects.get_config( name="commissioning_distro_series" ) ubuntu = UbuntuOS() if commissioning_distro_series not in ( ubuntu.get_supported_commissioning_releases() ): Config.objects.set_config( "commissioning_distro_series", ubuntu.get_default_commissioning_release(), ) Notification.objects.create_info_for_admins( "Ubuntu %s is no longer a supported commissioning " "series. Ubuntu %s has been automatically selected." % ( commissioning_distro_series, ubuntu.get_default_commissioning_release(), ), ident="commissioning_release_deprecated", ) with RegionConfiguration.open() as config: Config.objects.set_config("maas_url", config.maas_url) # Update deprecation notifications if needed sync_deprecation_notifications()
def test_uses_version_from_python_with_git_info(self): self.patch(version, "_get_version_from_apt").return_value = None self.patch(version, "DISTRIBUTION").parsed_version = parse_version("2.10.0b1") self.patch(version, "_get_maas_repo_commit_count").return_value = 1234 self.patch(version, "_get_maas_repo_hash").return_value = "deadbeef" maas_version = get_running_version() self.assertEqual(maas_version.short_version, "2.10.0~beta1") self.assertEqual(maas_version.extended_info, "1234-g.deadbeef")
def test_calls__get_version_from_apt(self): mock_apt = self.patch(version, "_get_version_from_apt") mock_apt.return_value = "2.10.0-456-g.deadbeef-0ubuntu1" maas_version = get_running_version() self.assertEqual(maas_version.short_version, "2.10.0") self.assertEqual(maas_version.extended_info, "456-g.deadbeef") self.expectThat( mock_apt, MockCalledOnceWith(version.RACK_PACKAGE_NAME, version.REGION_PACKAGE_NAME), )
def test_update_script(self): load_builtin_scripts() update_script_values = random.choice(BUILTIN_SCRIPTS) script = Script.objects.get(name=update_script_values.name) # Fields which we can update orig_title = script.title orig_description = script.description orig_script_type = script.script_type orig_results = script.results orig_parameters = script.parameters script.title = factory.make_string() script.description = factory.make_string() script.script_type = factory.pick_choice(SCRIPT_TYPE_CHOICES) script.results = [factory.make_name("result")] script.script.parameters = { factory.make_name("param"): { "type": "storage" } } # Put fake old data in to simulate updating a script. old_script = VersionedTextFile.objects.create( data=factory.make_string()) script.script = old_script # User changeable fields. user_tags = [factory.make_name("tag") for _ in range(3)] script.tags = copy.deepcopy(user_tags) user_timeout = timedelta(random.randint(0, 1000)) script.timeout = user_timeout script.save() load_builtin_scripts() script = reload_object(script) self.assertEqual(orig_title, script.title, script.name) self.assertEqual(orig_description, script.description, script.name) self.assertEqual(orig_script_type, script.script_type, script.name) self.assertDictEqual(orig_results, script.results, script.name) self.assertDictEqual(orig_parameters, script.parameters, script.name) self.assertThat(script.tags, ContainsAll(user_tags)) self.assertEqual(user_timeout, script.timeout) self.assertEqual(old_script, script.script.previous_version) self.assertEqual("Updated by maas-%s" % get_running_version(), script.script.comment) self.assertTrue(script.default)
def test_register_acks_version(self): yield self.installFakeRegion() rack_controller = yield deferToDatabase(factory.make_RackController) protocol = self.make_Region() protocol.transport = MagicMock() response = yield call_responder( protocol, RegisterRackController, { "system_id": rack_controller.system_id, "hostname": rack_controller.hostname, "interfaces": {}, "version": "2.3.0", }, ) self.assertEqual(response["version"], str(get_running_version()))
def read(self, request): """@description-title MAAS version information @description Read version and capabilities of this MAAS instance. @success (http-status-code) "server-success" 200 @success (json) "success-json" A JSON object containing MAAS version and capabilities information. @success-example "success-json" [exkey=version] placeholder text """ version = get_running_version() version_info = { "capabilities": API_CAPABILITIES_LIST, "version": version.short_version, "subversion": version.extended_info, } return HttpResponse( json.dumps(version_info), content_type="application/json; charset=utf-8", status=int(http.client.OK), )
def test_creates_scripts(self): load_builtin_scripts() for script in BUILTIN_SCRIPTS: script_in_db = Script.objects.get(name=script.name) # While MAAS allows user scripts to leave these fields blank, # builtin scripts should always have values. self.assertTrue(script_in_db.title, script.name) self.assertTrue(script_in_db.description, script.name) self.assertTrue(script_in_db.script.data, script.name) self.assertThat(script_in_db.tags, Not(Equals([])), script.name) # These values should always be set by the script loader. self.assertEqual( "Created by maas-%s" % get_running_version(), script_in_db.script.comment, script.name, ) self.assertTrue(script_in_db.default, script.name)
def test_updates_version(self): with post_commit_hooks: start_up.inner_start_up() region = RegionController.objects.first() self.assertEqual(region.version, str(get_running_version()))
def version(self, params): """Return the MAAS version.""" version = get_running_version() if version.extended_info: return f"{version.short_version} ({version.extended_info})" return version.short_version
def test_update_doesnt_revert_script(self): load_builtin_scripts() update_script_index = random.randint(0, len(BUILTIN_SCRIPTS) - 2) update_script_values = BUILTIN_SCRIPTS[update_script_index] script = Script.objects.get(name=update_script_values.name) # Put fake new data in to simulate another MAAS region updating # to a newer version. new_script = factory.make_string() script.script = script.script.update(new_script) # Fake user updates user_tags = [factory.make_name("tag") for _ in range(3)] script.tags = user_tags user_timeout = timedelta(random.randint(0, 1000)) script.timeout = user_timeout script.save() # Test that subsequent scripts still get updated second_update_script_values = BUILTIN_SCRIPTS[update_script_index + 1] second_script = Script.objects.get( name=second_update_script_values.name) # Put fake old data in to simulate updating a script. orig_title = second_script.title orig_description = second_script.description orig_script_type = second_script.script_type orig_results = second_script.results orig_parameters = second_script.parameters second_script.title = factory.make_string() second_script.description = factory.make_string() second_script.script_type = factory.pick_choice(SCRIPT_TYPE_CHOICES) second_script.results = [factory.make_name("result")] second_script.script.parameters = { factory.make_name("param"): { "type": "storage" } } # Put fake old data in to simulate updating a script. old_script = VersionedTextFile.objects.create( data=factory.make_string()) second_script.script = old_script second_script.save() load_builtin_scripts() script = reload_object(script) self.assertEqual(update_script_values.name, script.name) self.assertEqual(new_script, script.script.data) self.assertTrue(min([tag in script.tags for tag in user_tags])) self.assertEqual(user_timeout, script.timeout) self.assertTrue(script.default) second_script = reload_object(second_script) self.assertEqual(orig_title, second_script.title) self.assertEqual(orig_description, second_script.description) self.assertEqual(orig_script_type, second_script.script_type) self.assertDictEqual(orig_results, second_script.results) self.assertDictEqual(orig_parameters, second_script.parameters) self.assertEqual(old_script, second_script.script.previous_version) self.assertEqual( "Updated by maas-%s" % get_running_version(), second_script.script.comment, ) self.assertTrue(second_script.default)