class MocProjects(base.MocBaseApi): """ API Endpoint for applying, or listing accessible projects. """ url = r'^moc/Projects/?$' task_type = 'moc_create_project' config_group = config_groups.DynamicNameConfigGroup( children=[ config_fields.BoolConfig( 'create_default_network', help_text='If set to faulse, overrides what is in setup_network.', default=True, sample_default=True, ), config_fields.StrConfig( 'region', help_text='Region for creating default network and quota.', default='RegionOne', sample_default='RegionOne' ), config_fields.StrConfig( "project_domain_id", help_text="Domain id for projects.", default="default", sample_default="Default" ), ] ) @utils.authenticated def post(self, request, format=None): request.data['email'] = request.keystone_user['username'] request.data['region'] = self.config['region'] request.data['domain_id'] = self.config['project_domain_id'] if not self.config['create_default_network']: request.data['setup_network'] = False if 'project_name' not in request.data: message = 'Missing project_name in request.' self.logger.info(message) return self.response(message, 400) project = self.identity.find_project( request.data['project_name'], self.config.project_domain_id) if project: message = ('Project %s already exists.' % request.data['project_name']) self.logger.info(message) return self.response_error(message, 409) return self.create_task(request) @utils.authenticated def get(self, request, format=None): # List other projects that a user has access to, or has applied for. pass
class CreateProjectAndUser(BaseDelegateAPI): url = r"^actions/CreateProjectAndUser/?$" config_group = groups.DynamicNameConfigGroup( children=[ fields.StrConfig( "default_region", help_text="Default region in which any potential resources may be created.", required=True, default="RegionOne", ), fields.StrConfig( "default_domain_id", help_text="Domain in which project and users will be created.", default="default", required=True, ), fields.StrConfig( "default_parent_id", help_text="Parent id under which this project will be created. " "Default is None, and will create under default domain.", default=None, ), ] ) task_type = "create_project_and_user" def post(self, request, format=None): """ Unauthenticated endpoint bound primarily to NewProjectWithUser. This process requires approval, so this will validate incoming data and create a task to be approved later. """ self.logger.info("(%s) - Starting new project task." % timezone.now()) class_conf = self.config # we need to set the region the resources will be created in: request.data["region"] = class_conf.default_region # domain request.data["domain_id"] = class_conf.default_domain_id # parent_id for new project, if null defaults to domain: request.data["parent_id"] = class_conf.default_parent_id self.task_manager.create_from_request(self.task_type, request) return Response({"notes": ["task created"]}, status=202)
def _build_default_email_group( group_name, email_subject, email_from, email_reply, email_template, email_html_template, ): email_group = groups.ConfigGroup(group_name) email_group.register_child_config( fields.StrConfig( "subject", help_text="Default email subject for this stage", default=email_subject, )) email_group.register_child_config( fields.StrConfig("from", help_text="Default from email for this stage", default=email_from)) email_group.register_child_config( fields.StrConfig( "reply", help_text="Default reply-to email for this stage", default=email_reply, )) email_group.register_child_config( fields.StrConfig( "template", help_text="Default email template for this stage", default=email_template, )) email_group.register_child_config( fields.StrConfig( "html_template", help_text="Default email html template for this stage", default=email_html_template, )) return email_group
class MocInviteUserAction(base.MocBaseAction): required = [ 'email', 'project_id', 'roles', ] serializer = serializers.MocInviteUserSerializer config_group = config_groups.DynamicNameConfigGroup(children=[ config_fields.StrConfig("user_domain_id", help_text="Domain to create projects in.", default="default", sample_default="Default") ]) def _get_email(self): """This is the email where the invitation will be sent.""" return self.email def _prepare(self): if not self._validate(): self.add_note('Validation failed at _prepare') return self.action.auto_approve = True self.action.state = "pending" self.action.need_token = True self.set_token_fields(["confirm", "user"]) def validate_token(self, token_data): if not self.valid or not token_data.get('confirm'): self.add_note('Invitation not valid or not accepted.') return False return True def write_to_approve_journal(self): pass def write_to_submit_journal(self, token_data): project = self.leader_identity.get_project(self.project_id) project_ref = {'name': project.name, 'domain_id': project.domain_id} services = self.find_services_for_project(project) self.submit_journal.append( operations.AddUserToProjectOperation(services, token_data['user'], project_ref, self.roles))
class NewDefaultNetworkAction(BaseAction, ProjectMixin): """ This action will setup all required basic networking resources so that a new user can launch instances right away. """ required = [ "setup_network", "project_id", "region", ] serializer = serializers.NewDefaultNetworkSerializer config_group = groups.DynamicNameConfigGroup( children=[ groups.ConfigGroup( "region_defaults", children=[ fields.StrConfig( "network_name", help_text="Name to be given to the default network.", default="default_network", ), fields.StrConfig( "subnet_name", help_text="Name to be given to the default subnet.", default="default_subnet", ), fields.StrConfig( "router_name", help_text="Name to be given to the default router.", default="default_router", ), fields.StrConfig( "public_network", help_text="ID of the public network.", ), fields.StrConfig( "subnet_cidr", help_text="CIDR for the default subnet.", ), fields.ListConfig( "dns_nameservers", help_text="DNS nameservers for the subnet.", ), ], ), fields.DictConfig( "regions", help_text="Specific per region config for default network. " "See 'region_defaults'.", default={}, ), ] ) def __init__(self, *args, **kwargs): super(NewDefaultNetworkAction, self).__init__(*args, **kwargs) def _validate_region(self): if not self.region: self.add_note("ERROR: No region given.") return False id_manager = user_store.IdentityManager() region = id_manager.get_region(self.region) if not region: self.add_note("ERROR: Region does not exist.") return False self.add_note("Region: %s exists." % self.region) return True def _validate(self): self.action.valid = validate_steps( [ self._validate_region, self._validate_project_id, self._validate_keystone_user_project_id, ] ) self.action.save() def _create_network(self): neutron = openstack_clients.get_neutronclient(region=self.region) try: region_config = self.config.regions[self.region] network_config = self.config.region_defaults.overlay(region_config) except KeyError: network_config = self.config.region_defaults if not self.get_cache("network_id"): try: network_body = { "network": { "name": network_config.network_name, "tenant_id": self.project_id, "admin_state_up": True, } } network = neutron.create_network(body=network_body) except Exception as e: self.add_note( "Error: '%s' while creating network: %s" % (e, network_config.network_name) ) raise self.set_cache("network_id", network["network"]["id"]) self.add_note( "Network %s created for project %s" % (network_config.network_name, self.project_id) ) else: self.add_note( "Network %s already created for project %s" % (network_config.network_name, self.project_id) ) if not self.get_cache("subnet_id"): try: subnet_body = { "subnet": { "network_id": self.get_cache("network_id"), "ip_version": 4, "tenant_id": self.project_id, "dns_nameservers": network_config.dns_nameservers, "cidr": network_config.subnet_cidr, } } subnet = neutron.create_subnet(body=subnet_body) except Exception as e: self.add_note("Error: '%s' while creating subnet" % e) raise self.set_cache("subnet_id", subnet["subnet"]["id"]) self.add_note("Subnet created for network %s" % network_config.network_name) else: self.add_note( "Subnet already created for network %s" % network_config.network_name ) if not self.get_cache("router_id"): try: router_body = { "router": { "name": network_config.router_name, "external_gateway_info": { "network_id": network_config.public_network }, "tenant_id": self.project_id, "admin_state_up": True, } } router = neutron.create_router(body=router_body) except Exception as e: self.add_note( "Error: '%s' while creating router: %s" % (e, network_config.router_name) ) raise self.set_cache("router_id", router["router"]["id"]) self.add_note("Router created for project %s" % self.project_id) else: self.add_note("Router already created for project %s" % self.project_id) if not self.get_cache("port_id"): try: interface_body = {"subnet_id": self.get_cache("subnet_id")} interface = neutron.add_interface_router( self.get_cache("router_id"), body=interface_body ) except Exception as e: self.add_note("Error: '%s' while attaching interface" % e) raise self.set_cache("port_id", interface["port_id"]) self.add_note("Interface added to router for subnet") else: self.add_note("Interface added to router for project %s" % self.project_id) def _prepare(self): # Note: Do we need to get this from cache? it is a required setting # self.project_id = self.action.task.cache.get('project_id', None) self._validate() def _approve(self): self._validate() if self.setup_network and self.valid: self._create_network() def _submit(self, token_data, keystone_user=None): pass
class MailingListSubscribeAction(base.MocBaseAction): required = ['email'] serializer = serializers.MailingListSubscribeSerializer config_group = conf_group.DynamicNameConfigGroup(children=[ conf_field.StrConfig( "private_key", help_text="Location of private key for mailing list server.", default="/.ssh/id_rsa", sample_default="/.ssh/id_rsa", ), conf_field.HostNameConfig( "host", help_text="Mailing list server host.", default="mail.massopen.cloud", sample_default="mail.massopen.cloud", ), conf_field.IntConfig( "port", help_text="Mailing list server SSH port", default=22, sample_default=22, ), conf_field.StrConfig( "user", help_text="Mailing list server user.", default="moc-tools", sample_default="moc-tools", ), conf_field.StrConfig( "list", help_text="Mailing list to add users to.", default="kaizen-users", sample_default="kaizen-users", ), ], ) def _get_email(self): if CONF.identity.username_is_email: return self.action.task.keystone_user['username'] def _approve(self): try: with Mailman(self.config.host, self.config.port, self.config.user, self.config.private_key) as mailman: if mailman.is_already_subscribed(self._get_email(), self.config.list): self.add_note('%s already subscribed to mailing list.' % self._get_email()) else: mailman.subscribe(self._get_email(), self.config.list) self.add_note( '%s successfully subscribed to mailing list.' % self._get_email()) except paramiko.ssh_exception.SSHException as e: self.add_note('Unable to connect to Mailing List server. ' 'Proceeding regardless. %s' % str(e)) self.action.state = 'complete' self.action.save() def _submit(self, token_data): pass
class EmailNotification(base.BaseNotificationHandler): """ Basic email notification handler. Will send an email with the given templates. """ config_group = groups.DynamicNameConfigGroup(children=[ fields.ListConfig( "emails", help_text="List of email addresses to send this notification to.", item_type=types.String(regex=constants.EMAIL_REGEX), default=[], ), fields.StrConfig( "from", help_text="From email for this notification.", regex=constants.EMAIL_WITH_TEMPLATE_REGEX, sample_default="bounce+%(task_uuid)[email protected]", ), fields.StrConfig( "reply", help_text="Reply-to email for this notification.", regex=constants.EMAIL_REGEX, sample_default="*****@*****.**", ), fields.StrConfig( "template", help_text="Email template for this notification. " "No template will cause the email not to send.", default="notification.txt", ), fields.StrConfig( "html_template", help_text="Email html template for this notification.", ), ]) def _notify(self, task, notification): conf = self.config(task, notification) if not conf or not conf["emails"]: # Log that we did this!! note = ("Skipped sending notification for task: %s (%s) " "as notification handler conf is None, or no emails " "were configured." % (task.task_type, task.uuid)) self.logger.info("(%s) - %s" % (timezone.now(), note)) return template = loader.get_template(conf["template"], using="include_etc_templates") html_template = conf["html_template"] if html_template: html_template = loader.get_template(html_template, using="include_etc_templates") context = {"task": task, "notification": notification} if CONF.workflow.horizon_url: task_url = CONF.workflow.horizon_url notification_url = CONF.workflow.horizon_url if not task_url.endswith("/"): task_url += "/" if not notification_url.endswith("/"): notification_url += "/" task_url += "management/tasks/%s" % task.uuid notification_url += "management/notifications/%s" % notification.uuid context["task_url"] = task_url context["notification_url"] = notification_url if notification.error: subject = "Error - %s notification" % task.task_type else: subject = "%s notification" % task.task_type try: message = template.render(context) # from_email is the return-path and is distinct from the # message headers from_email = conf["from"] if not from_email: from_email = conf["reply"] elif "%(task_uuid)s" in from_email: from_email = from_email % {"task_uuid": task.uuid} # these are the message headers which will be visible to # the email client. headers = { "X-Adjutant-Task-UUID": task.uuid, # From needs to be set to be disctinct from return-path "From": conf["reply"], "Reply-To": conf["reply"], } email = EmailMultiAlternatives(subject, message, from_email, conf["emails"], headers=headers) if html_template: email.attach_alternative(html_template.render(context), "text/html") email.send(fail_silently=False) notification.acknowledged = True notification.save() except SMTPException as e: notes = { "errors": [("Error: '%s' while sending email notification") % e] } error_notification = Notification.objects.create( task=notification.task, notes=notes, error=True) error_notification.save()
def _build_default_email_group(group_name): email_group = groups.ConfigGroup(group_name) email_group.register_child_config( fields.StrConfig( "subject", help_text="Email subject for this stage.", default="Openstack Email Notification", )) email_group.register_child_config( fields.StrConfig( "from", help_text="From email for this stage.", regex=constants.EMAIL_WITH_TEMPLATE_REGEX, default="bounce+%(task_uuid)[email protected]", )) email_group.register_child_config( fields.StrConfig( "reply", help_text="Reply-to email for this stage.", regex=constants.EMAIL_WITH_TEMPLATE_REGEX, default="*****@*****.**", )) email_group.register_child_config( fields.StrConfig( "template", help_text="Email template for this stage. " "No template will cause the email not to send.", default=None, )) email_group.register_child_config( fields.StrConfig( "html_template", help_text="Email html template for this stage. " "No template will cause the email not to send.", default=None, )) email_group.register_child_config( fields.BoolConfig( "email_current_user", help_text="Email the user who started the task.", default=False, )) email_group.register_child_config( fields.BoolConfig( "email_task_cache", help_text="Send to an email set in the task cache.", default=False, )) email_group.register_child_config( fields.ListConfig( "email_roles", help_text="Send emails to the given roles on the project.", default=[], )) email_group.register_child_config( fields.ListConfig( "email_additional_addresses", help_text="Send emails to an arbitrary admin emails", item_type=types.String(regex=constants.EMAIL_WITH_TEMPLATE_REGEX), default=[], )) return email_group
# Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from confspirator import groups from confspirator import fields config_group = groups.ConfigGroup("django") config_group.register_child_config( fields.StrConfig( "secret_key", help_text="The Django secret key.", required=True, default="Do not ever use this awful secret in prod!!!!", secret=True, unsafe_default=True, )) config_group.register_child_config( fields.BoolConfig( "debug", help_text="Django debug mode is turned on.", default=False, unsafe_default=True, )) config_group.register_child_config( fields.ListConfig( "allowed_hosts", help_text="The Django allowed hosts", required=True,
"project_admin": [ "project_mod", "member", "heat_stack_owner", "project_admin", ], "project_mod": ["member", "heat_stack_owner", "project_mod"], }, ) ) _auth_group = groups.ConfigGroup("auth") _auth_group.register_child_config( fields.StrConfig( "username", help_text="Username for Adjutant Keystone admin user.", required=True, required_for_tests=False, ) ) _auth_group.register_child_config( fields.StrConfig( "password", help_text="Password for Adjutant Keystone admin user.", required=True, secret=True, required_for_tests=False, ) ) _auth_group.register_child_config( fields.StrConfig( "project_name",